Dark mode for contrast and more bug squashing
This commit is contained in:
parent
fe0cc3482e
commit
84eef1beb2
7 changed files with 244 additions and 136 deletions
116
src/App.css
116
src/App.css
|
@ -2,7 +2,7 @@
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: white;
|
background-color: #000000;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,14 +11,14 @@
|
||||||
top: 20px;
|
top: 20px;
|
||||||
left: 20px;
|
left: 20px;
|
||||||
transform: none;
|
transform: none;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
background-color: white;
|
background-color: rgba(40, 40, 40, 0.8);
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
font-family: Inter, system-ui, Arial, sans-serif;
|
font-family: Inter, system-ui, Arial, sans-serif;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #444;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
@ -43,27 +43,27 @@
|
||||||
width: calc(100vw / 0.01); /* Width based on minimum zoom (0.01) */
|
width: calc(100vw / 0.01); /* Width based on minimum zoom (0.01) */
|
||||||
height: calc((100vh - 100px) / 0.01); /* Height based on minimum zoom minus UI height */
|
height: calc((100vh - 100px) / 0.01); /* Height based on minimum zoom minus UI height */
|
||||||
transform-origin: 0 0;
|
transform-origin: 0 0;
|
||||||
background-color: white;
|
background-color: #000000;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
contain: layout paint;
|
contain: layout paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
.target {
|
.target {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: #444444; /* Darker gray for better visibility */
|
background-color: #666666; /* Light gray for better contrast on black */
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
transition: background-color 0.2s ease;
|
transition: background-color 0.2s ease;
|
||||||
box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
|
box-shadow: 0 0 15px rgba(100, 100, 100, 0.4);
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
contain: layout;
|
contain: layout;
|
||||||
border: 4px solid rgba(0, 0, 0, 0.4); /* Darker border for better contrast */
|
border: 4px solid rgba(180, 180, 180, 0.6); /* Lighter border for contrast */
|
||||||
}
|
}
|
||||||
|
|
||||||
.target.active {
|
.target.active {
|
||||||
background-color: #22aa22; /* Darker green for better visibility */
|
background-color: #22cc22; /* Bright green for better visibility */
|
||||||
box-shadow: 0 0 30px rgba(34, 170, 34, 0.8);
|
box-shadow: 0 0 30px rgba(34, 204, 34, 0.8);
|
||||||
border: 4px solid white;
|
border: 4px solid #ffffff;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ body,
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: white;
|
background-color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
|
@ -94,13 +94,14 @@ body,
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
background: white;
|
background: rgba(40, 40, 40, 0.8);
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #444;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
color: #ffffff;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +109,7 @@ body,
|
||||||
.rounds-toggle:hover,
|
.rounds-toggle:hover,
|
||||||
.export-button:hover,
|
.export-button:hover,
|
||||||
.reset-button:hover {
|
.reset-button:hover {
|
||||||
background: #f5f5f5;
|
background: #444444;
|
||||||
border-color: #646cff;
|
border-color: #646cff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,17 +119,17 @@ body,
|
||||||
}
|
}
|
||||||
|
|
||||||
.export-button:disabled:hover {
|
.export-button:disabled:hover {
|
||||||
background: white;
|
background: rgba(40, 40, 40, 0.8);
|
||||||
border-color: #ddd;
|
border-color: #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reset-button {
|
.reset-button {
|
||||||
border-color: #ffcdd2;
|
border-color: #aa3333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reset-button:hover {
|
.reset-button:hover {
|
||||||
background: #fff5f5;
|
background: #442222;
|
||||||
border-color: #ef5350;
|
border-color: #ff4444;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preset Selection */
|
/* Preset Selection */
|
||||||
|
@ -144,8 +145,9 @@ body,
|
||||||
|
|
||||||
.preset-button {
|
.preset-button {
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
background: white;
|
background: #333333;
|
||||||
border: 1px solid #ddd;
|
color: #ffffff;
|
||||||
|
border: 1px solid #555;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
|
@ -154,32 +156,14 @@ body,
|
||||||
.preset-button.active {
|
.preset-button.active {
|
||||||
background: #646cff;
|
background: #646cff;
|
||||||
color: white;
|
color: white;
|
||||||
border-color: #646cff;
|
border-color: #8088ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-button:hover:not(.active) {
|
.preset-button:hover:not(.active) {
|
||||||
background: #f5f5f5;
|
background: #444444;
|
||||||
border-color: #646cff;
|
border-color: #646cff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mode Selection */
|
|
||||||
.mode-selection {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.radio-group {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.radio-group label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Break Screen */
|
/* Break Screen */
|
||||||
.break-screen {
|
.break-screen {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -187,7 +171,7 @@ body,
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -195,17 +179,18 @@ body,
|
||||||
}
|
}
|
||||||
|
|
||||||
.break-container {
|
.break-container {
|
||||||
background-color: white;
|
background-color: #222222;
|
||||||
|
color: #ffffff;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.break-container h2 {
|
.break-container h2 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.break-container button {
|
.break-container button {
|
||||||
|
@ -221,7 +206,7 @@ body,
|
||||||
}
|
}
|
||||||
|
|
||||||
.break-container button:hover {
|
.break-container button:hover {
|
||||||
background-color: #4e57cc;
|
background-color: #7a82ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Resize Warning Popup */
|
/* Resize Warning Popup */
|
||||||
|
@ -231,7 +216,7 @@ body,
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -241,17 +226,18 @@ body,
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize-warning-content {
|
.resize-warning-content {
|
||||||
background-color: white;
|
background-color: #222222;
|
||||||
|
color: #ffffff;
|
||||||
padding: 20px 30px;
|
padding: 20px 30px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize-warning-content h3 {
|
.resize-warning-content h3 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize-warning-content button {
|
.resize-warning-content button {
|
||||||
|
@ -267,7 +253,7 @@ body,
|
||||||
}
|
}
|
||||||
|
|
||||||
.resize-warning-content button:hover {
|
.resize-warning-content button:hover {
|
||||||
background-color: #4e57cc;
|
background-color: #7a82ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
|
@ -292,26 +278,26 @@ body,
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
color: white;
|
color: white;
|
||||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-indicator.preset-A {
|
.preset-indicator.preset-A {
|
||||||
background-color: #4285f4; /* Blue for Preset A */
|
background-color: rgba(66, 133, 244, 0.9); /* Blue for Preset A */
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-indicator.preset-B {
|
.preset-indicator.preset-B {
|
||||||
background-color: #34a853; /* Green for Preset B */
|
background-color: rgba(52, 168, 83, 0.9); /* Green for Preset B */
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-indicator.preset-C {
|
.preset-indicator.preset-C {
|
||||||
background-color: #ea4335; /* Red for Preset C */
|
background-color: rgba(234, 67, 53, 0.9); /* Red for Preset C */
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-indicator.preset-D {
|
.preset-indicator.preset-D {
|
||||||
background-color: #fbbc05; /* Yellow for Preset D */
|
background-color: rgba(251, 188, 5, 0.9); /* Yellow for Preset D */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preset Transition Effect */
|
/* Preset Transition Effect */
|
||||||
|
@ -334,7 +320,7 @@ body,
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: white;
|
color: white;
|
||||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
|
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
|
||||||
padding: 30px 60px;
|
padding: 30px 60px;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -342,19 +328,19 @@ body,
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-transition-overlay.preset-A .preset-transition-content {
|
.preset-transition-overlay.preset-A .preset-transition-content {
|
||||||
background-color: rgba(66, 133, 244, 0.85); /* Blue for Preset A */
|
background-color: rgba(66, 133, 244, 0.9); /* Blue for Preset A */
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-transition-overlay.preset-B .preset-transition-content {
|
.preset-transition-overlay.preset-B .preset-transition-content {
|
||||||
background-color: rgba(52, 168, 83, 0.85); /* Green for Preset B */
|
background-color: rgba(52, 168, 83, 0.9); /* Green for Preset B */
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-transition-overlay.preset-C .preset-transition-content {
|
.preset-transition-overlay.preset-C .preset-transition-content {
|
||||||
background-color: rgba(234, 67, 53, 0.85); /* Red for Preset C */
|
background-color: rgba(234, 67, 53, 0.9); /* Red for Preset C */
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-transition-overlay.preset-D .preset-transition-content {
|
.preset-transition-overlay.preset-D .preset-transition-content {
|
||||||
background-color: rgba(251, 188, 5, 0.85); /* Yellow for Preset D */
|
background-color: rgba(251, 188, 5, 0.9); /* Yellow for Preset D */
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeInOut {
|
@keyframes fadeInOut {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.7);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -12,15 +12,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.instructions-panel {
|
.instructions-panel {
|
||||||
background: white;
|
background: #222222;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||||
position: relative;
|
position: relative;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instructions-header {
|
.instructions-header {
|
||||||
|
@ -33,18 +34,18 @@
|
||||||
.instructions-header h2 {
|
.instructions-header h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instructions-content {
|
.instructions-content {
|
||||||
color: #4a5568;
|
color: #cccccc;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instructions-content h3 {
|
.instructions-content h3 {
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.instructions-content ul {
|
.instructions-content ul {
|
||||||
|
@ -81,20 +82,21 @@
|
||||||
|
|
||||||
.keyboard-shortcut {
|
.keyboard-shortcut {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background: #f1f5f9;
|
background: #333333;
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mode Selection Styles */
|
/* Mode Selection Styles */
|
||||||
.mode-selection {
|
.mode-selection {
|
||||||
background: #f8fafc;
|
background: #333333;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #444444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-selection .radio-group {
|
.mode-selection .radio-group {
|
||||||
|
@ -107,9 +109,9 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border: 1px solid #e2e8f0;
|
border: 1px solid #444444;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: white;
|
background: #222222;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -117,25 +119,26 @@
|
||||||
|
|
||||||
.mode-selection label:hover {
|
.mode-selection label:hover {
|
||||||
border-color: #646cff;
|
border-color: #646cff;
|
||||||
box-shadow: 0 2px 8px rgba(100, 108, 255, 0.1);
|
box-shadow: 0 2px 8px rgba(100, 108, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-selection input[type="radio"] {
|
.mode-selection input[type="radio"] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 15px;
|
top: 15px;
|
||||||
left: 15px;
|
left: 15px;
|
||||||
|
accent-color: #646cff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-label {
|
.mode-label {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
margin-left: 25px;
|
margin-left: 25px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-description {
|
.mode-description {
|
||||||
margin: 8px 0 0 25px;
|
margin: 8px 0 0 25px;
|
||||||
color: #64748b;
|
color: #cccccc;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,11 +147,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-selection input[type="radio"]:checked ~ .mode-description {
|
.mode-selection input[type="radio"]:checked ~ .mode-description {
|
||||||
color: #4a5568;
|
color: #dddddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.warning-message {
|
.warning-message {
|
||||||
background-color: #fff8e1;
|
background-color: #332211;
|
||||||
border-left: 4px solid #ffb300;
|
border-left: 4px solid #ffb300;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
@ -156,7 +159,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.warning-message h3 {
|
.warning-message h3 {
|
||||||
color: #e65100;
|
color: #ffb300;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -165,5 +168,5 @@
|
||||||
|
|
||||||
.warning-message p {
|
.warning-message p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: #333;
|
color: #dddddd;
|
||||||
}
|
}
|
|
@ -2,16 +2,16 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 80px;
|
top: 80px;
|
||||||
left: 20px;
|
left: 20px;
|
||||||
background: white;
|
background: #222222;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #444;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
max-height: calc(100vh - 120px);
|
max-height: calc(100vh - 120px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounds-header {
|
.rounds-header {
|
||||||
|
@ -21,16 +21,16 @@
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
background: white;
|
background: #222222;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounds-header h2 {
|
.rounds-header h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounds-header button {
|
.rounds-header button {
|
||||||
|
@ -40,6 +40,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounds-header button:hover {
|
.rounds-header button:hover {
|
||||||
|
@ -55,27 +56,27 @@
|
||||||
|
|
||||||
.round-item {
|
.round-item {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border: 1px solid #eee;
|
border: 1px solid #444;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: #f9f9f9;
|
background: #333333;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.round-item:hover {
|
.round-item:hover {
|
||||||
border-color: #ddd;
|
border-color: #555;
|
||||||
background: white;
|
background: #3a3a3a;
|
||||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.round-number {
|
.round-number {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.round-stats {
|
.round-stats {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
color: #666;
|
color: #cccccc;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|
|
@ -2,28 +2,36 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 80px;
|
top: 80px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
background: white;
|
background: #222222;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #444;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 20px;
|
padding: 15px;
|
||||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
width: 300px;
|
width: 260px;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Override all child backgrounds except for specific elements */
|
||||||
|
.settings-panel * {
|
||||||
|
background-color: #222222;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-header {
|
.settings-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-header h2 {
|
.settings-header h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-header button {
|
.settings-header button {
|
||||||
|
@ -33,6 +41,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-header button:hover {
|
.settings-header button:hover {
|
||||||
|
@ -43,14 +52,14 @@
|
||||||
.slider-row {
|
.slider-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 10px 0;
|
margin: 8px 0;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-row label {
|
.slider-row label {
|
||||||
width: 120px;
|
width: 100px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-row input[type="range"] {
|
.slider-row input[type="range"] {
|
||||||
|
@ -58,14 +67,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-row .value-input {
|
.slider-row .value-input {
|
||||||
width: 50px;
|
width: 40px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #444;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: white;
|
background: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-row .value-input:focus {
|
.slider-row .value-input:focus {
|
||||||
|
@ -75,13 +84,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.slider-row .value-input:disabled {
|
.slider-row .value-input:disabled {
|
||||||
background: #f5f5f5;
|
background: #444;
|
||||||
color: #999;
|
color: #999;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acceleration-toggle {
|
.acceleration-toggle {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.acceleration-toggle label {
|
.acceleration-toggle label {
|
||||||
|
@ -90,12 +99,93 @@
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sliders-container h3 {
|
.sliders-container h3 {
|
||||||
margin: 0 0 15px 0;
|
margin: 0 0 12px 0;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #213547;
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mode selection styling */
|
||||||
|
.mode-selection {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background: #222222;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-selection h3 {
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-selection .radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
color: #ffffff;
|
||||||
|
background: #222222;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completely restyle radio buttons */
|
||||||
|
.radio-group label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ffffff;
|
||||||
|
background: #222222;
|
||||||
|
border: none;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group input[type="radio"] {
|
||||||
|
accent-color: #646cff;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
min-width: 16px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Preset Selection */
|
||||||
|
.preset-selection {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background: #222222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preset-selection h3 {
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preset-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preset-button {
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: #333333;
|
||||||
|
color: #ffffff;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preset-button.active {
|
||||||
|
background: #646cff;
|
||||||
|
color: white;
|
||||||
|
border-color: #8088ff;
|
||||||
}
|
}
|
|
@ -102,7 +102,7 @@ export const Settings: React.FC<SettingsProps> = ({
|
||||||
checked={mode === 'freestyle'}
|
checked={mode === 'freestyle'}
|
||||||
onChange={() => handleModeChange('freestyle')}
|
onChange={() => handleModeChange('freestyle')}
|
||||||
/>
|
/>
|
||||||
Freestyle Mode
|
<span>Freestyle Mode</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input
|
<input
|
||||||
|
@ -112,7 +112,7 @@ export const Settings: React.FC<SettingsProps> = ({
|
||||||
checked={mode === 'study'}
|
checked={mode === 'study'}
|
||||||
onChange={() => handleModeChange('study')}
|
onChange={() => handleModeChange('study')}
|
||||||
/>
|
/>
|
||||||
Study Mode (25 targets per preset)
|
<span>Study Mode (25 targets per preset)</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,24 +10,36 @@ export const calculateZoomDelta = (
|
||||||
|
|
||||||
export const calculateInitialViewport = (initialZoom: number): ViewportOffset => {
|
export const calculateInitialViewport = (initialZoom: number): ViewportOffset => {
|
||||||
// When fully zoomed out, we want to see the entire content area
|
// When fully zoomed out, we want to see the entire content area
|
||||||
// The target distribution is sized to match the viewport at minimum zoom
|
// Account for safety margins and UI exclusion zones
|
||||||
// Account for the UI exclusion zone at the top
|
|
||||||
const windowWidth = window.innerWidth;
|
const windowWidth = window.innerWidth;
|
||||||
const windowHeight = window.innerHeight;
|
const windowHeight = window.innerHeight;
|
||||||
|
|
||||||
// Same UI margin as in target generation
|
// Same UI margins as in target generation
|
||||||
const UI_TOP_MARGIN = 100;
|
const UI_TOP_MARGIN = 100;
|
||||||
|
const UI_BOTTOM_MARGIN = 50; // Added bottom margin
|
||||||
|
|
||||||
// Center the viewport on the target area
|
// We need to account for the safety margin used in target generation
|
||||||
const areaWidth = windowWidth / CONSTANTS.ZOOM_LEVELS.min;
|
const MAX_RADIUS = CONSTANTS.TARGET_MAX_RADIUS;
|
||||||
const areaHeight = (windowHeight - UI_TOP_MARGIN) / CONSTANTS.ZOOM_LEVELS.min;
|
const safetyMargin = MAX_RADIUS * 1.5; // Increased from 1.2 to 1.5
|
||||||
|
|
||||||
|
// Calculate the full target area including margins
|
||||||
|
const minZoom = CONSTANTS.ZOOM_LEVELS.min;
|
||||||
|
const areaWidth = windowWidth / minZoom;
|
||||||
|
const areaHeight = (windowHeight - UI_TOP_MARGIN - UI_BOTTOM_MARGIN) / minZoom;
|
||||||
|
|
||||||
// Account for the UI exclusion zone in Y offset
|
// Account for the UI exclusion zone in Y offset
|
||||||
const startY = UI_TOP_MARGIN / CONSTANTS.ZOOM_LEVELS.min;
|
const startY = UI_TOP_MARGIN / minZoom;
|
||||||
|
|
||||||
|
// Center viewport on the usable area
|
||||||
|
const usableWidth = areaWidth - (safetyMargin * 2);
|
||||||
|
const usableHeight = areaHeight - (safetyMargin * 2);
|
||||||
|
const usableCenterX = safetyMargin + (usableWidth / 2);
|
||||||
|
const usableCenterY = startY + safetyMargin + (usableHeight / 2);
|
||||||
|
|
||||||
|
// Position viewport so that the center of the usable area is in the middle of the screen
|
||||||
return {
|
return {
|
||||||
x: (areaWidth - windowWidth / initialZoom) / 2,
|
x: usableCenterX - (windowWidth / initialZoom / 2),
|
||||||
y: startY + (areaHeight - windowHeight / initialZoom) / 2
|
y: usableCenterY - (windowHeight / initialZoom / 2)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,15 @@ export const generateTargets = () => {
|
||||||
const windowWidth = window.innerWidth;
|
const windowWidth = window.innerWidth;
|
||||||
const windowHeight = window.innerHeight;
|
const windowHeight = window.innerHeight;
|
||||||
|
|
||||||
// Define UI exclusion zone (top area where UI elements are located)
|
// Define UI exclusion zones
|
||||||
const UI_TOP_MARGIN = 100; // pixels from top to exclude
|
const UI_TOP_MARGIN = 100; // pixels from top to exclude
|
||||||
|
const UI_BOTTOM_MARGIN = 50; // pixels from bottom to exclude for any potential UI
|
||||||
|
|
||||||
// Base the target area on the minimum zoom level
|
// Base the target area on the minimum zoom level
|
||||||
// This ensures when fully zoomed out, we see the entire grid
|
// This ensures when fully zoomed out, we see the entire grid
|
||||||
const minZoom = CONSTANTS.ZOOM_LEVELS.min;
|
const minZoom = CONSTANTS.ZOOM_LEVELS.min;
|
||||||
const areaWidth = windowWidth / minZoom;
|
const areaWidth = windowWidth / minZoom;
|
||||||
const areaHeight = (windowHeight - UI_TOP_MARGIN) / minZoom;
|
const areaHeight = (windowHeight - UI_TOP_MARGIN - UI_BOTTOM_MARGIN) / minZoom;
|
||||||
|
|
||||||
// Start Y position below the UI elements
|
// Start Y position below the UI elements
|
||||||
const startY = UI_TOP_MARGIN / minZoom;
|
const startY = UI_TOP_MARGIN / minZoom;
|
||||||
|
@ -28,18 +29,33 @@ export const generateTargets = () => {
|
||||||
const cellWidth = areaWidth / gridSize;
|
const cellWidth = areaWidth / gridSize;
|
||||||
const cellHeight = areaHeight / gridSize;
|
const cellHeight = areaHeight / gridSize;
|
||||||
|
|
||||||
|
// Increase safety margin to prevent any clipping
|
||||||
|
const safetyMargin = MAX_RADIUS * 1.5; // Increased from 1.2 to 1.5
|
||||||
|
|
||||||
|
// Adjust the usable area to prevent clipping at edges
|
||||||
|
const usableWidth = areaWidth - (safetyMargin * 2);
|
||||||
|
const usableHeight = areaHeight - (safetyMargin * 2);
|
||||||
|
|
||||||
|
// New starting point that accounts for target radius
|
||||||
|
const startUsableX = safetyMargin;
|
||||||
|
const startUsableY = startY + safetyMargin;
|
||||||
|
|
||||||
|
// Calculate adjusted cell dimensions for the usable area
|
||||||
|
const adjustedCellWidth = usableWidth / gridSize;
|
||||||
|
const adjustedCellHeight = usableHeight / gridSize;
|
||||||
|
|
||||||
for (let i = 0; i < CONSTANTS.TARGET_COUNT; i++) {
|
for (let i = 0; i < CONSTANTS.TARGET_COUNT; i++) {
|
||||||
// Calculate grid position
|
// Calculate grid position
|
||||||
const gridX = i % gridSize;
|
const gridX = i % gridSize;
|
||||||
const gridY = Math.floor(i / gridSize);
|
const gridY = Math.floor(i / gridSize);
|
||||||
|
|
||||||
// Add some randomness within each grid cell
|
// Reduce randomness to keep targets more centered in their cells
|
||||||
const randomOffsetX = (Math.random() - 0.5) * cellWidth * 0.6;
|
const randomOffsetX = (Math.random() - 0.5) * adjustedCellWidth * 0.4; // Reduced from 0.6
|
||||||
const randomOffsetY = (Math.random() - 0.5) * cellHeight * 0.6;
|
const randomOffsetY = (Math.random() - 0.5) * adjustedCellHeight * 0.4; // Reduced from 0.6
|
||||||
|
|
||||||
// Calculate final position - add startY to push everything down below UI
|
// Calculate final position - add margin to prevent edge clipping
|
||||||
const x = cellWidth * (gridX + 0.5) + randomOffsetX;
|
const x = startUsableX + adjustedCellWidth * (gridX + 0.5) + randomOffsetX;
|
||||||
const y = startY + cellHeight * (gridY + 0.5) + randomOffsetY;
|
const y = startUsableY + adjustedCellHeight * (gridY + 0.5) + randomOffsetY;
|
||||||
|
|
||||||
// Random radius
|
// Random radius
|
||||||
const radius = MIN_RADIUS + Math.random() * (MAX_RADIUS - MIN_RADIUS);
|
const radius = MIN_RADIUS + Math.random() * (MAX_RADIUS - MIN_RADIUS);
|
||||||
|
|
Loading…
Add table
Reference in a new issue