diff --git a/app.jsx b/app.jsx index 92b8f90..e2dbb5a 100644 --- a/app.jsx +++ b/app.jsx @@ -68,11 +68,46 @@ const GLYPHS = { ], }; -function PixelLogo({ word = "FACERE", scale = 11, gap = 0 }) { +function useResponsiveLogoScale(word = "FACERE") { + const [scale, setScale] = useState(() => computeLogoScale(word)); + useEffect(() => { + let raf = 0; + const onResize = () => { + cancelAnimationFrame(raf); + raf = requestAnimationFrame(() => setScale(computeLogoScale(word))); + }; + window.addEventListener("resize", onResize); + window.addEventListener("orientationchange", onResize); + return () => { + cancelAnimationFrame(raf); + window.removeEventListener("resize", onResize); + window.removeEventListener("orientationchange", onResize); + }; + }, [word]); + return scale; +} + +function computeLogoScale(word) { + // Total logo width = letters * GLYPH_W * scale + (letters-1) * scale * 1.6 + // Solve for scale that fits the viewport with side margins. + if (typeof window === "undefined") return 11; + const vw = window.innerWidth; + const letters = word.length; + const sideMargin = vw < 480 ? 0.10 : vw < 760 ? 0.12 : 0.16; // each side + const usable = vw * (1 - 2 * sideMargin); + const denom = letters * GLYPH_W + (letters - 1) * 1.6; + const fit = Math.floor(usable / denom); + // Clamp so it doesn't get too small or absurdly large on ultrawide. + return Math.max(4, Math.min(11, fit)); +} + +function PixelLogo({ word = "FACERE", scale, gap = 0 }) { + const responsiveScale = useResponsiveLogoScale(word); + const px = scale ?? responsiveScale; const letters = word.split(""); return (
-
+
{letters.map((ch, li) => { const g = GLYPHS[ch]; if (!g) return null; @@ -81,8 +116,8 @@ function PixelLogo({ word = "FACERE", scale = 11, gap = 0 }) { key={li} className="pixel-letter" style={{ - gridTemplateColumns: `repeat(${GLYPH_W}, ${scale}px)`, - gridTemplateRows: `repeat(${GLYPH_H}, ${scale}px)`, + gridTemplateColumns: `repeat(${GLYPH_W}, ${px}px)`, + gridTemplateRows: `repeat(${GLYPH_H}, ${px}px)`, gap: `${gap}px`, }} > @@ -100,10 +135,10 @@ function PixelLogo({ word = "FACERE", scale = 11, gap = 0 }) {
{/* Ghost layers for subtle electric jitter */}
); diff --git a/facere.html b/facere.html index 9b81e78..27eb938 100644 --- a/facere.html +++ b/facere.html @@ -9,7 +9,7 @@ - + @@ -28,6 +28,6 @@ - + diff --git a/styles.css b/styles.css index 7ba69be..103fb4e 100644 --- a/styles.css +++ b/styles.css @@ -905,31 +905,103 @@ a { color: inherit; text-decoration: none; } /* ───────────────── Mobile recompose ───────────────── */ @media (max-width: 760px) { + /* Shorter scroll on phones — 700vh of swiping is exhausting. + The GSAP timeline scrubs by progress (0..1) so the choreography + still plays out, just over a shorter total scroll distance. */ + .scroll-track { height: 480vh; } + + /* Re-aim the camera so the meaningful part of each landscape image + stays roughly in frame on a portrait viewport. */ + .bg-wrap { transform-origin: 70% 60% !important; } + .scene-product .bg-wrap { transform-origin: 55% 70% !important; } + .scene-install .bg-wrap { transform-origin: 70% 55% !important; } + + /* Hero: center the (now responsively sized) logo. */ .content-hero { - align-items: flex-start; - padding: 22vh 8vw 0; + align-items: center; + justify-content: center; + padding: 0 6vw; } - .pixel-letter > * { /* allow scaling? handled by JS, here just nudge */ } - .bg-wrap { transform-origin: 75% 70% !important; } - .scene-product .bg-wrap { transform-origin: 60% 80% !important; } - .scene-install .bg-wrap { transform-origin: 70% 65% !important; } .content-product, .content-install { - padding: 18vh 8vw 0; + padding: 14vh 7vw 14vh; + width: 100%; + max-width: 100%; justify-content: flex-start; + } + + .tag { + font-size: 11px; + letter-spacing: 0.22em; + margin-bottom: 22px; + padding: 7px 12px; + gap: 8px; + } + + .headline { + font-size: clamp(30px, 8.5vw, 52px); + white-space: normal; + line-height: 1.1; + margin-bottom: 22px; + } + .body, .subheadline { + white-space: normal; max-width: 100%; } - .headline { font-size: clamp(34px, 9vw, 56px); white-space: normal; } - .body, .subheadline { white-space: normal; max-width: 100%; } - .cmd-body { font-size: 12px; padding: 14px 14px 16px; } + .body { font-size: clamp(15px, 4vw, 18px); line-height: 1.5; } + .subheadline { font-size: 13px; letter-spacing: 0.16em; margin-bottom: 22px; } + + .cmd-box { font-size: 14px; max-width: 100%; } + .cmd-bar { padding: 7px 10px; font-size: 10px; letter-spacing: 0.14em; } + .cmd-title { display: none; } + .cmd-body { + font-size: 13px; + padding: 14px 12px 16px; + /* Allow long install command to wrap on tiny screens instead of scrolling. */ + white-space: normal; + word-break: break-all; + overflow-x: visible; + } .cmd-hint { display: none; } - .hud-nav { right: 14px; gap: 12px; } + + .docs-link { font-size: 13px; letter-spacing: 0.14em; } + + /* HUD: compact, less metadata, no labels. */ + .hud-brand { top: 16px; left: 14px; font-size: 10px; letter-spacing: 0.32em; } + .hud-meta { + top: 16px; right: 14px; + gap: 8px; + font-size: 10px; + letter-spacing: 0.22em; + } + .hud-meta-line { width: 16px; } + .hud-nav { right: 10px; gap: 14px; } .hud-step-label { display: none; } - .hud-meta { right: 14px; } - .hud-meta-line { width: 18px; } - .hud-brand { left: 14px; } + .scroll-cue { bottom: 18px; } + .scroll-cue-line { height: 28px; } + .chip-glow { width: 180px; height: 180px; margin: -90px 0 0 -90px; } + .arm-left, .arm-right { width: 40px; height: 40px; margin: -20px 0 0 -20px; } +} + +/* Narrow phones — tighten further */ +@media (max-width: 480px) { + .content-product, .content-install { padding: 12vh 6vw 12vh; } + .headline { font-size: clamp(26px, 9vw, 40px); margin-bottom: 18px; } + .body { font-size: 14px; } + .tag { font-size: 10px; padding: 6px 10px; margin-bottom: 18px; } + .cmd-body { font-size: 12px; padding: 12px 10px 14px; } + .docs-link { font-size: 12px; } + .hud-meta span:not(.hud-meta-line) { /* keep depth readout but shrink */ font-size: 9px; } + .scroll-cue-label { font-size: 8px; } +} + +/* Short / landscape phones — pull content tighter so HUD doesn't collide. */ +@media (max-height: 520px) and (max-width: 900px) { + .content-product, .content-install { padding: 9vh 6vw; } + .headline { font-size: clamp(24px, 5vw, 36px); margin-bottom: 14px; } + .scroll-cue { display: none; } } /* Reduced motion */