/* Served from our own box. No web fonts, no analytics, no third-party
   requests of any kind -- which is not a flourish, it is the privacy policy
   being true on the page that states it.

   The palette commits to dark rather than following the system. The studio
   is called Lantern Moth and the one image on the site is a lantern: on a
   cream ground that is a picture of a light, and on this ground it is the
   light. There is no prefers-color-scheme branch for the same reason a
   cinema has no day mode. */
:root {
	--paper: #0d0c12;
	--paper-2: #16151e;
	--paper-3: #1e1c28;
	--rule: #262233;
	--rule-2: #322c42;
	--ink: #f3f0ea;
	--ink-2: #ada6bb;
	--ink-3: #6f6885;
	--flame: #f0c75e;
	--flame-ink: #8a6a22;
	--lit-ink: #1d1304;
	--metal-hi: #6e6780;
	--metal: #46414f;
	--metal-lo: #241f2b;
	--shadow: #00000099;
	--glow: rgba(240, 199, 94, .07);
	/* Dark enough to silhouette against the lamplight, which is where the
	   moths now spend all their time -- they reach 110px and the glow runs
	   to 144px -- and still lighter than the page, so they do not vanish on
	   the rare pass beyond it. */
	--moth: #3d3649;
}
* { box-sizing: border-box; }
html { color-scheme: dark; }
body {
	margin: 0;
	background: var(--paper);
	color: var(--ink);
	font: 16px/1.65 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
	-webkit-text-size-adjust: 100%;
}

/* The lantern's light, spilling onto the page behind it. Fixed and
   pointer-events-none so it is atmosphere and never a surface. */
.glowfield {
	position: fixed; inset: 0; pointer-events: none; z-index: 0;
	will-change: transform;
	background:
		radial-gradient(60rem 40rem at 78% 16%, var(--glow), transparent 68%),
		radial-gradient(40rem 30rem at 12% 88%, rgba(120, 96, 200, .05), transparent 70%);
}
.wrap { position: relative; z-index: 1; max-width: 42rem; margin: 0 auto; padding: 3rem 1.5rem 5rem; }

header {
	display: flex; align-items: center; justify-content: space-between;
	gap: 1.5rem; flex-wrap: wrap;
	border-bottom: 1px solid var(--rule);
	padding-bottom: 1.1rem; margin-bottom: 3rem;
}
.mark {
	display: inline-flex; align-items: center; gap: .55rem;
	font: 700 1.4rem/1 ui-serif, Georgia, "Times New Roman", serif;
	letter-spacing: -.02em; color: var(--ink); text-decoration: none;
}
/* The same lantern as the favicon and the app tile, at wordmark size and
   without its ground -- one drawing, three places, so they cannot drift. */
.mark-lamp { width: 1.45em; height: 1.45em; flex: none; }
.mark-text span { color: var(--flame); }

/* One utility face for every label on the site: section headings, the tag
   in the header, the chips, the meta line. Uppercase monospace at a small
   size reads as an instrument panel, which is the right register for a
   studio and the wrong one for a sentence. */
.tag, h2, .chips, .stamp, .meta {
	font: 500 .72rem/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
	letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3);
}
h1 {
	font: 700 1.9rem/1.15 ui-serif, Georgia, serif;
	margin: 0 0 .5rem; letter-spacing: -.02em; text-wrap: balance;
}
h2 { margin: 0 0 1.1rem; }
h3 {
	font: 700 1.12rem/1.3 ui-serif, Georgia, serif;
	margin: 0 0 .4rem; color: var(--ink); letter-spacing: -.01em;
}
p, li { color: var(--ink-2); }
li { margin-bottom: .35rem; }
a { color: var(--flame); }
.stamp { text-transform: none; letter-spacing: .04em; }
.card {
	background: var(--paper-2); border: 1px solid var(--rule);
	border-radius: 12px; padding: 1.1rem 1.35rem; margin: 1.25rem 0;
}
footer {
	display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
	margin-top: 4.5rem; padding-top: 1.25rem; border-top: 1px solid var(--rule);
	font-size: .85rem; color: var(--ink-3);
}
footer a { color: var(--ink-3); }

/* ---- home ---------------------------------------------------------- */

.home .wrap { max-width: 60rem; }

.hero {
	display: grid;
	grid-template-columns: 1fr minmax(0, 18.5rem);
	gap: 3rem;
	align-items: center;
	margin: 1rem 0 0;
}
.hero h1 {
	font: 700 clamp(2.3rem, 5.6vw, 3.7rem)/1.04 ui-serif, Georgia, "Times New Roman", serif;
	margin: 0 0 1.1rem;
	letter-spacing: -.032em;
	text-wrap: balance;
}
.lede { font-size: 1.08rem; max-width: 27rem; margin: 0; }

/* Three statements on a rule, not three cards. Border and fill say
   "separate object", and these are one thought in three parts. */
.tenets {
	display: grid; grid-template-columns: repeat(3, 1fr); gap: 2.25rem;
	margin: 4.5rem 0 0; padding-top: 1.75rem;
	border-top: 1px solid var(--rule);
}
.tenets p { margin: 0; font-size: .92rem; color: var(--ink-3); }

.games { margin-top: 4.5rem; }

.game-card {
	display: grid; grid-template-columns: 1fr auto;
	gap: 2.25rem; align-items: center;
	background: var(--paper-2);
	border: 1px solid var(--rule);
	border-radius: 16px;
	padding: 1.9rem 2rem;
}
.game-card + .game-card { margin-top: 1.5rem; }
.game-card h3 { font-size: 1.45rem; }
.game-body p { margin: 0; max-width: 34rem; }

.chips { display: flex; flex-wrap: wrap; gap: .4rem; list-style: none; padding: 0; margin: 1.25rem 0 0; }
.chips li {
	margin: 0; padding: .32rem .6rem;
	border: 1px solid var(--rule-2); border-radius: 4px;
	color: var(--ink-3);
}

/* Three screenshots per game, sitting where the mark used to -- beside the
   text, not under it. At full phone size they took the page over: two bright
   slabs on a dark page, and five thousand pixels of scroll that were mostly
   image. Small enough to be evidence, not the subject.

   They carry their own width and height so the card reserves the space
   before the image arrives; without it every card below jumps as each one
   decodes, which is the jagged scroll this page had before. */
.shots {
	display: grid; grid-template-columns: repeat(3, 118px); gap: .6rem;
}
.shots img {
	display: block; width: 100%; height: auto;
	border-radius: 7px;
	border: 1px solid var(--rule-2);
	background: var(--paper-3);
}

.contact { margin-top: 4.5rem; }
.contact .big { margin: 0; font: 700 1.5rem/1.3 ui-serif, Georgia, serif; letter-spacing: -.015em; }
.contact .big a { color: var(--flame); }
.quiet { margin: .5rem 0 0; color: var(--ink-3); font-size: .92rem; }

footer .right { color: var(--ink-3); }

@media (max-width: 46rem) {
	.tenets { grid-template-columns: 1fr; gap: 1.5rem; }
}
@media (max-width: 40rem) {
	.wrap { padding: 2.25rem 1.25rem 4rem; }
	.hero { grid-template-columns: 1fr; gap: 2rem; margin-top: .5rem; }
	.lamp3d { justify-self: center; }
	.game-card { grid-template-columns: 1fr; padding: 1.5rem 1.35rem; }
	/* Three fixed 118px columns overrun a 307px card at phone width, so the
	   columns become fractions of whatever room the card has. */
	.shots { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	header { gap: .75rem; }
}

/* ---- motion ---------------------------------------------------------
   Declarative CSS on real elements. There is no JavaScript on this site at
   all, which is the same reason there are no web fonts: the privacy policy
   two pages over says no third-party requests and no tracking, and the
   cheapest way to keep that true is to have nothing that could break it.

   All of it is switched off wholesale under prefers-reduced-motion at the
   bottom of this file, where the lantern still reads as a lantern. */

@keyframes breathe {
	from { transform: scale(1);     opacity: .8; }
	to   { transform: scale(1.07);  opacity: 1; }
}

/* Deliberately not a loop of even beats -- a flame that flickers on a
   metronome reads as a blinking light. */
@keyframes flicker {
	0%   { transform: rotate(45deg) scale(1, 1); }
	14%  { transform: rotate(45deg) scale(.93, 1.10); }
	29%  { transform: rotate(45deg) scale(1.05, .96); }
	43%  { transform: rotate(45deg) scale(.96, 1.06); }
	61%  { transform: rotate(45deg) scale(1.03, 1.02); }
	78%  { transform: rotate(45deg) scale(.95, 1.08); }
	100% { transform: rotate(45deg) scale(1, 1); }
}
@keyframes flutter {
	from { transform: scaleX(1); }
	to   { transform: scaleX(.45); }
}

/* ---- the lantern, in three dimensions --------------------------------
   A Dietz-pattern hurricane lantern, built as a surface of revolution from
   DOM elements in a CSS 3D scene. Geometry generated by
   deploy/make-lantern.py; see the note at the top of that file for the
   profile, and for why this is CSS 3D rather than WebGL.

   One rule governs the whole thing: nothing between .stage and a band may
   set opacity, filter or overflow, because each of those flattens the 3D
   context and collapses the model into a stack of rectangles. The halo and
   the flame's glow are therefore leaves, outside the preserve-3d chain. */

.lamp3d {
	position: relative;
	width: 100%; max-width: 17.5rem; aspect-ratio: 1 / 1.16;
	margin-inline: auto;
	perspective: 760px;
}

/* Outside the 3D chain on purpose: it carries a blur, and a blur on an
   ancestor would flatten every band below it. */
.halo {
	position: absolute; left: 50%; top: 54%;
	border-radius: 50%;
	background: radial-gradient(circle at 50% 46%,
		rgba(255, 207, 107, .55) 0%,
		rgba(232, 163, 60, .20) 44%,
		rgba(232, 163, 60, 0) 72%);
	animation: breathe 6.5s ease-in-out infinite alternate;
}

.stage {
	position: absolute; inset: 0;
	transform-style: preserve-3d;
	transform: rotateX(-7deg);
	/* Promote the whole scene to one compositor layer. Without it, every
	   scroll step re-rasterises 10 panels per band across thirteen
	   bands, which is what made scrolling jagged and the phone slow. */
	will-change: transform;
}

.lantern {
	position: absolute; left: 50%; top: 54%;
	width: 0; height: 0;
	transform-style: preserve-3d;
	/* It hangs; it does not spin. The moths still orbit in this same 3D
	   space and pass behind it, which is what shows the depth is real. */
	transform: rotateY(24deg);
}
.shell {
	position: absolute; left: 0; top: 0; width: 0; height: 0;
	transform-style: preserve-3d;
}
.shell i, .tube { position: absolute; left: 0; top: 0; transform-origin: 50% 50%; }
.tube { transform-style: preserve-3d; }
.tube i { position: absolute; left: 0; top: 0; }

/* Metal. Opaque and back-face culled, so the far wall of the fount does
   not ghost through the near one. */
.m {
	backface-visibility: hidden;
	background:
		/* the key light, baked per face -- see STATIC_YAW in the generator */
		linear-gradient(rgba(0, 0, 0, var(--shade, 0)), rgba(0, 0, 0, var(--shade, 0))),
		linear-gradient(90deg,
			rgba(0, 0, 0, .28) 0%, rgba(0, 0, 0, 0) 40%,
			rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, .28) 100%),
		linear-gradient(180deg,
			var(--metal-hi) 0%, var(--metal) 38%, var(--metal-lo) 100%);
}

/* Glass. Translucent on purpose -- the far wall of the globe shows through
   the near one, which is most of what makes it read as glass rather than a
   drum, and it is only possible because the far wall is really there.

   The darkening towards each panel's vertical edges is the only
   angle-dependent shading in the model, and it stays correct from every
   direction because it follows the panel rather than the camera. */
/* Glass is a flat, even tint and nothing else.
   
   Anything that varies across a panel -- an edge darkening, a key-light
   term, a top-to-bottom ramp -- repeats twelve times around the globe and
   reads as pleating, because a panel boundary is not a feature of the
   object, only of how it is built. The roundness comes from .sheen
   instead, which is one element spanning the whole globe, so its gradient
   describes the globe rather than a facet of it. */
.g {
	backface-visibility: visible;
	background: rgba(250, 216, 134, .13);
}

/* The globe's roundness and its highlight, as one billboard just in front
   of the glass. Only possible because the lantern holds still -- on a
   turning model this would slide off the silhouette. */
/* A sibling of .lantern, not a child of it. Inside, it inherited the
   model's resting yaw -- a plane meant to face the camera, turned away
   from it, projecting narrower than the globe and offset to one side. It
   showed as a pale polygon sticking out past the glass. */
.sheen {
	position: absolute; left: 50%; top: 54%;
	background:
		linear-gradient(90deg,
			rgba(86, 50, 8, .30) 0%, rgba(86, 50, 8, .06) 22%,
			rgba(86, 50, 8, 0) 44%, rgba(86, 50, 8, 0) 58%,
			rgba(86, 50, 8, .08) 80%, rgba(86, 50, 8, .34) 100%),
		/* one narrow, near-vertical streak: a highlight on a cylinder is a
		   reflection of the light source, so it runs with the axis. The
		   first pass raked it across at 96deg and it read as a smear. */
		linear-gradient(93deg,
			rgba(255, 252, 240, 0) 24%, rgba(255, 252, 240, .26) 30%,
			rgba(255, 252, 240, .10) 34%, rgba(255, 252, 240, 0) 39%),
		/* and the vertical warmth the panels can no longer carry: on the
		   glass it would restart at every band seam, here it spans the
		   whole globe */
		linear-gradient(180deg,
			rgba(255, 244, 214, .10) 0%, rgba(255, 244, 214, 0) 26%,
			rgba(214, 148, 42, 0) 62%, rgba(214, 148, 42, .13) 100%);
}

/* Two crossed billboards. A single plane vanishes edge-on twice a turn;
   two at right angles mean there is always one facing you. */
.flame { position: absolute; left: 0; top: 0; width: 0; height: 0; transform-style: preserve-3d; }
.flame i {
	position: absolute;
	width: 28px; height: 28px; left: -14px; top: -32px;
	background: radial-gradient(circle at 62% 66%,
		#fffdf2 0%, #ffe9a6 30%, #f7c54f 62%, #ec9520 100%);
	box-shadow: 0 0 20px 4px rgba(255, 190, 70, .5);
	/* the flat corner is what makes the point, and rotate(45deg) carries
	   the top-left corner to the top -- so it has to come first */
	border-radius: 0 50% 50% 50%;
	transform: rotate(45deg);
	animation: flicker 3.1s ease-in-out infinite;
}
.flame i:nth-child(2) { transform: rotateY(90deg) rotate(45deg); animation-delay: -1.4s; }

/* Moths fly in the same 3D space as the lantern, so the far half of each
   path is genuinely behind it. The inner element counter-rotates by the
   same angle, which keeps the moth facing the viewer while its parent
   carries it round -- a billboard, done with the animation and not with
   script. */
.moth {
	position: absolute; left: 50%; top: 54%;
	width: 0; height: 0;
	transform-style: preserve-3d;
	/* Deliberately a mid-tone, not --ink. A moth crosses two grounds on
	   this page: the dark page, where it must be lighter to show at all,
	   and the lit globe, where it must be darker. Taking --ink made them
	   near-white and they read as sparks around the flame. */
	color: var(--moth);
}
.moth-art {
	position: absolute; width: 24px; height: 18px; left: -12px; top: -9px;
	overflow: visible;
	fill: currentColor;
}
.m2 .moth-art { width: 20px; height: 15px; left: -10px; top: -7.5px; }
.m3 .moth-art { width: 17px; height: 13px; left: -8.5px; top: -6.5px; }
/* The forewings sit over the hindwings and both over the body, so the
   wings carry a little less opacity than the body -- which is what a
   moth's wings do against its thorax. */
.moth-art .fore { opacity: .58; }
.moth-art .hind { opacity: .42; }
.moth-art .body { opacity: .78; }
.moth-art .feeler { opacity: .55; }
/* One group, one scaleX: both wings fold toward the body together, about
   the body's own axis. */
.wings {
	transform-box: view-box; transform-origin: 20px 15px;
	animation: flutter .26s ease-in-out infinite alternate;
}
.m2 .wings { animation-duration: .31s; }
.m3 .wings { animation-duration: .21s; }
/* The wingbeat and the third moth stay on at every size. They were cut on
   phones once, to save work -- but a transform animation is composited and
   costs the compositor a matrix per frame, not a repaint, so the saving was
   small and the loss was the thing people actually look at. The real wins
   were removing the page's one paint-bound animation, giving the scene its
   own layer, and dropping 74 panels. */
.m1 { animation: orbit1 17s linear infinite; }
.m2 { animation: orbit2 23s linear infinite; }
.m3 { animation: orbit3 13s linear infinite; }

/* One transform for every band panel; the band class supplies the radius
   and the lean, the side class supplies the angle. */
.shell > i {
	transform: translateY(var(--y)) rotateY(var(--k)) translateZ(var(--a))
	           rotateX(var(--t));
}
.tube { transform: translateY(var(--y)) rotateY(var(--ang)) translateZ(var(--off)); }
.tube i { transform: rotateY(var(--k)) translateZ(3.20px); --shade:.3; }
.bail { position: absolute; left: 0; top: 0; transform-style: preserve-3d; }
.bail i { position: absolute; left: 0; top: 0; transform-origin: 50% 50%; }
.wire { transform: translateX(var(--x)) translateY(var(--y)) rotateZ(var(--r)); }
.wire.cross { transform: translateX(var(--x)) translateY(var(--y)) rotateZ(var(--r)) rotateY(90deg); }

.s0 { --k:0.0deg; --shade:0.122; }
.s1 { --k:36.0deg; --shade:0.262; }
.s2 { --k:72.0deg; --shade:0.390; }
.s3 { --k:108.0deg; --shade:0.457; }
.s4 { --k:144.0deg; --shade:0.437; }
.s5 { --k:180.0deg; --shade:0.338; }
.s6 { --k:216.0deg; --shade:0.198; }
.s7 { --k:252.0deg; --shade:0.070; }
.s8 { --k:288.0deg; --shade:0.003; }
.s9 { --k:324.0deg; --shade:0.023; }
.u0 { --k:0deg; }
.u1 { --k:60deg; }
.u2 { --k:120deg; }
.u3 { --k:180deg; }
.u4 { --k:240deg; }
.u5 { --k:300deg; }

.b0 { width:8.45px; height:11.31px; margin:-5.66px 0 0 -4.22px; --y:-96.0px; --a:9.00px; --t:45.00deg; clip-path:polygon(30.8% 0%, 69.2% 0%, 84.6% 50%, 100.0% 100%, 0.0% 100%, 15.4% 50%); }
.b1 { width:13.65px; height:14.42px; margin:-7.21px 0 0 -6.82px; --y:-86.0px; --a:16.00px; --t:33.69deg; clip-path:polygon(19.0% 0%, 81.0% 0%, 85.7% 50%, 100.0% 100%, 0.0% 100%, 14.3% 50%); }
.b2 { width:16.90px; height:11.18px; margin:-5.59px 0 0 -8.45px; --y:-75.0px; --a:23.25px; --t:26.57deg; clip-path:polygon(9.6% 0%, 90.4% 0%, 94.2% 50%, 100.0% 100%, 0.0% 100%, 5.8% 50%); }
.b3 { width:19.50px; height:8.06px; margin:-4.03px 0 0 -9.75px; --y:-66.0px; --a:27.75px; --t:-7.13deg; clip-path:polygon(6.7% 0%, 93.3% 0%, 100.0% 50%, 91.7% 100%, 8.3% 100%, 0.0% 50%); }
.b4 { width:18.85px; height:16.64px; margin:-8.32px 0 0 -9.42px; --y:-53.0px; --a:24.50px; --t:32.74deg; clip-path:polygon(15.5% 0%, 84.5% 0%, 92.2% 50%, 100.0% 100%, 0.0% 100%, 7.8% 50%); }
.b5 { width:22.74px; height:22.80px; margin:-11.40px 0 0 -11.37px; --y:-35.0px; --a:32.00px; --t:15.26deg; clip-path:polygon(8.6% 0%, 91.4% 0%, 95.7% 50%, 100.0% 100%, 0.0% 100%, 4.3% 50%); }
.b6 { width:22.74px; height:22.09px; margin:-11.05px 0 0 -11.37px; --y:-13.0px; --a:34.00px; --t:-5.19deg; clip-path:polygon(0.0% 0%, 100.0% 0%, 98.6% 50%, 97.1% 100%, 2.9% 100%, 1.4% 50%); }
.b7 { width:21.44px; height:13.60px; margin:-6.80px 0 0 -10.72px; --y:3.5px; --a:29.00px; --t:-36.03deg; clip-path:polygon(0.0% 0%, 100.0% 0%, 93.9% 50%, 87.9% 100%, 12.1% 100%, 6.1% 50%); }
.b8 { width:17.55px; height:6.08px; margin:-3.04px 0 0 -8.77px; --y:12.0px; --a:26.50px; --t:9.46deg; clip-path:polygon(1.9% 0%, 98.1% 0%, 99.1% 50%, 100.0% 100%, 0.0% 100%, 0.9% 50%); }
.b9 { width:23.39px; height:15.00px; margin:-7.50px 0 0 -11.70px; --y:22.0px; --a:31.50px; --t:36.87deg; clip-path:polygon(12.5% 0%, 87.5% 0%, 93.8% 50%, 100.0% 100%, 0.0% 100%, 6.2% 50%); }
.b10 { width:26.64px; height:12.37px; margin:-6.18px 0 0 -13.32px; --y:34.0px; --a:39.25px; --t:14.04deg; clip-path:polygon(6.1% 0%, 93.9% 0%, 100.0% 50%, 97.6% 100%, 2.4% 100%, 0.0% 50%); }
.b11 { width:26.64px; height:12.17px; margin:-6.08px 0 0 -13.32px; --y:46.0px; --a:39.50px; --t:-9.46deg; clip-path:polygon(2.4% 0%, 97.6% 0%, 100.0% 50%, 95.1% 100%, 4.9% 100%, 0.0% 50%); }
.b12 { width:24.04px; height:13.04px; margin:-6.52px 0 0 -12.02px; --y:57.5px; --a:33.50px; --t:-32.47deg; clip-path:polygon(0.0% 0%, 100.0% 0%, 95.3% 50%, 90.5% 100%, 9.5% 100%, 4.7% 50%); }
.t0 { --y:-22.5px; --ang:66deg; --off:33.0px; }
.t0 i { width:3.70px; height:93.0px; margin:-46.5px 0 0 -1.85px; }
.t1 { --y:-22.5px; --ang:246deg; --off:33.0px; }
.t1 i { width:3.70px; height:93.0px; margin:-46.5px 0 0 -1.85px; }
.k0 { width:2.6px; height:15.43px; margin:-7.71px 0 0 -1.30px; --x:37.52px; --y:-75.90px; --r:176.05deg; }
.k1 { width:2.6px; height:15.00px; margin:-7.50px 0 0 -1.30px; --x:35.64px; --y:-89.35px; --r:167.90deg; }
.k2 { width:2.6px; height:14.20px; margin:-7.10px 0 0 -1.30px; --x:31.97px; --y:-101.78px; --r:158.94deg; }
.k3 { width:2.6px; height:13.11px; margin:-6.56px 0 0 -1.30px; --x:26.70px; --y:-112.56px; --r:148.50deg; }
.k4 { width:2.6px; height:11.92px; margin:-5.96px 0 0 -1.30px; --x:20.09px; --y:-121.17px; --r:135.71deg; }
.k5 { width:2.6px; height:10.85px; margin:-5.42px 0 0 -1.30px; --x:12.47px; --y:-127.15px; --r:119.72deg; }
.k6 { width:2.6px; height:10.20px; margin:-5.10px 0 0 -1.30px; --x:4.23px; --y:-130.22px; --r:100.42deg; }
.k7 { width:2.6px; height:10.20px; margin:-5.10px 0 0 -1.30px; --x:-4.23px; --y:-130.22px; --r:79.58deg; }
.k8 { width:2.6px; height:10.85px; margin:-5.42px 0 0 -1.30px; --x:-12.47px; --y:-127.15px; --r:60.28deg; }
.k9 { width:2.6px; height:11.92px; margin:-5.96px 0 0 -1.30px; --x:-20.09px; --y:-121.17px; --r:44.29deg; }
.k10 { width:2.6px; height:13.11px; margin:-6.56px 0 0 -1.30px; --x:-26.70px; --y:-112.56px; --r:31.50deg; }
.k11 { width:2.6px; height:14.20px; margin:-7.10px 0 0 -1.30px; --x:-31.97px; --y:-101.78px; --r:21.06deg; }
.k12 { width:2.6px; height:15.00px; margin:-7.50px 0 0 -1.30px; --x:-35.64px; --y:-89.35px; --r:12.10deg; }
.k13 { width:2.6px; height:15.43px; margin:-7.71px 0 0 -1.30px; --x:-37.52px; --y:-75.90px; --r:3.95deg; }
.sheen { width:70.0px; height:69.0px; margin:-34.5px 0 0 -35.0px; transform: translateY(-25.5px) translateZ(36.5px); clip-path:polygon(78.6% 0.0%, 91.4% 20.3%, 100.0% 52.2%, 97.1% 84.1%, 85.7% 100.0%, 14.3% 100.0%, 2.9% 84.1%, 0.0% 52.2%, 8.6% 20.3%, 21.4% 0.0%); }
.halo { width:288px; height:265px; margin:-154px 0 0 -144px; }

@keyframes orbit1 {
	0% { transform: translateY(-8.5px) rotateY(16.2deg) translateZ(79.6px) rotateY(-16.2deg) rotateZ(0.8deg); }
	2.778% { transform: translateY(-10.6px) rotateY(27.8deg) translateZ(80.1px) rotateY(-27.8deg) rotateZ(4.2deg); }
	5.556% { transform: translateY(-9.8px) rotateY(40.9deg) translateZ(80.7px) rotateY(-40.9deg) rotateZ(5.5deg); }
	8.333% { transform: translateY(-5.8px) rotateY(54.1deg) translateZ(81.0px) rotateY(-54.1deg) rotateZ(4.1deg); }
	11.11% { transform: translateY(0.2px) rotateY(65.6deg) translateZ(80.5px) rotateY(-65.6deg) rotateZ(0.1deg); }
	13.89% { transform: translateY(5.9px) rotateY(74.0deg) translateZ(78.8px) rotateY(-74.0deg) rotateZ(-5.6deg); }
	16.67% { transform: translateY(8.7px) rotateY(78.6deg) translateZ(75.5px) rotateY(-78.6deg) rotateZ(-11.7deg); }
	19.44% { transform: translateY(7.4px) rotateY(79.7deg) translateZ(70.9px) rotateY(-79.7deg) rotateZ(-16.5deg); }
	22.22% { transform: translateY(2.3px) rotateY(78.5deg) translateZ(65.4px) rotateY(-78.5deg) rotateZ(-19.0deg); }
	25% { transform: translateY(-4.7px) rotateY(76.7deg) translateZ(59.9px) rotateY(-76.7deg) rotateZ(-18.3deg); }
	27.78% { transform: translateY(-11.0px) rotateY(76.3deg) translateZ(55.6px) rotateY(-76.3deg) rotateZ(-14.6deg); }
	30.56% { transform: translateY(-14.4px) rotateY(78.8deg) translateZ(53.4px) rotateY(-78.8deg) rotateZ(-8.7deg); }
	33.33% { transform: translateY(-14.4px) rotateY(85.3deg) translateZ(54.2px) rotateY(-85.3deg) rotateZ(-2.1deg); }
	36.11% { transform: translateY(-12.2px) rotateY(95.9deg) translateZ(58.1px) rotateY(-95.9deg) rotateZ(3.7deg); }
	38.89% { transform: translateY(-9.9px) rotateY(109.5deg) translateZ(64.7px) rotateY(-109.5deg) rotateZ(7.6deg); }
	41.67% { transform: translateY(-10.0px) rotateY(124.7deg) translateZ(73.0px) rotateY(-124.7deg) rotateZ(8.6deg); }
	44.44% { transform: translateY(-13.6px) rotateY(139.7deg) translateZ(81.4px) rotateY(-139.7deg) rotateZ(6.9deg); }
	47.22% { transform: translateY(-20.5px) rotateY(153.0deg) translateZ(88.5px) rotateY(-153.0deg) rotateZ(3.4deg); }
	50% { transform: translateY(-28.5px) rotateY(163.8deg) translateZ(92.9px) rotateY(-163.8deg) rotateZ(-0.8deg); }
	52.78% { transform: translateY(-35.0px) rotateY(172.2deg) translateZ(93.8px) rotateY(-172.2deg) rotateZ(-4.2deg); }
	55.56% { transform: translateY(-38.0px) rotateY(179.1deg) translateZ(91.1px) rotateY(-179.1deg) rotateZ(-5.5deg); }
	58.33% { transform: translateY(-36.9px) rotateY(185.9deg) translateZ(85.3px) rotateY(-185.9deg) rotateZ(-4.1deg); }
	61.11% { transform: translateY(-32.8px) rotateY(194.4deg) translateZ(77.6px) rotateY(-194.4deg) rotateZ(-0.1deg); }
	63.89% { transform: translateY(-28.0px) rotateY(206.0deg) translateZ(69.4px) rotateY(-206.0deg) rotateZ(5.6deg); }
	66.67% { transform: translateY(-25.1px) rotateY(221.4deg) translateZ(62.2px) rotateY(-221.4deg) rotateZ(11.7deg); }
	69.44% { transform: translateY(-25.3px) rotateY(240.3deg) translateZ(57.2px) rotateY(-240.3deg) rotateZ(16.5deg); }
	72.22% { transform: translateY(-28.3px) rotateY(261.5deg) translateZ(55.0px) rotateY(-261.5deg) rotateZ(19.0deg); }
	75% { transform: translateY(-32.2px) rotateY(283.3deg) translateZ(55.6px) rotateY(-283.3deg) rotateZ(18.3deg); }
	77.78% { transform: translateY(-34.6px) rotateY(303.7deg) translateZ(58.5px) rotateY(-303.7deg) rotateZ(14.6deg); }
	80.56% { transform: translateY(-33.4px) rotateY(321.2deg) translateZ(62.8px) rotateY(-321.2deg) rotateZ(8.7deg); }
	83.33% { transform: translateY(-28.3px) rotateY(334.7deg) translateZ(67.5px) rotateY(-334.7deg) rotateZ(2.1deg); }
	86.11% { transform: translateY(-20.4px) rotateY(344.1deg) translateZ(71.8px) rotateY(-344.1deg) rotateZ(-3.7deg); }
	88.89% { transform: translateY(-12.3px) rotateY(350.5deg) translateZ(75.1px) rotateY(-350.5deg) rotateZ(-7.6deg); }
	91.67% { transform: translateY(-6.4px) rotateY(355.3deg) translateZ(77.3px) rotateY(-355.3deg) rotateZ(-8.6deg); }
	94.44% { transform: translateY(-4.3px) rotateY(360.3deg) translateZ(78.5px) rotateY(-360.3deg) rotateZ(-6.9deg); }
	97.22% { transform: translateY(-5.6px) rotateY(367.0deg) translateZ(79.1px) rotateY(-367.0deg) rotateZ(-3.4deg); }
	100% { transform: translateY(-8.5px) rotateY(376.2deg) translateZ(79.6px) rotateY(-376.2deg) rotateZ(0.8deg); }
}
@keyframes orbit2 {
	0% { transform: translateY(15.2px) rotateY(0.9deg) translateZ(83.3px) rotateY(-0.9deg) rotateZ(0.5deg); }
	2.778% { transform: translateY(12.3px) rotateY(13.6deg) translateZ(82.3px) rotateY(-13.6deg) rotateZ(8.9deg); }
	5.556% { transform: translateY(9.8px) rotateY(31.7deg) translateZ(78.0px) rotateY(-31.7deg) rotateZ(16.6deg); }
	8.333% { transform: translateY(7.2px) rotateY(52.6deg) translateZ(71.5px) rotateY(-52.6deg) rotateZ(16.3deg); }
	11.11% { transform: translateY(4.4px) rotateY(70.1deg) translateZ(65.1px) rotateY(-70.1deg) rotateZ(5.8deg); }
	13.89% { transform: translateY(1.4px) rotateY(79.0deg) translateZ(61.4px) rotateY(-79.0deg) rotateZ(-9.9deg); }
	16.67% { transform: translateY(-1.3px) rotateY(78.8deg) translateZ(61.8px) rotateY(-78.8deg) rotateZ(-22.0deg); }
	19.44% { transform: translateY(-2.9px) rotateY(73.9deg) translateZ(66.2px) rotateY(-73.9deg) rotateZ(-23.9deg); }
	22.22% { transform: translateY(-2.6px) rotateY(71.1deg) translateZ(72.9px) rotateY(-71.1deg) rotateZ(-15.4deg); }
	25% { transform: translateY(0.2px) rotateY(75.1deg) translateZ(79.1px) rotateY(-75.1deg) rotateZ(-3.3deg); }
	27.78% { transform: translateY(5.8px) rotateY(85.8deg) translateZ(82.8px) rotateY(-85.8deg) rotateZ(4.3deg); }
	30.56% { transform: translateY(13.6px) rotateY(98.5deg) translateZ(83.1px) rotateY(-98.5deg) rotateZ(3.1deg); }
	33.33% { transform: translateY(22.8px) rotateY(108.4deg) translateZ(81.1px) rotateY(-108.4deg) rotateZ(-4.2deg); }
	36.11% { transform: translateY(31.6px) rotateY(113.8deg) translateZ(78.9px) rotateY(-113.8deg) rotateZ(-9.9deg); }
	38.89% { transform: translateY(38.5px) rotateY(117.8deg) translateZ(79.0px) rotateY(-117.8deg) rotateZ(-7.5deg); }
	41.67% { transform: translateY(41.8px) rotateY(126.1deg) translateZ(82.7px) rotateY(-126.1deg) rotateZ(3.7deg); }
	44.44% { transform: translateY(40.8px) rotateY(142.8deg) translateZ(89.7px) rotateY(-142.8deg) rotateZ(17.7deg); }
	47.22% { transform: translateY(35.2px) rotateY(166.8deg) translateZ(98.3px) rotateY(-166.8deg) rotateZ(25.9deg); }
	50% { transform: translateY(25.8px) rotateY(192.7deg) translateZ(105.6px) rotateY(-192.7deg) rotateZ(22.8deg); }
	52.78% { transform: translateY(14.2px) rotateY(213.5deg) translateZ(109.6px) rotateY(-213.5deg) rotateZ(10.4deg); }
	55.56% { transform: translateY(2.5px) rotateY(225.6deg) translateZ(109.5px) rotateY(-225.6deg) rotateZ(-3.7deg); }
	58.33% { transform: translateY(-7.3px) rotateY(230.5deg) translateZ(106.2px) rotateY(-230.5deg) rotateZ(-11.4deg); }
	61.11% { transform: translateY(-13.5px) rotateY(233.5deg) translateZ(102.0px) rotateY(-233.5deg) rotateZ(-9.4deg); }
	63.89% { transform: translateY(-15.0px) rotateY(239.8deg) translateZ(99.3px) rotateY(-239.8deg) rotateZ(-1.8deg); }
	66.67% { transform: translateY(-11.8px) rotateY(250.7deg) translateZ(99.6px) rotateY(-250.7deg) rotateZ(3.7deg); }
	69.44% { transform: translateY(-4.7px) rotateY(262.6deg) translateZ(102.8px) rotateY(-262.6deg) rotateZ(1.0deg); }
	72.22% { transform: translateY(4.7px) rotateY(270.5deg) translateZ(107.0px) rotateY(-270.5deg) rotateZ(-9.1deg); }
	75% { transform: translateY(14.8px) rotateY(271.3deg) translateZ(109.8px) rotateY(-271.3deg) rotateZ(-20.0deg); }
	77.78% { transform: translateY(23.7px) rotateY(267.2deg) translateZ(109.2px) rotateY(-267.2deg) rotateZ(-23.6deg); }
	80.56% { transform: translateY(30.1px) rotateY(264.1deg) translateZ(104.4px) rotateY(-264.1deg) rotateZ(-16.0deg); }
	83.33% { transform: translateY(33.3px) rotateY(268.5deg) translateZ(96.6px) rotateY(-268.5deg) rotateZ(-0.8deg); }
	86.11% { transform: translateY(33.5px) rotateY(282.6deg) translateZ(88.1px) rotateY(-282.6deg) rotateZ(13.5deg); }
	88.89% { transform: translateY(31.1px) rotateY(303.3deg) translateZ(81.6px) rotateY(-303.3deg) rotateZ(19.2deg); }
	91.67% { transform: translateY(27.3px) rotateY(324.4deg) translateZ(78.7px) rotateY(-324.4deg) rotateZ(14.7deg); }
	94.44% { transform: translateY(22.9px) rotateY(340.7deg) translateZ(79.3px) rotateY(-340.7deg) rotateZ(5.1deg); }
	97.22% { transform: translateY(18.7px) rotateY(351.7deg) translateZ(81.6px) rotateY(-351.7deg) rotateZ(-1.3deg); }
	100% { transform: translateY(15.2px) rotateY(360.9deg) translateZ(83.3px) rotateY(-360.9deg) rotateZ(0.5deg); }
}
@keyframes orbit3 {
	0% { transform: translateY(-54.0px) rotateY(14.3deg) translateZ(63.7px) rotateY(-14.3deg) rotateZ(-5.1deg); }
	2.778% { transform: translateY(-54.3px) rotateY(17.7deg) translateZ(62.9px) rotateY(-17.7deg) rotateZ(-16.4deg); }
	5.556% { transform: translateY(-55.2px) rotateY(14.7deg) translateZ(61.0px) rotateY(-14.7deg) rotateZ(-24.3deg); }
	8.333% { transform: translateY(-56.4px) rotateY(8.9deg) translateZ(56.3px) rotateY(-8.9deg) rotateZ(-25.0deg); }
	11.11% { transform: translateY(-57.7px) rotateY(5.0deg) translateZ(49.5px) rotateY(-5.0deg) rotateZ(-17.8deg); }
	13.89% { transform: translateY(-58.7px) rotateY(7.4deg) translateZ(43.4px) rotateY(-7.4deg) rotateZ(-5.6deg); }
	16.67% { transform: translateY(-59.0px) rotateY(17.7deg) translateZ(42.0px) rotateY(-17.7deg) rotateZ(6.4deg); }
	19.44% { transform: translateY(-58.3px) rotateY(34.1deg) translateZ(47.3px) rotateY(-34.1deg) rotateZ(13.2deg); }
	22.22% { transform: translateY(-56.3px) rotateY(52.5deg) translateZ(57.9px) rotateY(-52.5deg) rotateZ(12.4deg); }
	25% { transform: translateY(-53.0px) rotateY(68.3deg) translateZ(69.2px) rotateY(-68.3deg) rotateZ(5.0deg); }
	27.78% { transform: translateY(-48.3px) rotateY(78.5deg) translateZ(75.9px) rotateY(-78.5deg) rotateZ(-4.7deg); }
	30.56% { transform: translateY(-42.6px) rotateY(83.2deg) translateZ(75.1px) rotateY(-83.2deg) rotateZ(-11.4deg); }
	33.33% { transform: translateY(-36.0px) rotateY(85.7deg) translateZ(67.9px) rotateY(-85.7deg) rotateZ(-11.3deg); }
	36.11% { transform: translateY(-29.1px) rotateY(90.6deg) translateZ(58.3px) rotateY(-90.6deg) rotateZ(-3.7deg); }
	38.89% { transform: translateY(-22.5px) rotateY(101.9deg) translateZ(50.9px) rotateY(-101.9deg) rotateZ(8.5deg); }
	41.67% { transform: translateY(-16.6px) rotateY(120.9deg) translateZ(47.9px) rotateY(-120.9deg) rotateZ(20.1deg); }
	44.44% { transform: translateY(-12.0px) rotateY(145.6deg) translateZ(48.8px) rotateY(-145.6deg) rotateZ(26.1deg); }
	47.22% { transform: translateY(-9.0px) rotateY(171.7deg) translateZ(50.9px) rotateY(-171.7deg) rotateZ(24.0deg); }
	50% { transform: translateY(-8.0px) rotateY(194.3deg) translateZ(52.3px) rotateY(-194.3deg) rotateZ(15.0deg); }
	52.78% { transform: translateY(-9.0px) rotateY(210.2deg) translateZ(53.1px) rotateY(-210.2deg) rotateZ(3.4deg); }
	55.56% { transform: translateY(-12.0px) rotateY(219.4deg) translateZ(55.0px) rotateY(-219.4deg) rotateZ(-5.5deg); }
	58.33% { transform: translateY(-16.6px) rotateY(224.9deg) translateZ(59.7px) rotateY(-224.9deg) rotateZ(-7.7deg); }
	61.11% { transform: translateY(-22.5px) rotateY(231.3deg) translateZ(66.5px) rotateY(-231.3deg) rotateZ(-2.5deg); }
	63.89% { transform: translateY(-29.1px) rotateY(242.6deg) translateZ(72.6px) rotateY(-242.6deg) rotateZ(7.2deg); }
	66.67% { transform: translateY(-36.0px) rotateY(260.0deg) translateZ(74.0px) rotateY(-260.0deg) rotateZ(16.4deg); }
	69.44% { transform: translateY(-42.6px) rotateY(281.7deg) translateZ(68.7px) rotateY(-281.7deg) rotateZ(20.0deg); }
	72.22% { transform: translateY(-48.3px) rotateY(303.4deg) translateZ(58.1px) rotateY(-303.4deg) rotateZ(15.8deg); }
	75% { transform: translateY(-53.0px) rotateY(320.3deg) translateZ(46.8px) rotateY(-320.3deg) rotateZ(4.9deg); }
	77.78% { transform: translateY(-56.3px) rotateY(329.4deg) translateZ(40.1px) rotateY(-329.4deg) rotateZ(-8.2deg); }
	80.56% { transform: translateY(-58.3px) rotateY(330.9deg) translateZ(40.9px) rotateY(-330.9deg) rotateZ(-18.4deg); }
	83.33% { transform: translateY(-59.0px) rotateY(328.1deg) translateZ(48.1px) rotateY(-328.1deg) rotateZ(-21.4deg); }
	86.11% { transform: translateY(-58.7px) rotateY(325.8deg) translateZ(57.7px) rotateY(-325.8deg) rotateZ(-16.6deg); }
	88.89% { transform: translateY(-57.7px) rotateY(328.1deg) translateZ(65.1px) rotateY(-328.1deg) rotateZ(-6.9deg); }
	91.67% { transform: translateY(-56.4px) rotateY(336.9deg) translateZ(68.1px) rotateY(-336.9deg) rotateZ(2.6deg); }
	94.44% { transform: translateY(-55.2px) rotateY(350.2deg) translateZ(67.2px) rotateY(-350.2deg) rotateZ(7.2deg); }
	97.22% { transform: translateY(-54.3px) rotateY(364.2deg) translateZ(65.1px) rotateY(-364.2deg) rotateZ(4.2deg); }
	100% { transform: translateY(-54.0px) rotateY(374.3deg) translateZ(63.7px) rotateY(-374.3deg) rotateZ(-5.1deg); }
}

/* ---- arrival --------------------------------------------------------
   One short staged entrance, and then the page is still.

   The text rises but never fades: it is fully opaque in the very first
   frame. An entrance that starts at opacity 0 looks better for about a
   second and then costs you every still frame of the page -- the link
   preview, the social card, the screenshot someone takes -- all of which
   catch it blank. Only the lantern, which nobody needs to read, fades in.

   It runs forward only and is done inside a second, so a reader who lands
   mid-animation is never waiting on it. */
@keyframes rise {
	from { transform: translateY(11px); }
	to   { transform: none; }
}
.home header,
.home .hero-text,
.home .lamp3d,
.home .tenets,
.home .games,
.home .contact,
.home footer {
	animation: rise .75s cubic-bezier(.22, 1, .36, 1) both;
}
.home .hero-text { animation-delay: .06s; }
.home .lamp3d    { animation-delay: .1s; }
.home .tenets    { animation-delay: .16s; }
.home .games     { animation-delay: .22s; }
.home .contact   { animation-delay: .28s; }
.home footer     { animation-delay: .34s; }

/* The app's own mark, lighting the way it does on the icon: one letter at
   a time, left to right.

   It used to run once on load, over 450ms, with 130ms between letters --
   by the time you had looked at the page it had already happened, and it
   was too slight to catch anyway. Now the sweep takes about a second and a
   half and returns every eight seconds, so it is something the page does
   rather than something it did.

   The cells are lit in their resting state and the animation only adds the
   flare, so the mark still says FOUR in the very first frame and in a
   reduced-motion browser. */
/* ---- hover and focus ------------------------------------------------ */

.game-card {
	transition: transform .3s cubic-bezier(.22, 1, .36, 1),
	            border-color .3s ease, background .3s ease, box-shadow .3s ease;
}
.game-card:hover {
	transform: translateY(-3px);
	border-color: var(--flame-ink);
	background: var(--paper-3);
	box-shadow: 0 18px 40px -22px #000;
}

.link {
	text-decoration: none;
	background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
	transition: background-size .3s cubic-bezier(.22, 1, .36, 1);
}
.link:hover, .link:focus-visible { background-size: 100% 1px; }

.mark span { transition: color .3s ease; }
.mark:hover .mark-text span { color: var(--ink); }

:focus-visible {
	outline: 2px solid var(--flame);
	outline-offset: 3px;
	border-radius: 2px;
}

/* ---- reduced motion -------------------------------------------------
   Not a courtesy. For some people the moths above are a headache, and a
   page whose whole point is that it is quiet should be the first to take
   that seriously. Everything lands in its finished state. */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation: none !important;
		transition: none !important;
	}
	/* The animations are what place the lantern and the moths, so with
	   them off everything would collapse to the origin facing straight
	   on. Put the scene back by hand, at a three-quarter view that
	   still shows the model has depth. These are the first frame of
	   each path, taken from the generator rather than typed. */
	.flame i:nth-child(2) { transform: rotateY(90deg) rotate(45deg); }
	.m1 { transform: translateY(-8.5px) rotateY(16.2deg) translateZ(79.6px) rotateY(-16.2deg) rotateZ(0.8deg); }
	.m2 { transform: translateY(15.2px) rotateY(0.9deg) translateZ(83.3px) rotateY(-0.9deg) rotateZ(0.5deg); }
	.m3 { transform: translateY(-54.0px) rotateY(14.3deg) translateZ(63.7px) rotateY(-14.3deg) rotateZ(-5.1deg); }
}
