Files
Calender/static/css/style.css
Ludwig Mey ced41148ef Add dynamic text color adjustment based on background brightness
Automatically adjusts text color for optimal readability:
- Bright backgrounds: Text switches to dark color (#1a1a1a)
- Dark backgrounds: Text remains white (#ffffff)
- Uses luminance formula (0.299×R + 0.587×G + 0.114×B) for accurate brightness detection
- Analyzes images using canvas to sample 100x100 pixels
- Smooth color transitions (0.5s) between background changes
- Adjusts text shadows for better contrast in each mode
- Event time color adapts (#0066cc for light, #4a9eff for dark)

Technical implementation:
- Added calculateImageBrightness() function in app.js
- Modified updateBackground() to analyze and apply appropriate CSS class
- Added .light-bg and .dark-bg CSS classes for text color themes
- Brightness threshold set at 140 (out of 255)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 22:25:51 +13:00

442 lines
7.3 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Reset and base styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
overflow: hidden;
width: 100vw;
height: 100vh;
color: #ffffff;
transition: color 0.5s ease-in-out;
}
/* Dark text for bright backgrounds */
body.light-bg {
color: #1a1a1a;
}
body.light-bg .time,
body.light-bg .date,
body.light-bg .current-temp,
body.light-bg .weather-label,
body.light-bg .weather-icon,
body.light-bg .forecast-icon,
body.light-bg section h2,
body.light-bg .day-name,
body.light-bg .day-date,
body.light-bg .event-title,
body.light-bg .event-location,
body.light-bg .joke {
text-shadow: 1px 1px 3px rgba(255, 255, 255, 0.8);
}
body.light-bg .event-time {
color: #0066cc;
}
body.light-bg .event {
border-left-color: #0066cc;
}
/* White text for dark backgrounds (default) */
body.dark-bg {
color: #ffffff;
}
body.dark-bg .event-time {
color: #4a9eff;
}
body.dark-bg .event {
border-left-color: #4a9eff;
}
/* Background */
#background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
z-index: 0;
transition: background-image 1s ease-in-out;
}
#background::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.1);
z-index: 1;
}
/* Main container */
.container {
position: relative;
z-index: 2;
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
padding: 1rem;
}
/* Header maximally transparent; text readable via text-shadow */
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 1rem;
background: rgba(0, 0, 0, 0.03);
padding: 1rem 1.5rem;
border-radius: 10px;
}
.time-display {
display: flex;
flex-direction: column;
}
.time {
font-size: 4.5rem;
font-weight: 600;
line-height: 1;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
.date {
font-size: 1.6rem;
font-weight: 500;
margin-top: 0.3rem;
opacity: 0.9;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.weather-summary {
display: flex;
align-items: center;
gap: 1.5rem;
}
.current-weather-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.2rem;
}
.weather-label {
font-size: 1.2rem;
font-weight: 600;
opacity: 0.8;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.current-temp {
font-size: 3rem;
font-weight: 600;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
.weather-icon {
font-size: 2.5rem;
}
.header-forecast {
display: flex;
gap: 1rem;
}
.forecast-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.2rem;
}
.forecast-icon {
font-size: 2.2rem;
}
.forecast-temps {
display: flex;
gap: 0.3rem;
font-size: 1.3rem;
}
.forecast-temps .high {
font-weight: 700;
}
.forecast-temps .low {
opacity: 0.6;
}
/* Main content */
.main-content {
flex: 1;
display: flex;
overflow: hidden;
}
/* Sections */
section {
background: rgba(0, 0, 0, 0.03);
padding: 1rem 1.5rem;
border-radius: 10px;
overflow-y: auto;
flex: 1;
}
section h2 {
font-size: 2rem;
font-weight: 700;
margin-bottom: 0.8rem;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
section h3 {
font-size: 1.1rem;
font-weight: 400;
margin: 1rem 0 0.5rem;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
/* Weather Section */
.weather-description {
font-size: 1.1rem;
margin-bottom: 0.6rem;
text-transform: capitalize;
}
.weather-details {
display: flex;
flex-direction: column;
gap: 0.4rem;
margin: 0.8rem 0;
}
.weather-detail {
display: flex;
justify-content: space-between;
font-size: 0.95rem;
padding: 0.3rem 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.weather-detail .label {
opacity: 0.8;
}
/* Forecast */
.forecast-days {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.forecast-day {
display: grid;
grid-template-columns: 60px 1fr 100px;
align-items: center;
padding: 0.6rem;
background: rgba(255, 255, 255, 0.04);
border-radius: 8px;
gap: 0.8rem;
}
.forecast-day-name {
font-size: 1rem;
font-weight: 500;
}
.forecast-description {
font-size: 0.9rem;
opacity: 0.8;
text-transform: capitalize;
}
.forecast-temp {
font-size: 1rem;
text-align: right;
}
.forecast-temp .high {
font-weight: 500;
}
.forecast-temp .low {
opacity: 0.6;
margin-left: 0.5rem;
}
/* Calendar Section */
.events-list {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 0.8rem;
height: 100%;
}
.day-group {
display: flex;
flex-direction: column;
min-height: 0;
}
.day-header {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.6rem;
background: rgba(255, 255, 255, 0.06);
border-radius: 8px 8px 0 0;
margin-bottom: 0.5rem;
text-align: center;
}
.day-name {
font-size: 1.5rem;
font-weight: 700;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.day-date {
font-size: 1.2rem;
font-weight: 600;
opacity: 0.8;
margin-top: 0.2rem;
}
.day-events {
display: flex;
flex-direction: column;
gap: 0.5rem;
overflow-y: auto;
flex: 1;
}
.no-events {
font-size: 1.2rem;
font-weight: 500;
opacity: 0.5;
font-style: italic;
padding: 0.5rem;
text-align: center;
}
.event {
background: rgba(255, 255, 255, 0.04);
padding: 0.5rem 0.6rem;
border-radius: 6px;
border-left: 3px solid #4a9eff;
}
.event-time {
font-size: 1.1rem;
font-weight: 700;
margin-bottom: 0.2rem;
color: #4a9eff;
}
.event-title {
font-size: 1.3rem;
font-weight: 600;
margin-bottom: 0.2rem;
line-height: 1.2;
}
.event-location {
font-size: 1.1rem;
font-weight: 500;
opacity: 0.7;
font-style: italic;
}
.event-placeholder {
font-size: 1rem;
opacity: 0.6;
text-align: center;
padding: 2rem;
}
/* Footer */
.footer {
margin-top: 1rem;
background: rgba(0, 0, 0, 0.03);
padding: 0.8rem 1.5rem;
border-radius: 10px;
}
.joke {
font-size: 1.3rem;
font-weight: 500;
font-style: italic;
text-align: center;
opacity: 0.9;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
/* Scrollbar styling */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
border-radius: 10px;
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.3);
}
/* Responsive adjustments for smaller screens */
@media (max-width: 1200px) {
.time {
font-size: 5rem;
}
.date {
font-size: 2rem;
}
.current-temp {
font-size: 4rem;
}
section h2 {
font-size: 2.5rem;
}
}
@media (max-width: 768px) {
.main-content {
grid-template-columns: 1fr;
}
.time {
font-size: 4rem;
}
.current-temp {
font-size: 3.5rem;
}
}