1222 lines
30 KiB
CSS
1222 lines
30 KiB
CSS
body {
|
||
font-family: Arial, sans-serif;
|
||
background: #0d0d0f;
|
||
color: white;
|
||
margin: 0;
|
||
/* remove centering - use new app layout */
|
||
}
|
||
|
||
/* App wrapper: sidebar + content */
|
||
.app-wrapper {
|
||
display: flex;
|
||
height: 100vh;
|
||
width: 100%;
|
||
}
|
||
|
||
/* Sidebar */
|
||
.sidebar {
|
||
width: 220px;
|
||
background: #111;
|
||
border-right: 1px solid #222;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
padding: 16px 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.sidebar .logo {
|
||
/* center the textual logo horizontally */
|
||
display: block;
|
||
width: 100%;
|
||
text-align: center;
|
||
margin-bottom: 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.logo-text {
|
||
font-weight: 700;
|
||
font-size: 18px;
|
||
color: #ddd; /* neutral label color */
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
letter-spacing: 0.2px;
|
||
}
|
||
|
||
/* base part (left) stays neutral */
|
||
.logo-base {
|
||
color: #ddd;
|
||
text-transform: none;
|
||
}
|
||
|
||
/* highlight the "hub" part in an orange pill (Pornhub-like) */
|
||
.logo-highlight {
|
||
background: linear-gradient(180deg,#ffb347,#ff8c00);
|
||
color: #000;
|
||
padding: 4px 6px;
|
||
border-radius: 6px;
|
||
font-weight: 800;
|
||
font-size: 16px;
|
||
line-height: 1;
|
||
box-shadow: 0 2px 6px rgba(0,0,0,0.25), inset 0 -1px 0 rgba(255,255,255,0.06);
|
||
}
|
||
|
||
/* remove unused logo-img rule if present (ensure it doesn't show if left over) */
|
||
.logo-img {
|
||
display: none !important;
|
||
}
|
||
|
||
/* Tabs in sidebar */
|
||
.tabs {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
.tab-button {
|
||
background: transparent;
|
||
color: #ddd;
|
||
border: none;
|
||
text-align: left;
|
||
padding: 10px 12px;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
transition: background 0.15s, color 0.15s;
|
||
}
|
||
|
||
.tab-button:hover {
|
||
background: #1a1a1a;
|
||
color: #fff;
|
||
}
|
||
|
||
.tab-button.active {
|
||
background: #007bff;
|
||
color: #fff;
|
||
}
|
||
|
||
/* Sidebar bottom (settings) */
|
||
.sidebar-bottom {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding-top: 12px;
|
||
}
|
||
|
||
.settings-btn {
|
||
width: 100%;
|
||
background: #222;
|
||
color: #ddd;
|
||
border: 1px solid #2b2b2b;
|
||
padding: 8px;
|
||
border-radius: 10px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.settings-btn:hover {
|
||
background: #007bff;
|
||
color: #fff;
|
||
}
|
||
|
||
/* Content area */
|
||
.content-area {
|
||
flex: 1;
|
||
padding: 20px;
|
||
overflow: auto;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* Settings overlay (full-screen backdrop) */
|
||
.settings-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(0,0,0,0.6);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 1000;
|
||
padding: 24px;
|
||
box-sizing: border-box;
|
||
visibility: hidden;
|
||
opacity: 0;
|
||
transition: opacity 0.18s ease, visibility 0.18s;
|
||
}
|
||
|
||
/* visible when aria-hidden is false */
|
||
.settings-overlay[aria-hidden="false"] {
|
||
visibility: visible;
|
||
opacity: 1;
|
||
|
||
/* subtle stronger backdrop and blur */
|
||
background: rgba(0,0,0,0.45);
|
||
backdrop-filter: blur(6px);
|
||
-webkit-backdrop-filter: blur(6px);
|
||
}
|
||
|
||
/* Centered settings window */
|
||
.settings-window {
|
||
width: 720px;
|
||
max-width: 100%;
|
||
background: #151515;
|
||
border-radius: 12px;
|
||
box-shadow: 0 8px 30px rgba(0,0,0,0.6);
|
||
overflow: hidden;
|
||
color: #eee;
|
||
}
|
||
|
||
/* Topbar with tabs — title on first row, tabs on second row, close button on right spanning both */
|
||
.settings-topbar {
|
||
display: grid;
|
||
grid-template-columns: 1fr auto;
|
||
grid-template-rows: auto auto;
|
||
grid-template-areas:
|
||
"title close"
|
||
"tabs close";
|
||
gap: 8px;
|
||
padding: 12px 16px;
|
||
background: linear-gradient(90deg,#111,#181818);
|
||
border-bottom: 1px solid #222;
|
||
box-sizing: border-box;
|
||
align-items: center;
|
||
}
|
||
|
||
.settings-title {
|
||
grid-area: title;
|
||
font-weight: 600;
|
||
font-size: 16px;
|
||
margin: 0;
|
||
justify-self: start;
|
||
}
|
||
|
||
.settings-close {
|
||
grid-area: close;
|
||
justify-self: end;
|
||
align-self: center;
|
||
background: transparent;
|
||
border: none;
|
||
color: #bbb;
|
||
font-size: 18px;
|
||
cursor: pointer;
|
||
padding: 6px;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.settings-close:hover {
|
||
color: #fff;
|
||
background: rgba(255,255,255,0.03);
|
||
}
|
||
|
||
.settings-tabs {
|
||
grid-area: tabs;
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: center;
|
||
justify-content: flex-start; /* tabs aligned under the title */
|
||
padding-top: 4px;
|
||
width: 100%;
|
||
}
|
||
|
||
/* Tabs row in topbar */
|
||
.settings-tabs {
|
||
display: flex;
|
||
gap: 8px;
|
||
flex: 1 1 auto;
|
||
align-items: center;
|
||
}
|
||
|
||
.settings-tab-button {
|
||
background: transparent;
|
||
border: none;
|
||
color: #cfcfcf;
|
||
padding: 8px 12px;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.settings-tab-button:hover {
|
||
background: rgba(255,255,255,0.03);
|
||
color: #fff;
|
||
}
|
||
|
||
.settings-tab-button.active {
|
||
background: #007bff;
|
||
color: white;
|
||
}
|
||
|
||
/* Content area below topbar */
|
||
.settings-content {
|
||
padding: 18px 20px;
|
||
max-height: 60vh;
|
||
overflow: auto;
|
||
box-sizing: border-box;
|
||
background: linear-gradient(180deg,#101010,#0b0b0b);
|
||
}
|
||
|
||
/* Tab content panels: hide by default, show when active */
|
||
.tab-content {
|
||
display: none;
|
||
}
|
||
|
||
.tab-content.active {
|
||
display: block;
|
||
}
|
||
|
||
/* Settings tab content panels: hide by default, show when active */
|
||
.settings-tab-content {
|
||
display: none;
|
||
}
|
||
|
||
.settings-tab-content.active {
|
||
display: block;
|
||
}
|
||
|
||
/* Keep main-layout styling but adapt to content area */
|
||
.main-layout {
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
align-items: flex-start;
|
||
width: 100%;
|
||
gap: 40px;
|
||
margin-top: 0;
|
||
}
|
||
|
||
/* existing rules for container, input, tags, sliders keep working */
|
||
/* replace fixed-width container with flexible collapse-safe rules */
|
||
.container {
|
||
/* used to be width: 400px; margin: 0; */
|
||
flex: 0 0 auto;
|
||
width: auto;
|
||
min-width: 0; /* allow shrinking inside flex container */
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
/* hide empty container so it doesn't create blank space on the left */
|
||
.container:empty {
|
||
display: none;
|
||
}
|
||
|
||
/* Limit widths for tag areas so they don't force layout width */
|
||
#tag-container,
|
||
.tag-container,
|
||
#tag-container-slider0,
|
||
#tag-container-slider1,
|
||
#tag-container-slider2 {
|
||
max-width: 100%;
|
||
box-sizing: border-box;
|
||
|
||
/* allow tags to wrap onto multiple lines and enable vertical growth */
|
||
display: flex;
|
||
flex-wrap: wrap; /* enforce wrapping for all tag containers */
|
||
|
||
/* set column and row gaps explicitly: smaller row-gap to pack rows tighter */
|
||
gap: 8px 6px; /* column-gap: 8px; row-gap: 6px (format: column row in some engines) */
|
||
column-gap: 8px;
|
||
row-gap: 6px;
|
||
|
||
justify-content: flex-start;
|
||
|
||
/* prevent flex items (tags) from stretching vertically */
|
||
align-items: flex-start;
|
||
|
||
/* pack tag rows to the top instead of stretching them across the container */
|
||
align-content: flex-start;
|
||
|
||
/* allow the container to grow vertically but cap it and enable scrolling */
|
||
height: auto;
|
||
min-height: 480px;
|
||
max-height: 480px;
|
||
overflow-y: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
}
|
||
|
||
/* small input style for per-slider inputs - keep them from expanding too wide */
|
||
.tag-input,
|
||
.slider-tag-generator .tag-input {
|
||
max-width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* allow tags to show full text (no truncation) and keep them inline */
|
||
.tag {
|
||
/* don't force a max-width here so full tag text can be scrolled into view */
|
||
white-space: nowrap;
|
||
overflow: visible;
|
||
text-overflow: clip;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
|
||
/* ensure tag items keep natural size and don't stretch inside .tag-container */
|
||
flex: 0 0 auto;
|
||
align-self: flex-start;
|
||
|
||
/* make tags more compact: reduce vertical padding and line-height */
|
||
padding: 6px 10px; /* was 8px 12px */
|
||
line-height: 1;
|
||
font-size: 13px; /* optional: slightly smaller to fit more per row */
|
||
}
|
||
|
||
/* Update global / per-slider tag-container styling to match wrapping behavior */
|
||
.tag-container {
|
||
margin-top: 10px;
|
||
/* layout changed above; keep borders/visuals */
|
||
border: 2px solid #444;
|
||
padding: 10px;
|
||
border-radius: 8px;
|
||
background: #333;
|
||
min-height: 480px; /* <-- ensure consistent minimum */
|
||
max-height: 480px; /* <-- keep consistent cap */
|
||
box-sizing: border-box;
|
||
|
||
/* ensure vertical wrapping behavior */
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 5px;
|
||
justify-content: flex-start;
|
||
overflow-y: auto;
|
||
}
|
||
|
||
/* ensure visible scrollbars for horizontal scrolling where supported */
|
||
#tag-container::-webkit-scrollbar,
|
||
.tag-container::-webkit-scrollbar,
|
||
#tag-container-slider0::-webkit-scrollbar,
|
||
#tag-container-slider1::-webkit-scrollbar,
|
||
#tag-container-slider2::-webkit-scrollbar {
|
||
height: 8px; /* horizontal scrollbar height */
|
||
background-color: #2f2f2f;
|
||
}
|
||
|
||
#tag-container::-webkit-scrollbar-thumb,
|
||
.tag-container::-webkit-scrollbar-thumb,
|
||
#tag-container-slider0::-webkit-scrollbar-thumb,
|
||
#tag-container-slider1::-webkit-scrollbar-thumb,
|
||
#tag-container-slider2::-webkit-scrollbar-thumb {
|
||
background-color: #808080;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
#tag-container::-webkit-scrollbar-thumb:hover,
|
||
.tag-container::-webkit-scrollbar-thumb:hover,
|
||
#tag-container-slider0::-webkit-scrollbar-thumb:hover,
|
||
#tag-container-slider1::-webkit-scrollbar-thumb:hover,
|
||
#tag-container-slider2::-webkit-scrollbar-thumb:hover {
|
||
background-color: rgba(255,255,255,0.2);
|
||
}
|
||
|
||
/* Input Field Styling */
|
||
.input-container {
|
||
border: 2px solid #444;
|
||
padding: 10px;
|
||
border-radius: 8px;
|
||
background: #333;
|
||
}
|
||
|
||
#tag-input {
|
||
border: none;
|
||
outline: none;
|
||
background: none;
|
||
color: white;
|
||
font-size: 16px;
|
||
width: 100%;
|
||
}
|
||
|
||
/* Tag Display Container (main/global) */
|
||
#tag-container {
|
||
margin-top: 10px;
|
||
display: flex;
|
||
flex-wrap: wrap; /* ensure tags can wrap */
|
||
gap: 5px;
|
||
justify-content: flex-start;
|
||
border: 2px solid #444;
|
||
padding: 10px;
|
||
border-radius: 8px;
|
||
background: #333;
|
||
min-height: 480px; /* <-- ensure consistent minimum */
|
||
max-height: 480px; /* <-- keep consistent cap */
|
||
overflow-y: auto;
|
||
}
|
||
|
||
#tag-container::-webkit-scrollbar {
|
||
width: 8px;
|
||
background-color: #2f2f2f; /* Visible scrollbar bar */
|
||
}
|
||
|
||
#tag-container::-webkit-scrollbar-thumb {
|
||
background-color: #808080; /* Transparent scrollbar thumb */
|
||
border-radius: 4px;
|
||
}
|
||
|
||
#tag-container::-webkit-scrollbar-thumb:hover {
|
||
background-color: rgba(255, 255, 255, 0.2); /* Slightly visible on hover */
|
||
}
|
||
|
||
/* Dynamic Tag Styling */
|
||
.tag {
|
||
background: #007bff;
|
||
color: white;
|
||
padding: 8px 12px;
|
||
border-radius: 15px;
|
||
display: flex;
|
||
align-items: center;
|
||
transition: all 0.2s ease-in-out;
|
||
}
|
||
|
||
/* Adjust container height dynamically */
|
||
#tag-container:empty {
|
||
padding: 0;
|
||
border: none;
|
||
}
|
||
|
||
.remove-tag {
|
||
cursor: pointer;
|
||
margin-right: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
font-weight: bold;
|
||
color: inherit;
|
||
transition: color 120ms ease;
|
||
}
|
||
|
||
/* separator drawn by CSS so we control spacing precisely.
|
||
Give it a fixed neutral color so it does NOT change when the tag is hovered. */
|
||
.remove-tag::after {
|
||
content: " |";
|
||
margin-left: 6px;
|
||
color: rgba(255,255,255,0.65); /* neutral separator color */
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* when hovering the whole tag, make only the X red (separator keeps its own color) */
|
||
.tag:hover .remove-tag {
|
||
color: #ff5252; /* vivid red for the "×" only */
|
||
}
|
||
|
||
/* ensure remove-tag uses a smooth color transition and the separator keeps a neutral color */
|
||
.remove-tag {
|
||
cursor: pointer;
|
||
margin-right: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
font-weight: bold;
|
||
color: inherit;
|
||
transition: color 120ms ease;
|
||
}
|
||
|
||
/* separator drawn by CSS so we control spacing precisely.
|
||
Give it a fixed neutral color so it does NOT change when the tag is hovered. */
|
||
.remove-tag::after {
|
||
content: " |";
|
||
margin-left: 6px;
|
||
color: rgba(255,255,255,0.65); /* neutral separator color */
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* when hovering the whole tag, make only the X red (separator keeps its own color) */
|
||
.tag:hover .remove-tag {
|
||
color: #ff5252; /* vivid red for the "×" only */
|
||
}
|
||
|
||
/* Sidebar Styling */
|
||
.sliders-panel {
|
||
width: auto;
|
||
height: auto;
|
||
background: none;
|
||
box-shadow: none;
|
||
display: flex;
|
||
flex-direction: row; /* <-- Change to row for horizontal layout */
|
||
align-items: flex-start; /* align groups to top */
|
||
justify-content: flex-start; /* align whole panel to the left */
|
||
gap: 36px; /* slight spacing */
|
||
padding: 16px 24px; /* left padding so content isn't flush to window edge */
|
||
}
|
||
|
||
/* separator: thin vertical line between tags and slider */
|
||
.slider-separator {
|
||
width: 1px;
|
||
background: rgba(255,255,255,0.06);
|
||
border-radius: 1px;
|
||
align-self: flex-start;
|
||
height: 525px; /* match .vertical-slider height */
|
||
margin: 0 18px;
|
||
}
|
||
|
||
/* container holding the vertical slider and its value/button */
|
||
.slider-controls {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start; /* align slider to the left side of this block */
|
||
gap: 8px;
|
||
position: relative; /* <-- needed for absolutely-positioned bubble */
|
||
}
|
||
|
||
/* prettier floating value bubble shown next to the slider thumb */
|
||
.value-bubble {
|
||
position: absolute;
|
||
left: calc(100% + -10px); /* moved closer to the slider */
|
||
top: 0; /* JS uses transform to vertically place the bubble */
|
||
pointer-events: none;
|
||
background: linear-gradient(180deg,#0f66d6,#0356b8);
|
||
color: #fff;
|
||
padding: 6px 8px;
|
||
border-radius: 10px;
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
box-shadow: 0 6px 18px rgba(2,47,110,0.48), inset 0 -2px 6px rgba(255,255,255,0.04);
|
||
white-space: nowrap;
|
||
/* use transform for positioning (more responsive) */
|
||
transition: transform 40ms linear; /* short transition for smoothness */
|
||
will-change: transform;
|
||
z-index: 5;
|
||
}
|
||
|
||
/* small triangular pointer - keeps centering using top:50% */
|
||
.value-bubble::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: -5px; /* adjusted to match new left offset */
|
||
top: 50%;
|
||
transform: translateY(-50%) rotate(45deg);
|
||
width: 8px;
|
||
height: 8px;
|
||
background: linear-gradient(180deg,#0f66d6,#0356b8);
|
||
box-shadow: none;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
/* ensure slider sits comfortably when left-aligned */
|
||
.slider-controls .vertical-slider {
|
||
margin: 0; /* remove centering margin */
|
||
}
|
||
|
||
.vertical-slider {
|
||
writing-mode: bt-lr; /* vertical orientation */
|
||
-webkit-appearance: slider-vertical;
|
||
-moz-appearance: slider-vertical;
|
||
appearance: slider-vertical; /* standard property for compatibility */
|
||
width: 28px; /* slightly wider for better appearance */
|
||
height: 470px; /* Increased height (was 200px) */
|
||
background: #333;
|
||
border-radius: 8px;
|
||
margin: 0 0 8px 0;
|
||
}
|
||
|
||
.vertical-slider::-webkit-slider-thumb {
|
||
background: #007bff;
|
||
border-radius: 50%;
|
||
width: 28px; /* match new width */
|
||
height: 28px; /* match new width */
|
||
-webkit-appearance: none;
|
||
}
|
||
|
||
/* slider thumb - smooth baseline transition (applies to both engines) */
|
||
.vertical-slider::-webkit-slider-thumb {
|
||
transition: transform 140ms ease, box-shadow 140ms ease;
|
||
}
|
||
.vertical-slider::-moz-range-thumb {
|
||
transition: transform 140ms ease, box-shadow 140ms ease;
|
||
}
|
||
|
||
/* strong glow only while dragging/grabbing the thumb */
|
||
.vertical-slider.thumb-dragging::-webkit-slider-thumb {
|
||
/* bright accent glow */
|
||
box-shadow:
|
||
0 0 18px rgba(0, 123, 255, 0.95),
|
||
0 0 36px rgba(0, 123, 255, 0.45),
|
||
0 0 72px rgba(0, 123, 255, 0.18);
|
||
transform: scale(1.14);
|
||
}
|
||
|
||
/* Firefox (moz) thumb */
|
||
.vertical-slider.thumb-dragging::-moz-range-thumb {
|
||
box-shadow:
|
||
0 0 18px rgba(0, 123, 255, 0.95),
|
||
0 0 36px rgba(0, 123, 255, 0.45),
|
||
0 0 72px rgba(0, 123, 255, 0.18);
|
||
transform: scale(1.14);
|
||
}
|
||
|
||
/* optional subtle track highlight while dragging */
|
||
.vertical-slider.thumb-dragging {
|
||
outline: none;
|
||
box-shadow: inset 0 0 24px rgba(0,123,255,0.035);
|
||
transition: box-shadow 160ms ease;
|
||
}
|
||
|
||
/* Button below slider */
|
||
.slider-btn {
|
||
width: 40px;
|
||
height: 40px;
|
||
background: #444;
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 12px;
|
||
margin-top: 8px;
|
||
cursor: pointer;
|
||
font-size: 18px;
|
||
transition: background 0.2s;
|
||
}
|
||
|
||
.slider-btn:hover {
|
||
background: #007bff;
|
||
}
|
||
|
||
/* Settings panel */
|
||
.settings-panel {
|
||
position: fixed;
|
||
right: 30px;
|
||
bottom: 30px;
|
||
background: #1b1b1b;
|
||
border: 1px solid #333;
|
||
padding: 16px;
|
||
border-radius: 10px;
|
||
display: none;
|
||
z-index: 999;
|
||
}
|
||
|
||
.settings-panel[aria-hidden="false"] {
|
||
display: block;
|
||
}
|
||
|
||
/* 4x4 button grid for placeholder tab */
|
||
.button-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 64px);
|
||
grid-template-rows: repeat(4, 64px);
|
||
gap: 12px;
|
||
align-items: center;
|
||
justify-content: start;
|
||
padding-top: 12px;
|
||
}
|
||
|
||
/* add extra vertical space between first row and the lower three */
|
||
.button-grid > *:nth-child(n+5):nth-child(-n+8) {
|
||
margin-top: 12px;
|
||
}
|
||
|
||
.grid-button {
|
||
width: 64px;
|
||
height: 64px;
|
||
background: #1b1b1b;
|
||
color: #ddd;
|
||
border: 1px solid #2b2b2b;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
transition: background 0.12s, transform 0.08s;
|
||
}
|
||
|
||
.grid-button:active {
|
||
transform: translateY(1px);
|
||
background: #222;
|
||
}
|
||
|
||
/* New: Makropad two-column layout used only for device-specific tab-2 content */
|
||
.makropad-two-col {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 18px;
|
||
padding-top: 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* left and right groups layout */
|
||
.makropad-two-col .left-group,
|
||
.makropad-two-col .right-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
/* a single row of three buttons */
|
||
.grid-3cols {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 64px);
|
||
grid-auto-rows: 64px;
|
||
gap: 12px;
|
||
}
|
||
|
||
/* spacer row preserves height but is empty */
|
||
.grid-3cols.spacer-row > div {
|
||
width: 64px;
|
||
height: 64px;
|
||
}
|
||
|
||
/* thin vertical separator between left and right groups */
|
||
.vertical-sep {
|
||
width: 1px;
|
||
background: rgba(255,255,255,0.06);
|
||
border-radius: 1px;
|
||
align-self: stretch;
|
||
margin-top: 4px;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
/* Potentiometer visual: circular, ring shows value via --deg (degrees) */
|
||
.potentiometer {
|
||
width: 64px;
|
||
height: 64px;
|
||
border-radius: 50%;
|
||
position: relative;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
pointer-events: none; /* non-interactive */
|
||
user-select: none;
|
||
-webkit-user-select: none;
|
||
}
|
||
|
||
/* outer ring drawn with conic-gradient; --deg expected like "180deg" */
|
||
.pot-ring {
|
||
position: absolute;
|
||
inset: 0;
|
||
border-radius: 50%;
|
||
padding: 5px;
|
||
box-sizing: border-box;
|
||
background:
|
||
conic-gradient(#007bff var(--deg, 180deg), rgba(255,255,255,0.06) 0);
|
||
}
|
||
|
||
/* inner circle to create ring effect */
|
||
.pot-inner {
|
||
width: calc(100% - 14px);
|
||
height: calc(100% - 14px);
|
||
border-radius: 50%;
|
||
background: linear-gradient(180deg,#151515,#0e0e0e);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #cfeaff;
|
||
font-size: 12px;
|
||
z-index: 1;
|
||
}
|
||
|
||
/* pot value text */
|
||
.pot-value {
|
||
font-weight: 600;
|
||
}
|
||
|
||
.slider-assignment {
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: center;
|
||
margin-top: 8px;
|
||
}
|
||
|
||
.slider-tag-select {
|
||
background: #2b2b2b;
|
||
color: #eee;
|
||
border: 1px solid #3a3a3a;
|
||
padding: 6px 8px;
|
||
border-radius: 6px;
|
||
font-size: 12px;
|
||
min-width: 140px;
|
||
}
|
||
|
||
.assign-btn {
|
||
background: #007bff;
|
||
color: #fff;
|
||
border: none;
|
||
padding: 6px 8px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.assign-btn:hover {
|
||
background: #0063d1;
|
||
}
|
||
|
||
/* New: explicit connect/disconnect state colors.
|
||
.connect-state = green (Connect)
|
||
.disconnect-state = red (Disconnect) */
|
||
.assign-btn.connect-state {
|
||
background: linear-gradient(180deg,#27ae60,#1e8449);
|
||
color: #fff;
|
||
}
|
||
.assign-btn.connect-state:hover {
|
||
background: linear-gradient(180deg,#2ecc71,#27ae60);
|
||
}
|
||
|
||
.assign-btn.disconnect-state {
|
||
background: linear-gradient(180deg,#ff5252,#e53935);
|
||
color: #fff;
|
||
}
|
||
.assign-btn.disconnect-state:hover {
|
||
background: linear-gradient(180deg,#ff6b6b,#ff5252);
|
||
}
|
||
|
||
/* reuse tag container styles for per-slider containers */
|
||
.tag-container {
|
||
margin-top: 10px;
|
||
display: flex;
|
||
flex-wrap: wrap; /* ensure per-slider containers also wrap */
|
||
gap: 5px;
|
||
justify-content: flex-start;
|
||
border: 2px solid #444;
|
||
padding: 10px;
|
||
border-radius: 8px;
|
||
background: #333;
|
||
min-height: 480px; /* <-- ensure consistent minimum */
|
||
max-height: 480px; /* <-- keep consistent cap */
|
||
overflow-y: auto;
|
||
}
|
||
|
||
.tag-container::-webkit-scrollbar {
|
||
width: 8px;
|
||
background-color: #2f2f2f;
|
||
}
|
||
|
||
.tag-container::-webkit-scrollbar-thumb {
|
||
background-color: #808080;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.tag-container::-webkit-scrollbar-thumb:hover {
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
}
|
||
|
||
/* small input style for per-slider inputs */
|
||
.tag-input {
|
||
background: #222;
|
||
color: #fff;
|
||
border: 1px solid #3a3a3a;
|
||
padding: 6px 8px;
|
||
border-radius: 6px;
|
||
font-size: 12px;
|
||
min-width: 155px; /* was 145px; increased by 10px */
|
||
}
|
||
|
||
/* new: layout for tag generator to the left of vertical slider */
|
||
.slider-row {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 16px;
|
||
width: 100%;
|
||
}
|
||
|
||
/* left column that holds tag input + tag list (fixed-ish width) */
|
||
.slider-tag-generator {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
width: 260px; /* was 185px; increased by 10px */
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* two-column layout for the General settings panel with a centered separator
|
||
Apply these rules ONLY when the panel is active so it doesn't remain visible
|
||
while other settings tabs are shown. */
|
||
#settings-tab-1.settings-tab-content.active {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 18px 24px;
|
||
align-items: start;
|
||
position: relative; /* needed for the separator pseudo-element */
|
||
}
|
||
|
||
/* thin vertical separation line in the middle (neutral color)
|
||
only present when the General panel is active */
|
||
#settings-tab-1.settings-tab-content.active::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: 8px;
|
||
bottom: 8px;
|
||
left: 50%;
|
||
width: 1px;
|
||
background: rgba(255,255,255,0.06);
|
||
transform: translateX(-0.5px);
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* gentle inner padding so controls don't butt against the separator
|
||
only apply while the panel is active */
|
||
#settings-tab-1.settings-tab-content.active > * {
|
||
padding: 6px 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* slight extra breathing room away from the separator per column */
|
||
#settings-tab-1.settings-tab-content.active > *:nth-child(odd) { /* left column */
|
||
padding-right: 28px;
|
||
}
|
||
#settings-tab-1.settings-tab-content.active > *:nth-child(even) { /* right column */
|
||
padding-left: 28px;
|
||
}
|
||
|
||
/* responsive: collapse to single column on smaller widths and hide separator (scoped to active) */
|
||
@media (max-width: 720px) {
|
||
#settings-tab-1.settings-tab-content.active {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
#settings-tab-1.settings-tab-content.active::before {
|
||
display: none;
|
||
}
|
||
#settings-tab-1.settings-tab-content.active > * {
|
||
padding: 6px 0;
|
||
}
|
||
}
|
||
|
||
/* ensure settings-tab-content children remain layout-contained (no overflow showing when inactive) */
|
||
.settings-tab-content {
|
||
contain: layout inline-size;
|
||
}
|
||
|
||
/* Restore and strengthen select + refresh-button styling (scoped to settings window)
|
||
so the dropdown keeps the dark theme and the refresh button stays green even if it also
|
||
has the settings-close class in the markup. */
|
||
.settings-window .settings-select {
|
||
background: #222;
|
||
color: #eee;
|
||
border: 1px solid #3a3a3a;
|
||
padding: 6px 10px;
|
||
border-radius: 6px;
|
||
font-size: 13px;
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* ensure the native dropdown arrow remains visible on dark background in some engines */
|
||
.settings-window .settings-select::-ms-expand {
|
||
display: block;
|
||
}
|
||
|
||
/* target the refresh button by id (higher specificity) so it keeps the green color */
|
||
#com-refresh-btn {
|
||
background: transparent;
|
||
border: none;
|
||
padding: 4px 6px;
|
||
font-size: 16px;
|
||
color: #27ae60; /* green icon color */
|
||
cursor: pointer;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* hover state — subtle green hover */
|
||
#com-refresh-btn:hover {
|
||
background: rgba(39,174,96,0.10);
|
||
color: #1e8449;
|
||
}
|
||
|
||
/* keep the settings-close general rules unaffected for other uses */
|
||
.settings-close {
|
||
grid-area: close;
|
||
justify-self: end;
|
||
align-self: center;
|
||
background: transparent;
|
||
border: none;
|
||
color: #bbb;
|
||
font-size: 18px;
|
||
cursor: pointer;
|
||
padding: 6px;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.settings-close:hover {
|
||
color: #fff;
|
||
background: rgba(255,255,255,0.03);
|
||
}
|
||
|
||
/* stack left column controls vertically and keep them left-aligned */
|
||
.settings-left-column {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
|
||
/* right column placeholder — now contains checkboxes stacked vertically */
|
||
.settings-right-column {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
padding-left: 12px; /* breathing room from separator */
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
/* checkbox rows and labels */
|
||
.settings-checkbox-row {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.checkbox-label {
|
||
color: #cfcfcf;
|
||
font-size: 13px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* small input spacing so checkbox doesn't touch the label text */
|
||
.settings-checkbox {
|
||
width: 16px;
|
||
height: 16px;
|
||
accent-color: #27ae60; /* green accent where supported */
|
||
}
|
||
|
||
/* ensure left-column checkbox aligns with label column sizing */
|
||
.settings-left-column .settings-row > label {
|
||
min-width: 64px; /* reuse existing label sizing for alignment */
|
||
}
|
||
|
||
/* make checkboxes dark and show a blue checked state (scoped to settings window) */
|
||
.settings-window .settings-checkbox {
|
||
/* remove native look so we can draw our own box */
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
|
||
width: 18px;
|
||
height: 18px;
|
||
background: #222; /* dark box */
|
||
border: 1px solid #3a3a3a; /* neutral border like selects */
|
||
border-radius: 4px;
|
||
display: inline-block;
|
||
vertical-align: middle;
|
||
position: relative;
|
||
box-sizing: border-box;
|
||
transition: background 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
|
||
cursor: pointer;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
/* keep native-accent fallback for engines that support it */
|
||
.settings-window .settings-checkbox {
|
||
accent-color: #0f66d6;
|
||
}
|
||
|
||
/* accessible focus ring */
|
||
.settings-window .settings-checkbox:focus {
|
||
outline: none;
|
||
box-shadow: 0 0 0 4px rgba(15,102,214,0.12);
|
||
}
|
||
|
||
/* draw a custom checkmark using ::after */
|
||
.settings-window .settings-checkbox::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: 4px;
|
||
top: 2px;
|
||
width: 6px;
|
||
height: 10px;
|
||
border: solid transparent;
|
||
border-width: 0 2px 2px 0;
|
||
transform: rotate(45deg) scale(0.9);
|
||
opacity: 0;
|
||
transition: opacity 120ms ease, transform 120ms ease;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* checked state: blue gradient background and visible white checkmark */
|
||
.settings-window .settings-checkbox:checked {
|
||
background: linear-gradient(180deg,#0f66d6,#0356b8);
|
||
border-color: #0356b8;
|
||
}
|
||
.settings-window .settings-checkbox:checked::after {
|
||
border-color: #fff;
|
||
opacity: 1;
|
||
transform: rotate(45deg) scale(1);
|
||
}
|
||
|
||
/* Small tweak: when label is clicked/active, keep pointer cursor for the whole label */
|
||
.settings-window .checkbox-label {
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* Customisation panel layout (applies to both .customisation-grid and .customisation-group) */
|
||
.customisation-grid,
|
||
.customisation-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
padding: 8px 4px;
|
||
}
|
||
.customisation-row {
|
||
display: flex;
|
||
gap: 12px;
|
||
align-items: center;
|
||
}
|
||
.customisation-row label {
|
||
width: 180px; /* align labels vertically */
|
||
font-size: 13px;
|
||
color: #cfcfcf;
|
||
}
|
||
/* keep a simple color input sizing for potential legacy inputs (no custom control UI) */
|
||
.customisation-row input[type="color"] {
|
||
width: 44px;
|
||
height: 28px;
|
||
border: 1px solid #333;
|
||
border-radius: 6px;
|
||
padding: 0;
|
||
background: none;
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
}
|
||
|
||
/* color-control layout for the color input + reset button */
|
||
.color-control {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
/* reset-default: compact centered button showing the ↩︎ glyph
|
||
Keep the element in DOM (so it can be focused/announced when JS enables it),
|
||
but hide it visually by default using opacity + transform so we can animate its appearance. */
|
||
.reset-default {
|
||
/* stay present in DOM; visual hiding via opacity/transform for smooth animation */
|
||
display: inline-grid;
|
||
place-items: center;
|
||
|
||
/* visually hidden by default */
|
||
opacity: 0;
|
||
transform: scale(0.94) translateY(-2px);
|
||
pointer-events: none;
|
||
transition:
|
||
opacity 200ms cubic-bezier(0.22, 1, 0.36, 1),
|
||
transform 200ms cubic-bezier(0.22, 1, 0.36, 1),
|
||
background 120ms linear;
|
||
|
||
background: transparent;
|
||
border: none;
|
||
color: #ff5252; /* icon always red when visible */
|
||
cursor: pointer;
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 6px;
|
||
font-size: 16px;
|
||
line-height: 1;
|
||
padding: 0;
|
||
}
|
||
|
||
/* subtle hover/focus background only — applies when visible via .dirty */
|
||
.reset-default:hover,
|
||
.reset-default:focus {
|
||
background: rgba(255,255,255,0.03);
|
||
outline: none;
|
||
}
|
||
|
||
/* keep accessible focus ring */
|
||
.reset-default:focus {
|
||
box-shadow: 0 0 0 4px rgba(15,102,214,0.08);
|
||
}
|
||
|
||
/* show and style the button only when the color differs from its data-default */
|
||
.reset-default.dirty {
|
||
opacity: 1;
|
||
transform: scale(1) translateY(0);
|
||
pointer-events: auto;
|
||
/* colour already set on the base rule to be always red */
|
||
}
|
||
.reset-default.dirty:hover,
|
||
.reset-default.dirty:focus {
|
||
background: rgba(255,82,82,0.06);
|
||
}
|