/*
 * omggg.wtf: the home and the 404. One screen, a toy: the word's letters are bodies that home.js
 * runs with Matter.js. The palette and faces follow the Levo page (levo/levo.css,
 * levo/desk.css). Light and dark follow the system.
 */

:root {
	--bg: #F7F7F7;
	--ink: 0 0 0;
	--text: #1D1D1F;
	--glow-a: rgba(122, 150, 255, 0.28);
	--glow-b: rgba(255, 170, 120, 0.24);
	--lift-a: rgba(0, 0, 0, 0.14);
	--lift-b: rgba(0, 0, 0, 0.08);
	--round: ui-rounded, "SF Pro Rounded", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
	color-scheme: light dark;
}
@media (prefers-color-scheme: dark) {
	:root {
		--bg: #070707;
		--ink: 255 255 255;
		--text: #F0F0F0;
		--glow-a: rgba(98, 84, 220, 0.3);
		--glow-b: rgba(40, 120, 200, 0.22);
		--lift-a: rgba(0, 0, 0, 0.55);
		--lift-b: rgba(0, 0, 0, 0.35);
	}
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; overflow: hidden; overscroll-behavior: none; }
/* The page colour on html, so it's under everything: the status bar, the browser's bars, the
   home indicator, and anywhere the page is pulled past its edges. */
html { background-color: var(--bg); color-scheme: light dark; -webkit-text-size-adjust: 100%; }
/* The glow on a layer as tall as the largest viewport (bars hidden), behind the scene. */
body::before {
	content: "";
	position: fixed;
	left: 0;
	right: 0;
	top: 0;
	height: 100vh;
	height: 100lvh;
	pointer-events: none;
	background:
		radial-gradient(50% 55% at 50% 0%, var(--glow-a) 0%, transparent 70%),
		radial-gradient(40% 50% at 88% 100%, var(--glow-b) 0%, transparent 70%);
}
body {
	color: var(--text);
	font-family: var(--round);
	-webkit-font-smoothing: antialiased;
	-webkit-user-select: none;
	user-select: none;
	-webkit-tap-highlight-color: transparent;
}
a { color: inherit; text-decoration: none; }
::selection { background: rgba(0, 178, 255, 0.3); }

/* The scene fills the window. Its padding is the safe area: home.js keeps the word and the
   letters' walls and floor inside it. */
.toy {
	position: fixed;
	inset: 0;
	overflow: hidden;
	touch-action: manipulation;
	padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
.toy-title { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* The letters: one canvas each, placed by home.js. */
.toy-letters { position: absolute; inset: 0; pointer-events: none; }
.lt { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
/* The drop shadow scales with the letter (--k: its size against the word's), so small ones look the same. */
.lt { --k: 1; filter: drop-shadow(0 calc(14px * var(--k)) calc(18px * var(--k)) var(--lift-a)) drop-shadow(0 calc(3px * var(--k)) calc(4px * var(--k)) var(--lift-b)); will-change: transform; }
.toy.is-still .lt { will-change: auto; }
.toy.can-grab { cursor: grab; }
.toy.is-held, .toy.is-held * { cursor: grabbing !important; }

/* The links: plain text in the page's ink. On hover the words hop and grow bolder (the hop is on
   an inner span, so it never fights the entrance). */
.lk { display: inline-block; font-size: 14px; font-weight: 500; letter-spacing: -0.005em; color: var(--text); transition: font-weight .22s ease; }
.lk-host:hover .lk, .lk-host:focus-visible .lk { font-weight: 700; animation: lk-hop .45s cubic-bezier(.34, 1.56, .64, 1); }
.lk-host:focus-visible { outline: 2px solid #00B2FF; outline-offset: 4px; border-radius: 6px; }
@keyframes lk-hop {
	0% { transform: none; }
	40% { transform: translateY(-3px) scale(1.04); }
	75% { transform: translateY(1px); }
	100% { transform: none; }
}

/* Cntxt Labs: alone in the bottom-trailing corner; it pops up from just below the window's edge
   once the word has arrived. */
.cntxt {
	position: fixed;
	right: calc(22px + env(safe-area-inset-right));
	bottom: calc(18px + env(safe-area-inset-bottom));
	z-index: 3;
	transform-origin: 50% 100%;
	animation: rise-in .6s cubic-bezier(.34, 1.56, .64, 1) .85s both;
}
@keyframes rise-in {
	from { transform: translateY(calc(100% + 30px + env(safe-area-inset-bottom))) scale(0.4); }
	to { transform: none; }
}

/* Levo: its icon pops up somewhere clear of the word (home.js picks the place) and dances, as on
   the Left app's review screen. Nested: the outer moves and turns about the centre, the inner
   squashes against the floor (its bottom centre). Lengths are px at a 64 px icon, times --u.
   Its question is hidden until the pointer is on it (or a first tap), then pops up above it. */
.levo {
	--u: 1.0625;
	position: fixed;
	left: 24px;
	top: 24px;
	z-index: 3;
	display: block;
	width: calc(64px * var(--u));
	height: calc(64px * var(--u));
	-webkit-user-drag: none;
	-webkit-tap-highlight-color: transparent;
}
.levo-dance, .levo-squash { display: block; width: 100%; height: 100%; }
.levo-dance { transform-origin: 50% 50%; }
.levo-squash { transform-origin: 50% 100%; }
.levo-icon {
	display: block;
	width: 100%;
	height: 100%;
	border-radius: 22.7%;
	filter: drop-shadow(0 calc(6px * var(--u)) calc(10px * var(--u)) rgba(0, 0, 0, 0.35));
	-webkit-user-drag: none;
}
.toy.is-live .levo:not(.is-in) { visibility: hidden; }
.levo.is-in .levo-icon { animation: levo-in .45s cubic-bezier(.34, 1.56, .64, 1) .06s both; }
.levo.is-dancing .levo-dance { animation: levo-dance .94s both; }
.levo.is-dancing .levo-squash { animation: levo-squash .94s both; }
@keyframes levo-in {
	from { opacity: 0; transform: scale(0.2); }
	to { opacity: 1; transform: none; }
}
/* Crouch, a tilted jump, land, a small hop, settle (bouncy). */
@keyframes levo-dance {
	0% { transform: translateY(0) rotate(0deg); animation-timing-function: ease-in-out; }
	12.77% { transform: translateY(calc(6px * var(--u))) rotate(0deg); animation-timing-function: ease-in-out; }
	38.3% { transform: translateY(calc(-26px * var(--u))) rotate(-9deg); animation-timing-function: ease-in-out; }
	61.7% { transform: translateY(0) rotate(0deg); animation-timing-function: ease-in-out; }
	78.72% { transform: translateY(calc(-10px * var(--u))) rotate(7deg); animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
	100% { transform: translateY(0) rotate(0deg); }
}
@keyframes levo-squash {
	0% { transform: scale(1, 1); animation-timing-function: ease-in-out; }
	12.77% { transform: scale(1.12, 0.82); animation-timing-function: ease-in-out; }
	38.3% { transform: scale(0.94, 1.1); animation-timing-function: ease-in-out; }
	61.7% { transform: scale(1.08, 0.9); animation-timing-function: ease-in-out; }
	78.72% { transform: scale(0.98, 1.04); animation-timing-function: cubic-bezier(.34, 1.56, .64, 1); }
	100% { transform: scale(1, 1); }
}
.levo-q {
	position: absolute;
	left: 50%;
	bottom: calc(100% + 10px);
	translate: -50% 0;
	white-space: nowrap;
	transform-origin: 50% 100%;
	visibility: hidden;
	pointer-events: none;
}
/* It pops once the icon is down from its big jump (0.5 s), so the jump never runs through it. */
@media (hover: hover) {
	.levo:hover .levo-q { visibility: visible; animation: q-pop .5s cubic-bezier(.34, 1.56, .64, 1) .5s both; }
}
.levo.is-armed .levo-q, .levo:focus-visible .levo-q { visibility: visible; animation: q-pop .5s cubic-bezier(.34, 1.56, .64, 1) .5s both; }
@keyframes q-pop {
	from { opacity: 0; transform: translateY(8px) scale(0.4); }
	to { opacity: 1; transform: none; }
}

@media (max-width: 600px) {
	.levo { --u: 0.9; }
}

/* A shake. */
.toy.is-quake { animation: quake .5s cubic-bezier(.36, .07, .19, .97); }
@keyframes quake {
	10%, 90% { translate: -2px 1px; }
	20%, 80% { translate: 5px -2px; }
	30%, 50%, 70% { translate: -9px 3px; }
	40%, 60% { translate: 9px -3px; }
}

@media (prefers-reduced-motion: reduce) {
	.cntxt, .levo.is-in .levo-icon, .levo.is-dancing .levo-dance, .levo.is-dancing .levo-squash, .levo .levo-q { animation: none !important; }
	.lk-host:hover .lk, .lk-host:focus-visible .lk { animation: none; }
	.toy.is-quake { animation: none; }
}
