diff --git a/www/android-chrome-192x192.png b/www/android-chrome-192x192.png new file mode 100644 index 0000000..3a41a87 Binary files /dev/null and b/www/android-chrome-192x192.png differ diff --git a/www/android-chrome-512x512.png b/www/android-chrome-512x512.png new file mode 100644 index 0000000..1d5d0ac Binary files /dev/null and b/www/android-chrome-512x512.png differ diff --git a/www/apple-touch-icon.png b/www/apple-touch-icon.png new file mode 100644 index 0000000..71ff0c7 Binary files /dev/null and b/www/apple-touch-icon.png differ diff --git a/www/favicon-16x16.png b/www/favicon-16x16.png new file mode 100644 index 0000000..04d910c Binary files /dev/null and b/www/favicon-16x16.png differ diff --git a/www/favicon-32x32.png b/www/favicon-32x32.png new file mode 100644 index 0000000..d1cfe9b Binary files /dev/null and b/www/favicon-32x32.png differ diff --git a/www/index.html b/www/index.html index 377dd48..bdda60d 100644 --- a/www/index.html +++ b/www/index.html @@ -3,11 +3,6 @@ WA2000 - - - - - @@ -268,10 +263,20 @@ function imageDataToDataURL(imageData) { function applyLiquidGlass() { const card = document.getElementById('card'); + + // offsetWidth/Height for map generation (unaffected by zoom) const w = card.offsetWidth; const h = card.offsetHeight; if (w === 0 || h === 0) return; + // getBoundingClientRect for SVG filter dimensions — these must match the + // actual rendered pixel size that backdrop-filter sees at current zoom level + const rect = card.getBoundingClientRect(); + const fw = Math.round(rect.width); + const fh = Math.round(rect.height); + + CONFIG.borderRadius = parseFloat(getComputedStyle(card).borderRadius) || 25; + const { imageData, maxDisplacement } = buildDisplacementMap(w, h); const dispDataURL = imageDataToDataURL(imageData); const specularDataURL = buildSpecularMap(w, h); @@ -280,12 +285,13 @@ function applyLiquidGlass() { const specImg = document.getElementById('specular-map-img'); const dispFilter = document.getElementById('displacement-map-filter'); + // Set filter image dimensions to the zoomed rect size so the map aligns correctly dispImg.setAttribute('href', dispDataURL); - dispImg.setAttribute('width', w); - dispImg.setAttribute('height', h); + dispImg.setAttribute('width', fw); + dispImg.setAttribute('height', fh); specImg.setAttribute('href', specularDataURL); - specImg.setAttribute('width', w); - specImg.setAttribute('height', h); + specImg.setAttribute('width', fw); + specImg.setAttribute('height', fh); dispFilter.setAttribute('scale', maxDisplacement); const isChrome = /Chrome/.test(navigator.userAgent) && !/Edg|Firefox/.test(navigator.userAgent); @@ -312,6 +318,10 @@ function applyNavGlassAt(radius) { const h = pill.offsetHeight; if (w === 0 || h === 0) return; + const rect = pill.getBoundingClientRect(); + const fw = Math.round(rect.width); + const fh = Math.round(rect.height); + const savedBezel = CONFIG.bezelWidth; const savedScale = CONFIG.scaleRatio; const savedRadius = CONFIG.borderRadius; @@ -328,11 +338,11 @@ function applyNavGlassAt(radius) { CONFIG.borderRadius = savedRadius; document.getElementById('nav-disp-img').setAttribute('href', dispDataURL); - document.getElementById('nav-disp-img').setAttribute('width', w); - document.getElementById('nav-disp-img').setAttribute('height', h); + document.getElementById('nav-disp-img').setAttribute('width', fw); + document.getElementById('nav-disp-img').setAttribute('height', fh); document.getElementById('nav-spec-img').setAttribute('href', specularDataURL); - document.getElementById('nav-spec-img').setAttribute('width', w); - document.getElementById('nav-spec-img').setAttribute('height', h); + document.getElementById('nav-spec-img').setAttribute('width', fw); + document.getElementById('nav-spec-img').setAttribute('height', fh); document.getElementById('nav-disp-filter').setAttribute('scale', maxDisplacement); const isChrome = /Chrome/.test(navigator.userAgent) && !/Edg|Firefox/.test(navigator.userAgent); diff --git a/www/site.webmanifest b/www/site.webmanifest new file mode 100644 index 0000000..45dc8a2 --- /dev/null +++ b/www/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/www/style.css b/www/style.css index 49a852a..095ea85 100644 --- a/www/style.css +++ b/www/style.css @@ -14,187 +14,206 @@ body { width: 99%; max-height: 280px; overflow: hidden; - margin: 5px 5px 10px 5px; /* 5px on top/left/right, 10px on bottom */ - border-radius: 35px; /* Rounded corners */ + margin: 5px 5px 10px 5px; + border-radius: 25px; + display: flex; + border: 4px solid rgba(196, 214, 226, 0.9); /* eww .box border */ + align-items: center; /* Vertically centre the image within the container */ } .banner img { - width: 100%; /* Stretch image to fill the banner width */ - height: 100%; /* Fill the banner height */ - object-fit: cover; /* Crop and center the image rather than squishing it */ - object-position: center top; /* Anchor to the top so the most important part of the image stays visible */ - display: block; /* Remove the default inline gap below images */ + width: 100%; + object-fit: cover; + object-position: center center; + display: block; } .card { - width: min(880px, 88%); /* Cap width at 880px, but shrink to 88% of viewport on small screens */ - height: 540px; /* Fixed height */ - padding: 40px; /* Inner spacing on all sides */ - border-radius: 50px; /* Rounded corners */ - text-align: center; /* Center all text content */ - background: rgba(255, 255, 255, 0.08); /* Very subtle white tint — more transparent than before so the background breathes through */ - border: 2px solid rgba(255, 255, 255, 1); /* Slightly brighter border for a crisper glass edge */ - backdrop-filter: blur(8px) saturate(1.8) brightness(1.05); /* Firefox fallback — blur, colour boost, and slight brightness lift; Chrome overrides this via JS with the SVG refraction filter */ - -webkit-backdrop-filter: blur(8px) saturate(1.8) brightness(1.05); /* Webkit prefix for Safari compatibility */ + width: min(880px, 88%); + height: 320px; /* scaled from 540px proportionally for 480px monitor */ + padding: 28px; /* scaled from 40px */ + border-radius: 25px; /* matches eww .box border-radius */ + text-align: center; + background: rgba(242, 242, 243, 0.6); /* eww .box background-color */ + border: 4px solid rgba(196, 214, 226, 0.9); /* eww .box border */ + backdrop-filter: blur(8px) saturate(1.4) brightness(1.02); + -webkit-backdrop-filter: blur(8px) saturate(1.4) brightness(1.02); box-shadow: - 0 24px 60px rgba(0, 0, 0, 0.35), /* Large soft drop shadow for depth/lift */ - 0 0 0 1px rgba(255, 255, 255, 0.08); /* Hairline outer glow ring */ - position: relative; /* Required so ::before/::after pseudo-elements position relative to the card */ - overflow: hidden; /* Clip pseudo-elements to the card's rounded corners */ + 0 2px 8px rgba(0, 0, 0, 0.15), /* eww notification box-shadow */ + inset 0 0 2px rgba(0, 0, 0, 0.2); /* eww .box inset shadow */ + position: relative; + overflow: hidden; } - + /* ── Main specular: top-left corner catch ── */ .card::before { - content: ''; /* Required to render a pseudo-element with no text */ - position: absolute; /* Layer it on top of the card without affecting layout */ - inset: 0; /* Stretch to fill all four edges of the card */ - border-radius: inherit; /* Match the card's rounded corners */ + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; background: radial-gradient( - ellipse 60% 30% at 10% -5%, /* Tighter ellipse originating just above the top-left corner */ - rgba(255, 255, 255, 0.28) 0%, /* Bright white at the light source center */ - transparent 55% /* Fade out before reaching the middle of the card */ + ellipse 60% 30% at 10% -5%, + rgba(255, 255, 255, 0.35) 0%, /* brighter on light bg */ + transparent 55% ), linear-gradient( - 128deg, /* Diagonal direction: top-left → bottom-right */ - rgba(255, 255, 255, 0.13) 0%, /* Broad glancing sheen starting at the top-left corner */ - rgba(255, 255, 255, 0.04) 30%, /* Dim mid-point to keep the fade gradual */ - transparent 55% /* Fades out before the center */ + 128deg, + rgba(255, 255, 255, 0.20) 0%, + rgba(255, 255, 255, 0.08) 30%, + transparent 55% ); - pointer-events: none; /* Prevent this overlay from blocking mouse interaction */ + pointer-events: none; } - -/* ── Glass rim: inset edge highlights ── */ + +/* ── Glass rim: inset edge highlights — matches eww border colour ── */ .card::after { - content: ''; /* Required to render the pseudo-element */ - position: absolute; /* Layer over the card without shifting layout */ - inset: 0; /* Fill the card edge to edge */ - border-radius: inherit; /* Match card rounding */ - background: transparent; /* No fill — only the inset shadow matters here */ - border: 1px solid transparent; /* Placeholder border so box-shadow inset renders correctly on all sides */ - border-image: none; /* Ensure no gradient border overrides the transparent border */ + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; + background: transparent; + border: 1px solid transparent; + border-image: none; box-shadow: - inset 1px 1px 0 rgba(218, 218, 218, 0.55), /* Bright top and left inner edge — simulates light hitting the glass rim */ - inset -1px -1px 0 rgba(0, 0, 0, 0.12); /* Darker bottom and right inner edge — simulates shadow on the far side */ - pointer-events: none; /* Let clicks pass through to card content */ + inset 1px 1px 0 rgba(196, 214, 226, 0.8), /* eww border colour as rim light */ + inset -1px -1px 0 rgba(0, 0, 0, 0.08); + pointer-events: none; } - + h1 { - font-size: clamp(36px, 6vw, 52px); /* Fluid size: min 36px, scales with viewport, max 52px */ - font-weight: 300; /* Light weight for an elegant look */ - line-height: 1.1; /* Tight leading for large display text */ - color: rgba(255, 255, 255, 0.92); /* Near-white, slightly transparent */ + font-size: clamp(24px, 5vw, 38px); /* scaled down for smaller monitor */ + font-weight: 300; + line-height: 1.1; + color: rgba(35, 38, 41, 0.92); /* eww $text-color #232629 */ + text-shadow: 0 0 2px rgba(0, 0, 0, 0.3); /* eww label.time text-shadow */ } - + h1 em { - font-style: italic; /* Standard italic for emphasis */ - color: rgba(180, 210, 255, 0.85); /* Cool blue tint for italicised words */ + font-style: italic; + color: rgba(137, 180, 250, 0.9); /* eww $primary-neon #89b4fa */ } - + .divider { - width: 40px; /* Short horizontal rule */ - height: 0.5px; /* Hairline thickness */ - background: rgba(255, 255, 255, 0.2); /* Faint white line */ - margin: 22px auto; /* Vertical spacing + horizontal centering */ + width: 40px; + height: 0.5px; + background: rgba(196, 214, 226, 0.8); /* eww border colour */ + margin: 16px auto; /* scaled from 22px */ } - + p { - font-size: 15px; - font-weight: 300; /* Light weight to match the heading style */ - line-height: 1.75; /* Generous leading for readability */ - color: rgba(255, 255, 255, 0.52); /* Dimmed white — secondary text hierarchy */ + font-size: 14px; /* scaled from 15px */ + font-weight: 300; + line-height: 1.75; + color: rgba(35, 38, 41, 0.52); /* eww $text-color at reduced opacity */ } - -/* ── Nav pill wrapper — sits below banner, pins to top on scroll ── */ + +/* ── Nav pill wrapper ── */ .nav-wrap { - align-self: stretch; /* Override body align-items:center — makes this child full width */ + align-self: stretch; display: flex; - justify-content: center; /* Centre the pill inside the full-width container */ - padding: 8px 0; + justify-content: center; + padding: 6px 0; /* scaled from 8px */ } - + .nav-wrap.pinned { position: fixed; top: 0; left: 0; right: 0; z-index: 100; - padding: 8px 0; + padding: 6px 0; display: flex; justify-content: center; } - + .nav-placeholder { display: none; align-self: stretch; - height: 60px; + height: 56px; /* scaled: 44px pill + 6px + 6px padding */ } - + .nav-placeholder.visible { display: block; } - + /* ── The pill itself ── */ .nav-pill { + position: relative; /* anchor for the absolute dropdown */ width: 160px; border-radius: 999px; - background: rgba(255, 255, 255, 0.08); - border: 1px solid rgba(255, 255, 255, 0.30); - backdrop-filter: blur(8px) saturate(1.8) brightness(1.05); - -webkit-backdrop-filter: blur(8px) saturate(1.8) brightness(1.05); + position: relative; + z-index: 100; + background: rgba(242, 242, 243, 0.6); + border: 4px solid rgba(196, 214, 226, 0.9); + backdrop-filter: blur(8px) saturate(1.4) brightness(1.02); + -webkit-backdrop-filter: blur(8px) saturate(1.4) brightness(1.02); box-shadow: - 0 8px 32px rgba(0, 0, 0, 0.25), - inset 1px 1px 0 rgba(255, 255, 255, 0.45), - inset -1px -1px 0 rgba(0, 0, 0, 0.10); - overflow: hidden; + 0 2px 8px rgba(0, 0, 0, 0.15), + inset 0 0 2px rgba(0, 0, 0, 0.2); + /* no overflow:hidden — that would clip the absolute dropdown */ transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1), border-radius 0.25s cubic-bezier(0.4, 0, 0.2, 1); } -/* ── Pill expands and corners soften when open ── */ +.nav-pill-bar { + overflow: hidden; /* clip bar content to pill border-radius */ + border-radius: inherit; + display: flex; + align-items: center; + justify-content: space-between; + height: 40px; + padding: 0 16px; + cursor: pointer; + user-select: none; +} + +.nav-dropdown { + position: absolute; /* float over page — doesn't push content down */ + top: calc(100% + 4px); /* gap between pill bar and dropdown */ + left: 50%; + transform: translateX(-50%); /* centre under the pill */ + width: 100%; /* match pill width */ + max-height: 0; + opacity: 0; + overflow: hidden; + background: rgba(242, 242, 243, 0.6); + border: 4px solid rgba(196, 214, 226, 0.9); + border-radius: 22px; + backdrop-filter: blur(8px) saturate(1.4) brightness(1.02); + -webkit-backdrop-filter: blur(8px) saturate(1.4) brightness(1.02); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + z-index: 101; + transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1) 0.22s, + opacity 0.25s ease 0.22s; +} + .nav-pill.open { border-radius: 22px; width: 200px; } - -/* ── The always-visible top bar: logo + chevron ── */ -.nav-pill-bar { - display: flex; - align-items: center; - justify-content: space-between; - height: 44px; - padding: 0 18px; - cursor: pointer; - user-select: none; -} - + .nav-logo { - font-size: 14px; + font-size: 13px; font-weight: 400; - color: rgba(255, 255, 255, 0.88); + color: rgba(35, 38, 41, 0.88); /* eww $text-color */ letter-spacing: 0.06em; } -/* ── Chevron rotates 180° when open ── */ .nav-chevron { - width: 16px; - height: 16px; + width: 14px; + height: 14px; flex-shrink: 0; transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); } -.nav-pill.open .nav-chevron { - transform: rotate(180deg); +/* Restyle chevron stroke to dark to match eww theme */ +.nav-chevron polyline { + stroke: rgba(35, 38, 41, 0.7); /* eww $text-color */ } -/* ── Dropdown — hidden by default, slides down when open ── */ -.nav-dropdown { - max-height: 0; - opacity: 0; - overflow: hidden; - /* Opening: wait for width to finish first, then drop down */ - transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1) 0.22s, - opacity 0.25s ease 0.22s; +.nav-pill.open .nav-chevron { + transform: rotate(180deg); } .nav-pill.open .nav-dropdown { @@ -202,13 +221,11 @@ p { opacity: 1; } -/* Closing: dropdown collapses immediately (no delay), width waits after */ .nav-pill:not(.open) .nav-dropdown { transition: max-height 0.2s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.15s ease; } -/* Width/radius collapse waits for dropdown to finish */ .nav-pill:not(.open) { transition: width 0.25s cubic-bezier(0.4, 0, 0.2, 1) 0.2s, border-radius 0.25s cubic-bezier(0.4, 0, 0.2, 1) 0.2s; @@ -216,22 +233,22 @@ p { .nav-divider { height: 1px; - background: rgba(255, 255, 255, 0.12); - margin: 0 14px; + background: rgba(196, 214, 226, 0.8); /* eww .spacer border colour */ + margin: 0 12px; } .nav-link { display: block; - padding: 11px 18px; - font-size: 14px; + padding: 10px 16px; + font-size: 13px; font-weight: 300; - color: rgba(255, 255, 255, 0.70); + text-align: center; + color: rgba(35, 38, 41, 0.75); /* eww $text-color */ text-decoration: none; - transition: color 0.15s ease, - background 0.15s ease; + transition: color 0.15s ease, background 0.15s ease; } .nav-link:hover { - color: rgba(255, 255, 255, 0.95); - background: rgba(255, 255, 255, 0.06); + color: rgba(137, 180, 250, 1); /* eww $primary-neon on hover */ + background: rgba(196, 214, 226, 0.25); /* soft eww border colour tint */ } \ No newline at end of file