diff --git a/.DS_Store b/.DS_Store index a3236e6..20d52eb 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/CSS/styles.css b/CSS/styles.css index 4df5f05..01c891a 100644 --- a/CSS/styles.css +++ b/CSS/styles.css @@ -48,6 +48,218 @@ body.dark-theme { --shadow: 0 24px 80px oklch(8% 0.01 50 / 0.38); } +body.intro-active { + overflow: hidden; +} + +body.intro-active .app-shell { + pointer-events: none; + user-select: none; +} + +.intro-overlay { + --intro-bg: #111111; + --intro-fg: #fafafa; + --intro-border: #e5e5e5; + --intro-accent: #2f6feb; + --intro-tile-empty: #3a3a3c; + --intro-tile-wrong: #787c7e; + --intro-tile-misplaced: #c9b458; + --intro-tile-correct: #6aaa64; + --intro-font-mono: ui-monospace, "JetBrains Mono", monospace; + + position: fixed; + inset: 0; + z-index: 1000; + display: grid; + min-block-size: 100svh; + place-items: center; + overflow: hidden; + background: linear-gradient(180deg, #181818 0%, var(--intro-bg) 58%, #080808 100%); + color: var(--intro-fg); + font-family: var(--font-body); + opacity: 1; + perspective: 1200px; + transition: opacity 520ms ease, visibility 520ms ease; + visibility: visible; +} + +.intro-overlay::before, +.intro-overlay::after { + content: ""; + position: absolute; + inset-inline: 0; + block-size: 20vh; + z-index: 4; + pointer-events: none; +} + +.intro-overlay::before { + inset-block-start: 0; + background: linear-gradient(180deg, rgba(17, 17, 17, 0.85), transparent); +} + +.intro-overlay::after { + inset-block-end: 0; + background: linear-gradient(0deg, rgba(17, 17, 17, 0.88), transparent); +} + +.intro-overlay.is-dismissing { + opacity: 0; + pointer-events: none; + visibility: hidden; +} + +.intro-overlay[hidden] { + display: none; +} + +.intro-stage { + position: relative; + display: grid; + inline-size: min(1120px, calc(100vw - 32px)); + block-size: min(640px, calc(100svh - 32px)); + min-block-size: 420px; + place-items: center; + transform-style: preserve-3d; +} + +.intro-scanline { + position: absolute; + inset-inline: 10%; + inset-block-start: 50%; + z-index: 1; + block-size: 1px; + background: linear-gradient(90deg, transparent, rgba(250, 250, 250, 0.36), transparent); + opacity: 0; + transform: translateY(-50%); + animation: intro-scan 4.8s ease forwards; +} + +.intro-tiles { + --intro-tile-size: clamp(46px, 10vw, 128px); + --intro-tile-gap: clamp(6px, 1.4vw, 16px); + + position: relative; + z-index: 2; + display: grid; + grid-template-columns: repeat(6, var(--intro-tile-size)); + gap: var(--intro-tile-gap); + transform-origin: 50% 50%; + transform-style: preserve-3d; + transition: gap 420ms cubic-bezier(0.2, 0.7, 0.15, 1), transform 520ms cubic-bezier(0.2, 0.7, 0.15, 1); +} + +.intro-tile { + position: relative; + inline-size: var(--intro-tile-size); + block-size: var(--intro-tile-size); + opacity: 0; + transform: translate3d(0, 34px, -180px); + transform-style: preserve-3d; + animation: intro-tile-enter 520ms cubic-bezier(0.2, 0.7, 0.15, 1) forwards; + animation-delay: calc(var(--intro-index) * 56ms); +} + +.intro-letter { + position: absolute; + inset: 0; + display: grid; + place-items: center; + border: 1px solid rgba(229, 229, 229, 0.18); + background: var(--intro-tile-empty); + box-shadow: inset 0 0 0 1px rgba(250, 250, 250, 0.08); + color: var(--intro-fg); + font-family: var(--font-body); + font-size: clamp(28px, 6vw, 78px); + font-weight: 900; + line-height: 1; + text-transform: uppercase; + transform-origin: 50% 50%; +} + +.intro-tile.is-flipping .intro-letter { + animation: intro-split-flap 260ms cubic-bezier(0.3, 0.7, 0.2, 1); +} + +.intro-tile[data-status="wrong"] .intro-letter { + background: var(--intro-tile-wrong); +} + +.intro-tile[data-status="misplaced"] .intro-letter { + background: var(--intro-tile-misplaced); +} + +.intro-tile[data-status="correct"] .intro-letter { + background: var(--intro-tile-correct); +} + +.intro-tile:nth-child(1) { --intro-index: 0; } +.intro-tile:nth-child(2) { --intro-index: 1; } +.intro-tile:nth-child(3) { --intro-index: 2; } +.intro-tile:nth-child(4) { --intro-index: 3; } +.intro-tile:nth-child(5) { --intro-index: 4; } +.intro-tile:nth-child(6) { --intro-index: 5; } + +.intro-tiles.is-solved .intro-tile { + opacity: 1; + animation: intro-logo-cascade 680ms cubic-bezier(0.18, 0.85, 0.22, 1) calc(var(--intro-index) * 76ms) both; +} + +.intro-tiles.is-logo { + gap: clamp(3px, 0.7vw, 8px); + transform: scale(0.88); +} + +.intro-tiles.is-logo .intro-letter { + border-color: rgba(250, 250, 250, 0.28); + box-shadow: inset 0 0 0 1px rgba(250, 250, 250, 0.1), 0 0 28px rgba(106, 170, 100, 0.16); +} + +.intro-caption { + position: absolute; + inset-block-end: clamp(24px, 6vh, 64px); + inset-inline: 24px; + z-index: 5; + display: flex; + justify-content: center; + color: rgba(250, 250, 250, 0.62); + font-family: var(--intro-font-mono); + font-size: 12px; + letter-spacing: 0.08em; + text-transform: uppercase; + opacity: 0; + animation: intro-caption-cue 4.8s ease forwards; +} + +.intro-skip { + position: fixed; + inset-block-start: 16px; + inset-inline-end: 16px; + z-index: 10; + min-height: 40px; + border: 1px solid rgba(229, 229, 229, 0.22); + border-radius: 999px; + padding: 0 16px; + background: rgba(17, 17, 17, 0.74); + color: var(--intro-fg); + cursor: pointer; + font: 800 0.85rem/1 var(--font-body); +} + +.intro-skip:hover { + border-color: rgba(250, 250, 250, 0.5); +} + +.intro-skip:focus-visible { + outline: 2px solid var(--intro-accent); + outline-offset: 3px; +} + +.intro-overlay.restarting * { + animation: none !important; +} + button, a { font: inherit; @@ -800,6 +1012,106 @@ h2 { text-align: start; } +@keyframes intro-tile-enter { + 0% { + transform: translate3d(0, 34px, -180px); + filter: blur(2px); + opacity: 0; + } + + 100% { + transform: translate3d(0, 0, 0); + filter: blur(0); + opacity: 1; + } +} + +@keyframes intro-split-flap { + 0% { + transform: rotateX(0deg); + filter: brightness(1); + } + + 49% { + transform: rotateX(-88deg); + filter: brightness(0.72); + } + + 50% { + transform: rotateX(88deg); + filter: brightness(1.12); + } + + 100% { + transform: rotateX(0deg); + filter: brightness(1); + } +} + +@keyframes intro-logo-cascade { + 0% { + transform: translate3d(0, 0, 0) scale(1); + filter: brightness(1); + } + + 34% { + transform: translate3d(0, -22%, 130px) scale(1.18); + filter: brightness(1.16); + } + + 62% { + transform: translate3d(0, 4%, 0) scale(0.98); + filter: brightness(1.04); + } + + 100% { + transform: translate3d(0, 0, 0) scale(1); + filter: brightness(1); + } +} + +@keyframes intro-scan { + 0%, + 12% { + opacity: 0; + transform: translateY(-50%) scaleX(0.2); + } + + 24% { + opacity: 0.75; + } + + 54% { + opacity: 0.22; + transform: translateY(-50%) scaleX(1); + } + + 72%, + 100% { + opacity: 0; + } +} + +@keyframes intro-caption-cue { + 0%, + 18% { + opacity: 0; + transform: translateY(8px); + } + + 28%, + 64% { + opacity: 1; + transform: translateY(0); + } + + 82%, + 100% { + opacity: 0; + transform: translateY(-8px); + } +} + @keyframes shake { 10%, 90% { transform: translateX(-4%); } 30%, 70% { transform: translateX(5%); } @@ -814,6 +1126,39 @@ h2 { 100% { transform: translateY(0); } } +@media (max-width: 720px) { + .intro-stage { + min-block-size: 420px; + } + + .intro-tiles { + --intro-tile-size: min(13.5vw, 56px); + --intro-tile-gap: 5px; + } + + .intro-caption { + font-size: 10px; + } + + .intro-skip { + min-height: 38px; + padding-inline: 14px; + } +} + +@media (prefers-reduced-motion: reduce) { + .intro-overlay, + .intro-tiles, + .intro-tile, + .intro-letter, + .intro-scanline, + .intro-caption { + animation-duration: 1ms !important; + animation-delay: 0ms !important; + transition-duration: 1ms !important; + } +} + @media (max-width: 780px) { .app-shell { width: min(100% - 20px, 600px); diff --git a/fancy-wordle-modern.html b/fancy-wordle-modern.html index 7e64855..74d2c6a 100644 --- a/fancy-wordle-modern.html +++ b/fancy-wordle-modern.html @@ -5,14 +5,30 @@