diff --git a/assets/styles/main.css b/assets/styles/main.css index 3a2c09b..30b5af7 100644 --- a/assets/styles/main.css +++ b/assets/styles/main.css @@ -151,8 +151,7 @@ body { } .masthead, -.grid, -.brand { +.grid { position: relative; z-index: 2; } @@ -201,39 +200,8 @@ body { text-shadow: 0 1px 3px rgb(0 0 0 / 0.55); } -/* ========================================================================= - Brand footer — quiet Screenly lockup in the corner - ========================================================================= */ -.brand { - display: flex; - align-items: center; - justify-content: flex-end; - gap: 0.7em; - padding-block-start: clamp(0.4rem, 1.2vmin, 0.9rem); - border-block-start: 1px solid var(--hairline); -} - -.brand-by { - font-size: max(10px, 0.6rem); - text-transform: uppercase; - letter-spacing: 0.22em; - color: var(--ink-dim); - text-shadow: 0 1px 3px rgb(0 0 0 / 0.55); -} - -.brand-logo { - block-size: max(14px, 0.95rem); - inline-size: auto; - filter: drop-shadow(0 0.05em 0.4em rgb(0 0 0 / 0.45)); -} - -.brand-url { - font-size: max(10px, 0.6rem); - text-transform: uppercase; - letter-spacing: 0.22em; - color: var(--ink-dim); - text-shadow: 0 1px 3px rgb(0 0 0 / 0.55); -} +/* The footer Screenly badge is the kit's standardized fixed corner .brand + (prepended from styles/brand.css); no app-specific badge rules needed. */ /* ========================================================================= Grid of city cards @@ -464,9 +432,7 @@ body { /* Very small displays (Pi touch 480x800 / 800x480): tighten the masthead so the grid keeps the most room. */ @media (max-height: 500px), (max-width: 540px) { - .masthead-meta, - .brand-by, - .brand-url { + .masthead-meta { display: none; } } diff --git a/build.ts b/build.ts index 7cfe9f6..b15261b 100644 --- a/build.ts +++ b/build.ts @@ -8,12 +8,23 @@ // site works unchanged whether it is served from a domain root or from a // project subpath like https://.github.io/world-clock/. +import { readFileSync } from 'node:fs' import { cp, mkdir, rm } from 'node:fs/promises' import { bundleJs, injectGate, processCss } from '@screenly-labs/signage-kit/build' import { run as syncFonts } from './sync-fonts.ts' const DIST = 'dist' +// The standardized fixed footer badge from @screenly-labs/signage-kit, prepended +// to this app's main.css. Only brand.css (not the kit's fonts.css): this app uses +// RELATIVE asset paths (../fonts/...) for Pages-subpath portability, while the +// kit's fonts.css hard-codes /static/fonts/, so this app keeps its own relative +// @font-face and only shares the path-agnostic badge rules. +const brandCss = readFileSync( + Bun.resolveSync('@screenly-labs/signage-kit/styles/brand.css', import.meta.dir), + 'utf8' +) + // Vendor the Bun-managed webfonts into ./assets/fonts before copying them on. await syncFonts() @@ -34,7 +45,7 @@ try { console.log(`✓ JS: ${DIST}/main.js`) try { - const css = await processCss(await Bun.file('assets/styles/main.css').text(), { + const css = await processCss(`${brandCss}\n${await Bun.file('assets/styles/main.css').text()}`, { includeDegraded: true, filename: 'assets/styles/main.css' }) diff --git a/bun.lock b/bun.lock index 78e3041..e1ca674 100644 --- a/bun.lock +++ b/bun.lock @@ -5,9 +5,7 @@ "": { "name": "world-clock", "dependencies": { - "@fontsource-variable/fraunces": "^5.2.9", - "@fontsource-variable/hanken-grotesk": "^5.2.8", - "@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.0", + "@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.2", }, "devDependencies": { "@biomejs/biome": "^2.5.1", @@ -90,11 +88,19 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], + "@fontsource-variable/bricolage-grotesque": ["@fontsource-variable/bricolage-grotesque@5.2.10", "", {}, "sha512-5EDsCqgGpKVcJWE4sg9ydli+t5WM97mISYw5lla/Ev4z71FwXh1oN0YUU8xjkRW9+wBCGD9R+ntAvI8G4bUFJg=="], + "@fontsource-variable/fraunces": ["@fontsource-variable/fraunces@5.2.9", "", {}, "sha512-Y6IjunlN9Ni723np+GIgAaKzCDBrPRrqNi01TZxHs5wtHYROWFM9W6yiT+/gGwSjWIRD18oX17kD/BRWekc/Lw=="], "@fontsource-variable/hanken-grotesk": ["@fontsource-variable/hanken-grotesk@5.2.8", "", {}, "sha512-K7hu09ZKReBc7EifRLeM4K94NZBrxFEg0nGcISmVwlFQOJo4EmYkLXTWEwr5JcNW4z2hr5zy8vLS2sxC8JDmrQ=="], - "@screenly-labs/signage-kit": ["@screenly-labs/signage-kit@github:Screenly-Labs/signage-kit#eb470fb", { "peerDependencies": { "@csstools/postcss-cascade-layers": "^6", "browserslist": "^4", "esbuild": "^0.28", "lightningcss": "^1.32", "postcss": "^8" }, "optionalPeers": ["@csstools/postcss-cascade-layers", "postcss"] }, "Screenly-Labs-signage-kit-eb470fb", "sha512-acuAb2R/77crUjgnT9GFVlNdpgUTzvK5OLRRsZsZ30dZcJ7ThH/f8al2janEIJWC1JoyqTiarJ2x1uAH6In86A=="], + "@fontsource-variable/jetbrains-mono": ["@fontsource-variable/jetbrains-mono@5.2.8", "", {}, "sha512-WBA9elru6Jdp5df2mES55wuOO0WIrn3kpXnI4+W2ek5u3ZgLS9XS4gmIlcQhiZOWEKl95meYdvK7xI+ETLCq/Q=="], + + "@fontsource-variable/newsreader": ["@fontsource-variable/newsreader@5.2.10", "", {}, "sha512-MdI2iRwrqWpMOU/2aV2BgfZ4dJNlj/XlYaY8Zb7t87mWqHskYW0XiUANkt1cyOCiEfW2VQ0bQ5vZgGPp6B2B4w=="], + + "@fontsource/space-mono": ["@fontsource/space-mono@5.2.9", "", {}, "sha512-b61faFOHEISQ/pD25G+cfGY9o/WW6lRv6hBQQfpWvEJ4y1V+S4gmth95EVyBE2VL3qDYHeVQ8nBzrplzdXTDDg=="], + + "@screenly-labs/signage-kit": ["@screenly-labs/signage-kit@github:Screenly-Labs/signage-kit#b7f3d44", { "dependencies": { "@fontsource-variable/bricolage-grotesque": "^5.2.10", "@fontsource-variable/fraunces": "^5.2.9", "@fontsource-variable/hanken-grotesk": "^5.2.8", "@fontsource-variable/jetbrains-mono": "^5.2.8", "@fontsource-variable/newsreader": "^5.2.10", "@fontsource/space-mono": "^5.2.9" }, "peerDependencies": { "@csstools/postcss-cascade-layers": "^6", "browserslist": "^4", "esbuild": "^0.28", "lightningcss": "^1.32", "postcss": "^8" }, "optionalPeers": ["@csstools/postcss-cascade-layers", "postcss"] }, "Screenly-Labs-signage-kit-b7f3d44", "sha512-42YdnSCPpYpTyMucl1T+FGv3HQeyzz2UDEvYoLdP4EMVAD1m0U1G8WN2hgTE4vFVs3w8hGcqFisWBjkEc26rFA=="], "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], diff --git a/index.html b/index.html index 046e9eb..c0dde84 100644 --- a/index.html +++ b/index.html @@ -49,17 +49,15 @@
- + + Screenly + diff --git a/package.json b/package.json index c12dcad..95c8bf0 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,7 @@ }, "license": "AGPL-3.0-only", "dependencies": { - "@fontsource-variable/fraunces": "^5.2.9", - "@fontsource-variable/hanken-grotesk": "^5.2.8", - "@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.0" + "@screenly-labs/signage-kit": "github:Screenly-Labs/signage-kit#2026.7.2" }, "devDependencies": { "@biomejs/biome": "^2.5.1", diff --git a/src/main.ts b/src/main.ts index 4816ae3..8c1cdcf 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,6 +7,7 @@ // Side-effect import: installs the replaceChildren shim for the older-browser // degraded mode (shared across all apps). Must stay first. import '@screenly-labs/signage-kit/polyfills' +import { removeScreenlyBranding } from '@screenly-labs/signage-kit/branding' import { buildFormatters, type ClockConfig, @@ -166,15 +167,6 @@ const layoutGrid = (grid: HTMLElement, cards: ClockCard[]): void => { } } -// On a Screenly player the viewer is already a Screenly customer, so the -// promotional Screenly badge is removed. The 'screenly-viewer' token in the -// user agent marks these devices; every other browser keeps the badge. -const removeScreenlyBranding = (): void => { - if (navigator.userAgent.includes('screenly-viewer')) { - document.querySelector('.brand')?.remove() - } -} - const start = (): void => { removeScreenlyBranding() const config = parseClocks(window.location.search) diff --git a/sync-fonts.ts b/sync-fonts.ts index 01db7c0..5d028cc 100644 --- a/sync-fonts.ts +++ b/sync-fonts.ts @@ -1,40 +1,13 @@ #!/usr/bin/env bun -// Copies the self-hosted webfont files out of the Bun-managed @fontsource -// packages into ./assets/fonts, where the build picks them up and ships them to -// ./fonts in the static site. Bun owns the font versions (package.json); this -// step vendors the exact files we serve ourselves — no CDN. -// -// Fonts: Fraunces (display serif, "standard" axis = opsz + wght, normal + -// italic) for the time; Hanken Grotesk for metadata. +// Vendor this app's webfonts into ./assets/fonts. The files, versions, and copy +// logic all live in @screenly-labs/signage-kit — this just names the families +// the board uses (Fraunces time digits + Hanken Grotesk chrome) and the dest +// dir (this app keeps a relative ../fonts/ layout, not /static/fonts). -const FONTS = [ - '@fontsource-variable/fraunces/files/fraunces-latin-standard-normal.woff2', - '@fontsource-variable/fraunces/files/fraunces-latin-standard-italic.woff2', - '@fontsource-variable/hanken-grotesk/files/hanken-grotesk-latin-wght-normal.woff2' -] -const DEST_DIR = 'assets/fonts' +import { syncFonts } from '@screenly-labs/signage-kit/sync-fonts' -export const run = async (): Promise => { - let count = 0 +export const run = (): Promise => syncFonts(['fraunces', 'hanken-grotesk'], 'assets/fonts') - for (const rel of FONTS) { - const file = rel.split('/').pop() - const src = Bun.file(`node_modules/${rel}`) - - if (!(await src.exists())) { - console.error(`✗ Missing ${file} — run \`bun install\` first.`) - process.exit(1) - } - - await Bun.write(`${DEST_DIR}/${file}`, src) - console.log(`✓ Font: ${DEST_DIR}/${file}`) - count++ - } - - console.log(`Fonts synced — ${count} file(s) vendored from @fontsource.`) -} - -// Allow running standalone: `bun run sync-fonts.ts`. if (import.meta.main) { await run() }