02Memory pair cards
Two revealed cards stay when they match and flip back when they don't; the rotateY flip and the remaining-pair count set the game's rhythm.
Best forA time-killer mini game; put quiz questions on the card faces
rotateY(preserve-3dbackface-visibility

<main class="stage">
<div class="mm is-demo" id="mm">
<header class="mm__bar">
<p class="mm__title">Memory pair cards</p>
<button class="mm__restart" id="mmRestart" type="button" aria-label="Reshuffle">
<svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M216 128a88 88 0 1 1-88-88a88 88 0 0 1 88 88" opacity=".2"/><path d="M240 56v48a8 8 0 0 1-8 8h-48a8 8 0 0 1 0-16h27.4l-26.59-24.36l-.25-.24a80 80 0 1 0-1.67 114.78a8 8 0 0 1 11 11.63A95.44 95.44 0 0 1 128 224h-1.32a96 96 0 1 1 69.07-164L224 85.8V56a8 8 0 1 1 16 0"/></g></svg>
</button>
</header>
<div class="mm__stats">
<span class="mm__stat"><b class="mm__num" id="mmTries">0</b><span class="mm__label">Tries</span></span>
<span class="mm__stat"><b class="mm__num" id="mmPairs">6</b><span class="mm__label">Pairs left</span></span>
<span class="mm__stat mm__stat--best" aria-label="Best score">
<svg class="mm__trophy" viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M200 48v63.1c0 39.7-31.75 72.6-71.45 72.9A72 72 0 0 1 56 112V48Z" opacity=".2"/><path d="M232 64h-24V48a8 8 0 0 0-8-8H56a8 8 0 0 0-8 8v16H24A16 16 0 0 0 8 80v16a40 40 0 0 0 40 40h3.65A80.13 80.13 0 0 0 120 191.61V216H96a8 8 0 0 0 0 16h64a8 8 0 0 0 0-16h-24v-24.42c31.94-3.23 58.44-25.64 68.08-55.58H208a40 40 0 0 0 40-40V80a16 16 0 0 0-16-16M48 120a24 24 0 0 1-24-24V80h24v32q0 4 .39 8Zm144-8.9c0 35.52-29 64.64-64 64.9a64 64 0 0 1-64-64V56h128ZM232 96a24 24 0 0 1-24 24h-.5a82 82 0 0 0 .5-8.9V80h24Z"/></g></svg>
<b class="mm__num" id="mmBest">-</b>
</span>
</div>
<div class="mm__grid" id="mmGrid">
<button class="mm__card" type="button" data-face="star" aria-label="Card 1" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m229.06 108.79l-48.7 42l14.88 62.79a8.4 8.4 0 0 1-12.52 9.17L128 189.09l-54.72 33.65a8.4 8.4 0 0 1-12.52-9.17l14.88-62.79l-48.7-42A8.46 8.46 0 0 1 31.73 94l63.91-5.2l24.62-59.6a8.36 8.36 0 0 1 15.48 0l24.62 59.6l63.91 5.2a8.46 8.46 0 0 1 4.79 14.79" opacity=".2"/><path d="M239.18 97.26A16.38 16.38 0 0 0 224.92 86l-59-4.76l-22.78-55.09a16.36 16.36 0 0 0-30.27 0L90.11 81.23L31.08 86a16.46 16.46 0 0 0-9.37 28.86l45 38.83L53 211.75a16.38 16.38 0 0 0 24.5 17.82l50.5-31.08l50.53 31.08A16.4 16.4 0 0 0 203 211.75l-13.76-58.07l45-38.83a16.43 16.43 0 0 0 4.94-17.59m-15.34 5.47l-48.7 42a8 8 0 0 0-2.56 7.91l14.88 62.8a.37.37 0 0 1-.17.48c-.18.14-.23.11-.38 0l-54.72-33.65a8 8 0 0 0-8.38 0l-54.72 33.67c-.15.09-.19.12-.38 0a.37.37 0 0 1-.17-.48l14.88-62.8a8 8 0 0 0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16a8 8 0 0 0 6.72-4.94l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153 91.86a8 8 0 0 0 6.75 4.92l63.92 5.16c.15 0 .24 0 .33.29s0 .4-.16.5"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="heart" aria-label="Card 2" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M232 102c0 66-104 122-104 122S24 168 24 102a54 54 0 0 1 54-54c22.59 0 41.94 12.31 50 32c8.06-19.69 27.41-32 50-32a54 54 0 0 1 54 54" opacity=".2"/><path d="M178 40c-20.65 0-38.73 8.88-50 23.89C116.73 48.88 98.65 40 78 40a62.07 62.07 0 0 0-62 62c0 70 103.79 126.66 108.21 129a8 8 0 0 0 7.58 0C136.21 228.66 240 172 240 102a62.07 62.07 0 0 0-62-62m-50 174.8c-18.26-10.64-96-59.11-96-112.8a46.06 46.06 0 0 1 46-46c19.45 0 35.78 10.36 42.6 27a8 8 0 0 0 14.8 0c6.82-16.67 23.15-27 42.6-27a46.06 46.06 0 0 1 46 46c0 53.61-77.76 102.15-96 112.8"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="moon" aria-label="Card 3" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M227.89 147.89A96 96 0 1 1 108.11 28.11a96.09 96.09 0 0 0 119.78 119.78" opacity=".2"/><path d="M233.54 142.23a8 8 0 0 0-8-2a88.08 88.08 0 0 1-109.8-109.8a8 8 0 0 0-10-10a104.84 104.84 0 0 0-52.91 37A104 104 0 0 0 136 224a103.1 103.1 0 0 0 62.52-20.88a104.84 104.84 0 0 0 37-52.91a8 8 0 0 0-1.98-7.98m-44.64 48.11A88 88 0 0 1 65.66 67.11a89 89 0 0 1 31.4-26A106 106 0 0 0 96 56a104.11 104.11 0 0 0 104 104a106 106 0 0 0 14.92-1.06a89 89 0 0 1-26.02 31.4"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="rocket" aria-label="Card 4" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m94.81 192l-29.45 22.24a8 8 0 0 1-12.81-4.51L40.19 154.1a8 8 0 0 1 1.66-6.86l30.31-36.33C71 134.25 76.7 161.43 94.81 192m119.34-44.76l-30.31-36.33c1.21 23.34-4.54 50.52-22.65 81.09l29.45 22.24a8 8 0 0 0 12.81-4.51l12.36-55.63a8 8 0 0 0-1.66-6.86" opacity=".2"/><path d="M152 224a8 8 0 0 1-8 8h-32a8 8 0 0 1 0-16h32a8 8 0 0 1 8 8m-24-112a12 12 0 1 0-12-12a12 12 0 0 0 12 12m95.62 43.83l-12.36 55.63a16 16 0 0 1-25.51 9.11L158.51 200h-61l-27.26 20.57a16 16 0 0 1-25.51-9.11l-12.36-55.63a16.09 16.09 0 0 1 3.32-13.71l28.56-34.26a123 123 0 0 1 8.57-36.67c12.9-32.34 36-52.63 45.37-59.85a16 16 0 0 1 19.6 0c9.34 7.22 32.47 27.51 45.37 59.85a123 123 0 0 1 8.57 36.67l28.56 34.26a16.09 16.09 0 0 1 3.32 13.71M99.43 184h57.14c21.12-37.54 25.07-73.48 11.74-106.88C156.55 47.64 134.49 29 128 24c-6.51 5-28.57 23.64-40.33 53.12c-13.31 33.4-9.36 69.34 11.76 106.88m-15 5.85q-16.15-29.35-19.6-57.69L48 152.36L60.36 208l.18-.13ZM208 152.36l-16.83-20.2q-3.42 28.28-19.56 57.69l23.85 18l.18.13Z"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="lightning" aria-label="Card 5" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m96 240l16-80l-64-24L160 16l-16 80l64 24Z" opacity=".2"/><path d="M215.79 118.17a8 8 0 0 0-5-5.66L153.18 90.9l14.66-73.33a8 8 0 0 0-13.69-7l-112 120a8 8 0 0 0 3 13l57.63 21.61l-14.62 73.25a8 8 0 0 0 13.69 7l112-120a8 8 0 0 0 1.94-7.26M109.37 214l10.47-52.38a8 8 0 0 0-5-9.06L62 132.71l84.62-90.66l-10.46 52.38a8 8 0 0 0 5 9.06l52.8 19.8Z"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="flower" aria-label="Card 6" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M206.35 136.29c-8.87-5.13-24.46-7.38-39.4-8.29c14.94-.91 30.53-3.16 39.4-8.29a32 32 0 1 0-32-55.42c-8.87 5.12-18.61 17.48-26.87 30C154.17 80.87 160 66.25 160 56a32 32 0 0 0-64 0c0 10.25 5.83 24.87 12.52 38.26c-8.26-12.49-18-24.85-26.87-30a32 32 0 1 0-32 55.42c8.87 5.13 24.46 7.38 39.4 8.29c-14.94.91-30.53 3.16-39.4 8.29a32 32 0 1 0 32 55.42c8.87-5.12 18.61-17.48 26.87-30C101.83 175.13 96 189.75 96 200a32 32 0 0 0 64 0c0-10.25-5.83-24.87-12.52-38.26c8.26 12.49 18 24.85 26.87 30a32 32 0 1 0 32-55.42ZM155.71 144a32 32 0 1 1 4.29-16a31.74 31.74 0 0 1-4.29 16" opacity=".2"/><path d="M210.35 129.36c-.81-.47-1.7-.92-2.62-1.36c.92-.44 1.81-.89 2.62-1.36a40 40 0 1 0-40-69.28c-.81.47-1.65 1-2.48 1.59c.08-1 .13-2 .13-3a40 40 0 0 0-80 0c0 .94 0 1.94.13 3c-.83-.57-1.67-1.12-2.48-1.59a40 40 0 1 0-40 69.28c.81.47 1.7.92 2.62 1.36c-.92.44-1.81.89-2.62 1.36a40 40 0 1 0 40 69.28c.81-.47 1.65-1 2.48-1.59c-.08 1-.13 1.94-.13 2.95a40 40 0 0 0 80 0c0-.94-.05-1.94-.13-2.95c.83.57 1.67 1.12 2.48 1.59a39.8 39.8 0 0 0 19.94 5.36a40.4 40.4 0 0 0 10.42-1.38a40 40 0 0 0 9.64-73.28ZM104 128a24 24 0 1 1 24 24a24 24 0 0 1-24-24m74.35-56.79a24 24 0 1 1 24 41.57c-6.27 3.63-18.61 6.13-35.16 7.19a40 40 0 0 0-12.66-21.87c9.2-13.82 17.55-23.26 23.82-26.89M128 32a24 24 0 0 1 24 24c0 7.24-4 19.19-11.36 34.06a39.8 39.8 0 0 0-25.28 0C108.36 75.19 104 63.24 104 56a24 24 0 0 1 24-24M44.86 80a24 24 0 0 1 32.79-8.79c6.27 3.63 14.62 13.07 23.82 26.89A40 40 0 0 0 88.81 120c-16.55-1.06-28.89-3.56-35.16-7.18A24 24 0 0 1 44.86 80m32.79 104.79a24 24 0 1 1-24-41.57c6.27-3.63 14.62-6.13 35.16-7.19a40 40 0 0 0 12.66 21.87c-9.2 13.82-17.55 23.26-23.82 26.89M128 224a24 24 0 0 1-24-24c0-7.24 4-19.19 11.36-34.06a39.8 39.8 0 0 0 25.28 0C148.36 180.81 152 192.76 152 200a24 24 0 0 1-24 24m83.14-48a24 24 0 0 1-32.79 8.79c-6.27-3.63-14.62-13.07-23.82-26.89a40 40 0 0 0 12.66-21.9c16.55 1.06 28.89 3.56 35.16 7.18a24 24 0 0 1 8.79 32.82"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="star" aria-label="Card 7" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m229.06 108.79l-48.7 42l14.88 62.79a8.4 8.4 0 0 1-12.52 9.17L128 189.09l-54.72 33.65a8.4 8.4 0 0 1-12.52-9.17l14.88-62.79l-48.7-42A8.46 8.46 0 0 1 31.73 94l63.91-5.2l24.62-59.6a8.36 8.36 0 0 1 15.48 0l24.62 59.6l63.91 5.2a8.46 8.46 0 0 1 4.79 14.79" opacity=".2"/><path d="M239.18 97.26A16.38 16.38 0 0 0 224.92 86l-59-4.76l-22.78-55.09a16.36 16.36 0 0 0-30.27 0L90.11 81.23L31.08 86a16.46 16.46 0 0 0-9.37 28.86l45 38.83L53 211.75a16.38 16.38 0 0 0 24.5 17.82l50.5-31.08l50.53 31.08A16.4 16.4 0 0 0 203 211.75l-13.76-58.07l45-38.83a16.43 16.43 0 0 0 4.94-17.59m-15.34 5.47l-48.7 42a8 8 0 0 0-2.56 7.91l14.88 62.8a.37.37 0 0 1-.17.48c-.18.14-.23.11-.38 0l-54.72-33.65a8 8 0 0 0-8.38 0l-54.72 33.67c-.15.09-.19.12-.38 0a.37.37 0 0 1-.17-.48l14.88-62.8a8 8 0 0 0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16a8 8 0 0 0 6.72-4.94l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153 91.86a8 8 0 0 0 6.75 4.92l63.92 5.16c.15 0 .24 0 .33.29s0 .4-.16.5"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="heart" aria-label="Card 8" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M232 102c0 66-104 122-104 122S24 168 24 102a54 54 0 0 1 54-54c22.59 0 41.94 12.31 50 32c8.06-19.69 27.41-32 50-32a54 54 0 0 1 54 54" opacity=".2"/><path d="M178 40c-20.65 0-38.73 8.88-50 23.89C116.73 48.88 98.65 40 78 40a62.07 62.07 0 0 0-62 62c0 70 103.79 126.66 108.21 129a8 8 0 0 0 7.58 0C136.21 228.66 240 172 240 102a62.07 62.07 0 0 0-62-62m-50 174.8c-18.26-10.64-96-59.11-96-112.8a46.06 46.06 0 0 1 46-46c19.45 0 35.78 10.36 42.6 27a8 8 0 0 0 14.8 0c6.82-16.67 23.15-27 42.6-27a46.06 46.06 0 0 1 46 46c0 53.61-77.76 102.15-96 112.8"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="moon" aria-label="Card 9" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M227.89 147.89A96 96 0 1 1 108.11 28.11a96.09 96.09 0 0 0 119.78 119.78" opacity=".2"/><path d="M233.54 142.23a8 8 0 0 0-8-2a88.08 88.08 0 0 1-109.8-109.8a8 8 0 0 0-10-10a104.84 104.84 0 0 0-52.91 37A104 104 0 0 0 136 224a103.1 103.1 0 0 0 62.52-20.88a104.84 104.84 0 0 0 37-52.91a8 8 0 0 0-1.98-7.98m-44.64 48.11A88 88 0 0 1 65.66 67.11a89 89 0 0 1 31.4-26A106 106 0 0 0 96 56a104.11 104.11 0 0 0 104 104a106 106 0 0 0 14.92-1.06a89 89 0 0 1-26.02 31.4"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="rocket" aria-label="Card 10" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m94.81 192l-29.45 22.24a8 8 0 0 1-12.81-4.51L40.19 154.1a8 8 0 0 1 1.66-6.86l30.31-36.33C71 134.25 76.7 161.43 94.81 192m119.34-44.76l-30.31-36.33c1.21 23.34-4.54 50.52-22.65 81.09l29.45 22.24a8 8 0 0 0 12.81-4.51l12.36-55.63a8 8 0 0 0-1.66-6.86" opacity=".2"/><path d="M152 224a8 8 0 0 1-8 8h-32a8 8 0 0 1 0-16h32a8 8 0 0 1 8 8m-24-112a12 12 0 1 0-12-12a12 12 0 0 0 12 12m95.62 43.83l-12.36 55.63a16 16 0 0 1-25.51 9.11L158.51 200h-61l-27.26 20.57a16 16 0 0 1-25.51-9.11l-12.36-55.63a16.09 16.09 0 0 1 3.32-13.71l28.56-34.26a123 123 0 0 1 8.57-36.67c12.9-32.34 36-52.63 45.37-59.85a16 16 0 0 1 19.6 0c9.34 7.22 32.47 27.51 45.37 59.85a123 123 0 0 1 8.57 36.67l28.56 34.26a16.09 16.09 0 0 1 3.32 13.71M99.43 184h57.14c21.12-37.54 25.07-73.48 11.74-106.88C156.55 47.64 134.49 29 128 24c-6.51 5-28.57 23.64-40.33 53.12c-13.31 33.4-9.36 69.34 11.76 106.88m-15 5.85q-16.15-29.35-19.6-57.69L48 152.36L60.36 208l.18-.13ZM208 152.36l-16.83-20.2q-3.42 28.28-19.56 57.69l23.85 18l.18.13Z"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="lightning" aria-label="Card 11" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m96 240l16-80l-64-24L160 16l-16 80l64 24Z" opacity=".2"/><path d="M215.79 118.17a8 8 0 0 0-5-5.66L153.18 90.9l14.66-73.33a8 8 0 0 0-13.69-7l-112 120a8 8 0 0 0 3 13l57.63 21.61l-14.62 73.25a8 8 0 0 0 13.69 7l112-120a8 8 0 0 0 1.94-7.26M109.37 214l10.47-52.38a8 8 0 0 0-5-9.06L62 132.71l84.62-90.66l-10.46 52.38a8 8 0 0 0 5 9.06l52.8 19.8Z"/></g></svg></span>
</span>
</button>
<button class="mm__card" type="button" data-face="flower" aria-label="Card 12" aria-pressed="false">
<span class="mm__inner">
<span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span>
<span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M206.35 136.29c-8.87-5.13-24.46-7.38-39.4-8.29c14.94-.91 30.53-3.16 39.4-8.29a32 32 0 1 0-32-55.42c-8.87 5.12-18.61 17.48-26.87 30C154.17 80.87 160 66.25 160 56a32 32 0 0 0-64 0c0 10.25 5.83 24.87 12.52 38.26c-8.26-12.49-18-24.85-26.87-30a32 32 0 1 0-32 55.42c8.87 5.13 24.46 7.38 39.4 8.29c-14.94.91-30.53 3.16-39.4 8.29a32 32 0 1 0 32 55.42c8.87-5.12 18.61-17.48 26.87-30C101.83 175.13 96 189.75 96 200a32 32 0 0 0 64 0c0-10.25-5.83-24.87-12.52-38.26c8.26 12.49 18 24.85 26.87 30a32 32 0 1 0 32-55.42ZM155.71 144a32 32 0 1 1 4.29-16a31.74 31.74 0 0 1-4.29 16" opacity=".2"/><path d="M210.35 129.36c-.81-.47-1.7-.92-2.62-1.36c.92-.44 1.81-.89 2.62-1.36a40 40 0 1 0-40-69.28c-.81.47-1.65 1-2.48 1.59c.08-1 .13-2 .13-3a40 40 0 0 0-80 0c0 .94 0 1.94.13 3c-.83-.57-1.67-1.12-2.48-1.59a40 40 0 1 0-40 69.28c.81.47 1.7.92 2.62 1.36c-.92.44-1.81.89-2.62 1.36a40 40 0 1 0 40 69.28c.81-.47 1.65-1 2.48-1.59c-.08 1-.13 1.94-.13 2.95a40 40 0 0 0 80 0c0-.94-.05-1.94-.13-2.95c.83.57 1.67 1.12 2.48 1.59a39.8 39.8 0 0 0 19.94 5.36a40.4 40.4 0 0 0 10.42-1.38a40 40 0 0 0 9.64-73.28ZM104 128a24 24 0 1 1 24 24a24 24 0 0 1-24-24m74.35-56.79a24 24 0 1 1 24 41.57c-6.27 3.63-18.61 6.13-35.16 7.19a40 40 0 0 0-12.66-21.87c9.2-13.82 17.55-23.26 23.82-26.89M128 32a24 24 0 0 1 24 24c0 7.24-4 19.19-11.36 34.06a39.8 39.8 0 0 0-25.28 0C108.36 75.19 104 63.24 104 56a24 24 0 0 1 24-24M44.86 80a24 24 0 0 1 32.79-8.79c6.27 3.63 14.62 13.07 23.82 26.89A40 40 0 0 0 88.81 120c-16.55-1.06-28.89-3.56-35.16-7.18A24 24 0 0 1 44.86 80m32.79 104.79a24 24 0 1 1-24-41.57c6.27-3.63 14.62-6.13 35.16-7.19a40 40 0 0 0 12.66 21.87c-9.2 13.82-17.55 23.26-23.82 26.89M128 224a24 24 0 0 1-24-24c0-7.24 4-19.19 11.36-34.06a39.8 39.8 0 0 0 25.28 0C148.36 180.81 152 192.76 152 200a24 24 0 0 1-24 24m83.14-48a24 24 0 0 1-32.79 8.79c-6.27-3.63-14.62-13.07-23.82-26.89a40 40 0 0 0 12.66-21.9c16.55 1.06 28.89 3.56 35.16 7.18a24 24 0 0 1 8.79 32.82"/></g></svg></span>
</span>
</button>
<span class="mm__ghost mm__ghost--a" aria-hidden="true"><span class="mm__ghostInner"><span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span><span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M232 102c0 66-104 122-104 122S24 168 24 102a54 54 0 0 1 54-54c22.59 0 41.94 12.31 50 32c8.06-19.69 27.41-32 50-32a54 54 0 0 1 54 54" opacity=".2"/><path d="M178 40c-20.65 0-38.73 8.88-50 23.89C116.73 48.88 98.65 40 78 40a62.07 62.07 0 0 0-62 62c0 70 103.79 126.66 108.21 129a8 8 0 0 0 7.58 0C136.21 228.66 240 172 240 102a62.07 62.07 0 0 0-62-62m-50 174.8c-18.26-10.64-96-59.11-96-112.8a46.06 46.06 0 0 1 46-46c19.45 0 35.78 10.36 42.6 27a8 8 0 0 0 14.8 0c6.82-16.67 23.15-27 42.6-27a46.06 46.06 0 0 1 46 46c0 53.61-77.76 102.15-96 112.8"/></g></svg></span></span></span>
<span class="mm__ghost mm__ghost--b" aria-hidden="true"><span class="mm__ghostInner"><span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span><span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="M232 102c0 66-104 122-104 122S24 168 24 102a54 54 0 0 1 54-54c22.59 0 41.94 12.31 50 32c8.06-19.69 27.41-32 50-32a54 54 0 0 1 54 54" opacity=".2"/><path d="M178 40c-20.65 0-38.73 8.88-50 23.89C116.73 48.88 98.65 40 78 40a62.07 62.07 0 0 0-62 62c0 70 103.79 126.66 108.21 129a8 8 0 0 0 7.58 0C136.21 228.66 240 172 240 102a62.07 62.07 0 0 0-62-62m-50 174.8c-18.26-10.64-96-59.11-96-112.8a46.06 46.06 0 0 1 46-46c19.45 0 35.78 10.36 42.6 27a8 8 0 0 0 14.8 0c6.82-16.67 23.15-27 42.6-27a46.06 46.06 0 0 1 46 46c0 53.61-77.76 102.15-96 112.8"/></g></svg></span></span></span>
<span class="mm__ghost mm__ghost--c" aria-hidden="true"><span class="mm__ghostInner"><span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span><span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m229.06 108.79l-48.7 42l14.88 62.79a8.4 8.4 0 0 1-12.52 9.17L128 189.09l-54.72 33.65a8.4 8.4 0 0 1-12.52-9.17l14.88-62.79l-48.7-42A8.46 8.46 0 0 1 31.73 94l63.91-5.2l24.62-59.6a8.36 8.36 0 0 1 15.48 0l24.62 59.6l63.91 5.2a8.46 8.46 0 0 1 4.79 14.79" opacity=".2"/><path d="M239.18 97.26A16.38 16.38 0 0 0 224.92 86l-59-4.76l-22.78-55.09a16.36 16.36 0 0 0-30.27 0L90.11 81.23L31.08 86a16.46 16.46 0 0 0-9.37 28.86l45 38.83L53 211.75a16.38 16.38 0 0 0 24.5 17.82l50.5-31.08l50.53 31.08A16.4 16.4 0 0 0 203 211.75l-13.76-58.07l45-38.83a16.43 16.43 0 0 0 4.94-17.59m-15.34 5.47l-48.7 42a8 8 0 0 0-2.56 7.91l14.88 62.8a.37.37 0 0 1-.17.48c-.18.14-.23.11-.38 0l-54.72-33.65a8 8 0 0 0-8.38 0l-54.72 33.67c-.15.09-.19.12-.38 0a.37.37 0 0 1-.17-.48l14.88-62.8a8 8 0 0 0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16a8 8 0 0 0 6.72-4.94l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153 91.86a8 8 0 0 0 6.75 4.92l63.92 5.16c.15 0 .24 0 .33.29s0 .4-.16.5"/></g></svg></span></span></span>
<span class="mm__ghost mm__ghost--d" aria-hidden="true"><span class="mm__ghostInner"><span class="mm__face mm__face--back"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86" opacity=".2"/><path d="M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8"/></g></svg></span><span class="mm__face mm__face--front"><svg viewBox="0 0 256 256" aria-hidden="true" focusable="false"><g fill="currentColor"><path d="m229.06 108.79l-48.7 42l14.88 62.79a8.4 8.4 0 0 1-12.52 9.17L128 189.09l-54.72 33.65a8.4 8.4 0 0 1-12.52-9.17l14.88-62.79l-48.7-42A8.46 8.46 0 0 1 31.73 94l63.91-5.2l24.62-59.6a8.36 8.36 0 0 1 15.48 0l24.62 59.6l63.91 5.2a8.46 8.46 0 0 1 4.79 14.79" opacity=".2"/><path d="M239.18 97.26A16.38 16.38 0 0 0 224.92 86l-59-4.76l-22.78-55.09a16.36 16.36 0 0 0-30.27 0L90.11 81.23L31.08 86a16.46 16.46 0 0 0-9.37 28.86l45 38.83L53 211.75a16.38 16.38 0 0 0 24.5 17.82l50.5-31.08l50.53 31.08A16.4 16.4 0 0 0 203 211.75l-13.76-58.07l45-38.83a16.43 16.43 0 0 0 4.94-17.59m-15.34 5.47l-48.7 42a8 8 0 0 0-2.56 7.91l14.88 62.8a.37.37 0 0 1-.17.48c-.18.14-.23.11-.38 0l-54.72-33.65a8 8 0 0 0-8.38 0l-54.72 33.67c-.15.09-.19.12-.38 0a.37.37 0 0 1-.17-.48l14.88-62.8a8 8 0 0 0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16a8 8 0 0 0 6.72-4.94l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153 91.86a8 8 0 0 0 6.75 4.92l63.92 5.16c.15 0 .24 0 .33.29s0 .4-.16.5"/></g></svg></span></span></span>
<p class="mm__clear" id="mmClear" role="status" hidden><b id="mmClearMsg">Clear! {n} tries · {t}s</b></p>
</div>
</div>
</main>@use "../../../../site/static/demo-tokens" as *;
// 짝 맞추기 카드 — 4×3 12장(6쌍). 카드는 <button> 이라 탭+엔터로 뒤집힌다.
// 뒤집기: .mm__inner 에 transform-style:preserve-3d 와 rotateY(180deg) 전환, 앞뒷면은 backface-visibility:hidden.
// 정적 상태(사람이 안 만진 첫 화면)는 뒷면 12장이 깔린 완결된판 — 격자 미리보기(.is-demo)는
// 실제 카드 위에 겹쳐 둔 고스트 카드 4장이 순서대로 뒤집히며 짝이 맞아 하이라이트되는 연출만 보여 준다.
// 3D 플립의 90도 모서리뷰가 poster 를 잡는 문제(252-07) 때문에 미리보기 회전은 steps(1,end) 컷 — 실제 클릭은 부드러운 transition 그대로.
$duration: $dur-loop;
$easing: $ease-spring;
$color: $subject-blue-deep;
@include stage($stage-yellow);
.mm { display: flex; flex-direction: column; gap: $sp-2; width: 100%; max-width: 280px; height: 100%; }
.mm__bar { display: flex; align-items: center; justify-content: space-between; gap: $sp-2; }
.mm__title { margin: 0; font-weight: 800; font-size: clamp(12px, 3vw, 15px); color: $subject-ink; }
.mm__restart {
display: grid; place-items: center; width: clamp(24px, 5vw, 28px); aspect-ratio: 1; padding: 0;
border: 2px solid rgba($subject-ink, .32); border-radius: $r-control;
background: none; color: $subject-ink; cursor: pointer;
}
.mm__restart svg { width: 62%; height: 62%; }
.mm__restart:focus-visible { outline: 2px solid $subject-ink; outline-offset: 2px; }
.mm__stats { display: flex; align-items: baseline; gap: $sp-3; }
.mm__stat { display: inline-flex; align-items: baseline; gap: $sp-1; }
.mm__num { font-weight: 800; font-size: clamp(11px, 2.8vw, 14px); color: $subject-ink; }
.mm__label { font-weight: 700; font-size: clamp(8px, 2.2vw, 10px); color: rgba($subject-ink, .72); }
.mm__trophy { width: clamp(12px, 3vw, 14px); height: clamp(12px, 3vw, 14px); color: $subject-orange-deep; }
.mm__grid { position: relative; flex: 1 1 auto; min-height: 0; display: grid; grid-template: repeat(3, 1fr) / repeat(4, 1fr); gap: $sp-2; }
.mm__card { position: relative; width: 100%; height: 100%; padding: 0; border: 0; background: none; cursor: pointer; }
.mm__card:focus-visible { outline: 2px solid $subject-ink; outline-offset: 2px; }
.mm__inner {
position: absolute; inset: 0;
transform-style: preserve-3d;
transition: transform $dur-base $easing;
}
.mm__card.is-open .mm__inner,
.mm__card.is-matched .mm__inner { transform: rotateY(180deg); }
.mm__face {
position: absolute; inset: 0;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
display: grid; place-items: center;
border-radius: $r-sm;
}
.mm__face svg { width: clamp(18px, 6vw, 26px); height: clamp(18px, 6vw, 26px); }
.mm__face--back {
background-color: $subject-cream;
border: 2px solid rgba($subject-ink, .18);
color: $color; // 뒷면 반짝임 문양은 진파랑
}
.mm__face--front {
background-color: $stage-paper;
border: 2px solid rgba($subject-ink, .14);
transform: rotateY(180deg);
}
// 앞면 아이콘 색 — 노랑 무대 위 흰 카드 면에 AA 를 넘기는 넉 색만
.mm__card[data-face="star"] .mm__face--front,
.mm__card[data-face="lightning"] .mm__face--front { color: $subject-orange-deep; }
.mm__card[data-face="heart"] .mm__face--front { color: $error; }
.mm__card[data-face="moon"] .mm__face--front,
.mm__card[data-face="flower"] .mm__face--front { color: $subject-blue-deep; }
.mm__card[data-face="rocket"] .mm__face--front { color: $subject-ink; }
// 매치된 짝은 테두리와 광택으로 남는다 — 팝 애니메이션은 자기 중심에서
.mm__card.is-matched { animation-name: mmPop; animation-duration: 420ms; animation-timing-function: $easing; animation-iteration-count: 1; }
.mm__card.is-matched .mm__face--front { border-color: $color; box-shadow: 0 0 0 3px rgba($color, .22); }
@keyframes mmPop {
0% { transform: scale(1); }
45% { transform: scale(1.09); }
100% { transform: scale(1); }
}
// 클리어 오버레이 — [hidden] 과 display 를 함께 쓰면 [hidden] 이 지는 것을 막는다
.mm__clear { position: absolute; inset: 0; z-index: 6; display: grid; place-items: center; margin: 0; background-color: rgba($subject-ink, .55); border-radius: $r-sm; }
.mm__clear[hidden] { display: none; }
.mm__clear b {
display: inline-block; padding: $sp-2 $sp-4; border-radius: $r-pill;
background-color: $color; color: $subject-cream;
font-weight: 800; font-size: clamp(10px, 2.6vw, 13px);
animation-name: mmClearIn; animation-duration: $dur-enter; animation-timing-function: $easing;
animation-iteration-count: 1; animation-fill-mode: both;
}
@keyframes mmClearIn {
from { opacity: 0; transform: scale(.82); }
to { opacity: 1; transform: scale(1); }
}
// ── 격자 미리보기 고스트 카드 ─────────────────────────────────
// 실제 패 위에 같은 크기로 겹쳐 둔 연출용 카드. 짝(하트 2장 · 별 2장)이 순서대로 뒤집혀 하이라이트된다.
// 사람이 손을 대면 .is-demo 가 떨어져 사라진다.
.mm__ghost { display: none; position: absolute; z-index: 4; pointer-events: none; }
.mm.is-demo .mm__ghost { display: block; }
.mm__ghost--a { grid-area: 1 / 2; }
.mm__ghost--b { grid-area: 3 / 3; }
.mm__ghost--c { grid-area: 1 / 4; }
.mm__ghost--d { grid-area: 2 / 1; }
.mm__ghostInner {
position: absolute; inset: 0;
transform-style: preserve-3d;
animation-name: mmGhostFlip;
animation-duration: $duration;
animation-timing-function: steps(1, end); // 모서리뷰 유령 프레임 방지 — 뒤집기는 컷으로
animation-iteration-count: infinite;
animation-fill-mode: backwards;
}
.mm__ghost--a .mm__ghostInner { animation-delay: 100ms; }
.mm__ghost--b .mm__ghostInner { animation-delay: 340ms; }
.mm__ghost--c .mm__ghostInner { animation-delay: 1100ms; }
.mm__ghost--d .mm__ghostInner { animation-delay: 1340ms; }
.mm__ghost--a .mm__face--front,
.mm__ghost--b .mm__face--front { color: $error; } // 하트 짝
.mm__ghost--c .mm__face--front,
.mm__ghost--d .mm__face--front { color: $subject-orange-deep; } // 별 짝
// 하이라이트 펄스 — 짝을 이루는 두 장이 같은 순간에 뛴다(래퍼와 이너가 요소가 달라 transform 이 충돌하지 않는다)
.mm__ghost--a, .mm__ghost--b {
animation-name: mmGhostPulse1; animation-duration: $duration; animation-timing-function: $easing; animation-iteration-count: infinite;
}
.mm__ghost--c, .mm__ghost--d {
animation-name: mmGhostPulse2; animation-duration: $duration; animation-timing-function: $easing; animation-iteration-count: infinite;
}
@keyframes mmGhostFlip {
0% { transform: rotateY(0deg); }
3% { transform: rotateY(180deg); }
90% { transform: rotateY(180deg); }
94% { transform: rotateY(0deg); }
100% { transform: rotateY(0deg); }
}
@keyframes mmGhostPulse1 {
0%, 27% { transform: scale(1); }
38% { transform: scale(1.1); }
51%, 100% { transform: scale(1); }
}
@keyframes mmGhostPulse2 {
0%, 78% { transform: scale(1); }
86% { transform: scale(1.1); }
97%, 100% { transform: scale(1); }
}
@media (max-width: 340px) {
.mm { gap: $sp-1; }
.mm__grid { gap: $sp-1; }
.mm__stats { gap: $sp-2; }
}
// reduce 에서는 뒤집기·펄스를 끈다 — 카드는 즉시 뒤집히고 매치 표시는 정적 테두리로만
@media (prefers-reduced-motion: reduce) {
.mm__inner { transition: none !important; }
.mm__card.is-matched { animation: none !important; }
.mm__clear b { animation: none !important; }
.mm.is-demo .mm__ghost,
.mm.is-demo .mm__ghostInner { animation: none !important; }
}html, body {
margin: 0;
overflow: hidden;
}
.stage {
box-sizing: border-box;
min-height: 100vh;
display: grid;
place-items: center;
margin: 0;
background: #ffd23f;
font-family: -apple-system, "Segoe UI", "Noto Sans KR", sans-serif;
padding: clamp(8px, 4vw, 24px);
}
.mm {
display: flex;
flex-direction: column;
gap: 8px;
width: 100%;
max-width: 280px;
height: 100%;
}
.mm__bar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}
.mm__title {
margin: 0;
font-weight: 800;
font-size: clamp(12px, 3vw, 15px);
color: #17141a;
}
.mm__restart {
display: grid;
place-items: center;
width: clamp(24px, 5vw, 28px);
aspect-ratio: 1;
padding: 0;
border: 2px solid rgba(23, 20, 26, 0.32);
border-radius: 12px;
background: none;
color: #17141a;
cursor: pointer;
}
.mm__restart svg {
width: 62%;
height: 62%;
}
.mm__restart:focus-visible {
outline: 2px solid #17141a;
outline-offset: 2px;
}
.mm__stats {
display: flex;
align-items: baseline;
gap: 12px;
}
.mm__stat {
display: inline-flex;
align-items: baseline;
gap: 4px;
}
.mm__num {
font-weight: 800;
font-size: clamp(11px, 2.8vw, 14px);
color: #17141a;
}
.mm__label {
font-weight: 700;
font-size: clamp(8px, 2.2vw, 10px);
color: rgba(23, 20, 26, 0.72);
}
.mm__trophy {
width: clamp(12px, 3vw, 14px);
height: clamp(12px, 3vw, 14px);
color: #c93000;
}
.mm__grid {
position: relative;
flex: 1 1 auto;
min-height: 0;
display: grid;
grid-template: repeat(3, 1fr)/repeat(4, 1fr);
gap: 8px;
}
.mm__card {
position: relative;
width: 100%;
height: 100%;
padding: 0;
border: 0;
background: none;
cursor: pointer;
}
.mm__card:focus-visible {
outline: 2px solid #17141a;
outline-offset: 2px;
}
.mm__inner {
position: absolute;
inset: 0;
transform-style: preserve-3d;
transition: transform 300ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.mm__card.is-open .mm__inner,
.mm__card.is-matched .mm__inner {
transform: rotateY(180deg);
}
.mm__face {
position: absolute;
inset: 0;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
display: grid;
place-items: center;
border-radius: 8px;
}
.mm__face svg {
width: clamp(18px, 6vw, 26px);
height: clamp(18px, 6vw, 26px);
}
.mm__face--back {
background-color: #fff7e6;
border: 2px solid rgba(23, 20, 26, 0.18);
color: #0a4fe8;
}
.mm__face--front {
background-color: #ffffff;
border: 2px solid rgba(23, 20, 26, 0.14);
transform: rotateY(180deg);
}
.mm__card[data-face=star] .mm__face--front,
.mm__card[data-face=lightning] .mm__face--front {
color: #c93000;
}
.mm__card[data-face=heart] .mm__face--front {
color: #c2361a;
}
.mm__card[data-face=moon] .mm__face--front,
.mm__card[data-face=flower] .mm__face--front {
color: #0a4fe8;
}
.mm__card[data-face=rocket] .mm__face--front {
color: #17141a;
}
.mm__card.is-matched {
animation-name: mmPop;
animation-duration: 420ms;
animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
animation-iteration-count: 1;
}
.mm__card.is-matched .mm__face--front {
border-color: #0a4fe8;
box-shadow: 0 0 0 3px rgba(10, 79, 232, 0.22);
}
@keyframes mmPop {
0% {
transform: scale(1);
}
45% {
transform: scale(1.09);
}
100% {
transform: scale(1);
}
}
.mm__clear {
position: absolute;
inset: 0;
z-index: 6;
display: grid;
place-items: center;
margin: 0;
background-color: rgba(23, 20, 26, 0.55);
border-radius: 8px;
}
.mm__clear[hidden] {
display: none;
}
.mm__clear b {
display: inline-block;
padding: 8px 16px;
border-radius: 999px;
background-color: #0a4fe8;
color: #fff7e6;
font-weight: 800;
font-size: clamp(10px, 2.6vw, 13px);
animation-name: mmClearIn;
animation-duration: 600ms;
animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
animation-iteration-count: 1;
animation-fill-mode: both;
}
@keyframes mmClearIn {
from {
opacity: 0;
transform: scale(0.82);
}
to {
opacity: 1;
transform: scale(1);
}
}
.mm__ghost {
display: none;
position: absolute;
z-index: 4;
pointer-events: none;
}
.mm.is-demo .mm__ghost {
display: block;
}
.mm__ghost--a {
grid-area: 1/2;
}
.mm__ghost--b {
grid-area: 3/3;
}
.mm__ghost--c {
grid-area: 1/4;
}
.mm__ghost--d {
grid-area: 2/1;
}
.mm__ghostInner {
position: absolute;
inset: 0;
transform-style: preserve-3d;
animation-name: mmGhostFlip;
animation-duration: 2s;
animation-timing-function: steps(1, end);
animation-iteration-count: infinite;
animation-fill-mode: backwards;
}
.mm__ghost--a .mm__ghostInner {
animation-delay: 100ms;
}
.mm__ghost--b .mm__ghostInner {
animation-delay: 340ms;
}
.mm__ghost--c .mm__ghostInner {
animation-delay: 1100ms;
}
.mm__ghost--d .mm__ghostInner {
animation-delay: 1340ms;
}
.mm__ghost--a .mm__face--front,
.mm__ghost--b .mm__face--front {
color: #c2361a;
}
.mm__ghost--c .mm__face--front,
.mm__ghost--d .mm__face--front {
color: #c93000;
}
.mm__ghost--a, .mm__ghost--b {
animation-name: mmGhostPulse1;
animation-duration: 2s;
animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
animation-iteration-count: infinite;
}
.mm__ghost--c, .mm__ghost--d {
animation-name: mmGhostPulse2;
animation-duration: 2s;
animation-timing-function: cubic-bezier(0.2, 0.8, 0.2, 1);
animation-iteration-count: infinite;
}
@keyframes mmGhostFlip {
0% {
transform: rotateY(0deg);
}
3% {
transform: rotateY(180deg);
}
90% {
transform: rotateY(180deg);
}
94% {
transform: rotateY(0deg);
}
100% {
transform: rotateY(0deg);
}
}
@keyframes mmGhostPulse1 {
0%, 27% {
transform: scale(1);
}
38% {
transform: scale(1.1);
}
51%, 100% {
transform: scale(1);
}
}
@keyframes mmGhostPulse2 {
0%, 78% {
transform: scale(1);
}
86% {
transform: scale(1.1);
}
97%, 100% {
transform: scale(1);
}
}
@media (max-width: 340px) {
.mm {
gap: 4px;
}
.mm__grid {
gap: 4px;
}
.mm__stats {
gap: 8px;
}
}
@media (prefers-reduced-motion: reduce) {
.mm__inner {
transition: none !important;
}
.mm__card.is-matched {
animation: none !important;
}
.mm__clear b {
animation: none !important;
}
.mm.is-demo .mm__ghost,
.mm.is-demo .mm__ghostInner {
animation: none !important;
}
}// 짝 맞추기 — 카드 12장(6쌍)은 HTML 에 정적으로 있고 JS 가 불러오자마자 자리를 섞는다.
// 상태기계: 첫 장 오픈 → 둘째 장 오픈 → 같으면 매치 고정, 다르면 700ms 뒤 복귀.
// 최고 기록은 최소 Tries 수(p301-02-best)다.
(function () {
var KEY = 'p301-02-best';
var CLEAR_TEXT = 'Clear! {n} tries · {t}s';
var NEW_BEST = 'New best!';
var root = document.getElementById('mm');
var grid = document.getElementById('mmGrid');
var triesEl = document.getElementById('mmTries');
var pairsEl = document.getElementById('mmPairs');
var bestEl = document.getElementById('mmBest');
var clearEl = document.getElementById('mmClear');
var clearMsgEl = document.getElementById('mmClearMsg');
var first = null, lock = false, tries = 0, left = 6, startAt = 0;
function loadBest() {
try { return Number(window.localStorage.getItem(KEY)) || 0; } catch (e) { return 0; }
}
function saveBest(v) {
try { window.localStorage.setItem(KEY, String(v)); } catch (e) { /* 저장소가 막힌 창은 건너뛴다 */ }
}
var best = loadBest();
if (best) { bestEl.textContent = String(best); }
function shuffle() {
var cards = [].slice.call(grid.querySelectorAll('.mm__card'));
for (var i = cards.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var t = cards[i]; cards[i] = cards[j]; cards[j] = t;
}
for (var k = 0; k < cards.length; k++) { grid.appendChild(cards[k]); }
}
function reset() {
first = null; lock = false; tries = 0; left = 6; startAt = 0;
triesEl.textContent = '0';
pairsEl.textContent = '6';
clearEl.hidden = true;
var cards = grid.querySelectorAll('.mm__card');
for (var i = 0; i < cards.length; i++) {
cards[i].classList.remove('is-open', 'is-matched');
cards[i].disabled = false;
cards[i].setAttribute('aria-pressed', 'false');
}
shuffle();
}
function finish() {
var t = Math.round((Date.now() - startAt) / 100) / 10; // s 단위 한 자리
var msg = CLEAR_TEXT.replace('{n}', String(tries)).replace('{t}', String(t));
if (!best || tries < best) {
best = tries; saveBest(best); bestEl.textContent = String(best);
msg = msg + ' ' + NEW_BEST;
}
clearMsgEl.textContent = msg;
clearEl.hidden = false;
}
grid.addEventListener('click', function (e) {
var btn = e.target.closest ? e.target.closest('.mm__card') : null;
if (!btn || btn.disabled || lock || btn.classList.contains('is-open')) { return; }
root.classList.remove('is-demo');
if (!startAt) { startAt = Date.now(); }
btn.classList.add('is-open');
btn.setAttribute('aria-pressed', 'true');
if (!first) { first = btn; return; }
var a = first; first = null; lock = true;
tries++; triesEl.textContent = String(tries);
if (a.getAttribute('data-face') === btn.getAttribute('data-face')) {
setTimeout(function () {
a.classList.add('is-matched'); btn.classList.add('is-matched');
a.disabled = true; btn.disabled = true;
left--; pairsEl.textContent = String(left);
lock = false;
if (left === 0) { finish(); }
}, 350);
} else {
setTimeout(function () {
a.classList.remove('is-open'); btn.classList.remove('is-open');
a.setAttribute('aria-pressed', 'false'); btn.setAttribute('aria-pressed', 'false');
lock = false;
}, 700);
}
});
document.getElementById('mmRestart').addEventListener('click', function () {
root.classList.remove('is-demo');
reset();
});
shuffle();
})();// MemoryPairFlip — vanilla 판(run/301/demo/02-memory-pair-flip/index.html) 의 React 포트.
// 카드 12장(6쌍)을 상태로 들고 섞고, 두 장 오픈 → 같으면 매치 고정, 다르면 700ms 뒤 복귀.
// 뒤집기는 CSS(rotateY + preserve-3d + backface-visibility)가 하고 React 는 상태만 바꾼다.
// 최고 기록은 최소 시도 수(p301-02-best).
import { useEffect, useRef, useState } from "react";
import type { CSSProperties } from "react";
import styles from "./MemoryPairFlip.module.scss";
export type MemoryPairFlipProps = {
duration?: number;
easing?: string;
accentColor?: string;
};
type Vars = CSSProperties & { "--duration"?: string; "--easing"?: string; "--color"?: string };
type FaceKey = "star" | "heart" | "moon" | "rocket" | "lightning" | "flower";
type TimerBox = { current: number[] }; // ambient 의 useRef 는 T|null 을 돌려주므로 단언용
const KEY = "p301-02-best";
const TOTAL = 12;
const TITLE = "짝 맞추기 카드";
const RESTART_LABEL = "다시 섞기";
const TRIES_LABEL = "시도";
const PAIRS_LABEL = "남은 짝";
const BEST_LABEL = "최고 기록";
const CARD_LABEL = "{n}번 카드";
const CLEAR_TEXT = "클리어! 시도 {n}회 · {t}초";
const NEW_BEST = "최고 기록 갱신!";
// Phosphor Duotone(무료 아이콘 세트) 경로 — [20% 채움 경로, 본 경로]
const BACK_PATHS: [string, string] = [
"m194.82 151.43l-55.09 20.3l-20.3 55.09a7.92 7.92 0 0 1-14.86 0l-20.3-55.09l-55.09-20.3a7.92 7.92 0 0 1 0-14.86l55.09-20.3l20.3-55.09a7.92 7.92 0 0 1 14.86 0l20.3 55.09l55.09 20.3a7.92 7.92 0 0 1 0 14.86",
"M197.58 129.06L146 110l-19-51.62a15.92 15.92 0 0 0-29.88 0L78 110l-51.62 19a15.92 15.92 0 0 0 0 29.88L78 178l19 51.62a15.92 15.92 0 0 0 29.88 0L146 178l51.62-19a15.92 15.92 0 0 0 0-29.88ZM137 164.22a8 8 0 0 0-4.74 4.74L112 223.85L91.78 169a8 8 0 0 0-4.78-4.78L32.15 144L87 123.78a8 8 0 0 0 4.78-4.78L112 64.15L132.22 119a8 8 0 0 0 4.74 4.74L191.85 144ZM144 40a8 8 0 0 1 8-8h16V16a8 8 0 0 1 16 0v16h16a8 8 0 0 1 0 16h-16v16a8 8 0 0 1-16 0V48h-16a8 8 0 0 1-8-8m104 48a8 8 0 0 1-8 8h-8v8a8 8 0 0 1-16 0v-8h-8a8 8 0 0 1 0-16h8v-8a8 8 0 0 1 16 0v8h8a8 8 0 0 1 8 8",
];
const FACE_PATHS: Record<FaceKey, [string, string]> = {
star: [
"m229.06 108.79l-48.7 42l14.88 62.79a8.4 8.4 0 0 1-12.52 9.17L128 189.09l-54.72 33.65a8.4 8.4 0 0 1-12.52-9.17l14.88-62.79l-48.7-42A8.46 8.46 0 0 1 31.73 94l63.91-5.2l24.62-59.6a8.36 8.36 0 0 1 15.48 0l24.62 59.6l63.91 5.2a8.46 8.46 0 0 1 4.79 14.79",
"M239.18 97.26A16.38 16.38 0 0 0 224.92 86l-59-4.76l-22.78-55.09a16.36 16.36 0 0 0-30.27 0L90.11 81.23L31.08 86a16.46 16.46 0 0 0-9.37 28.86l45 38.83L53 211.75a16.38 16.38 0 0 0 24.5 17.82l50.5-31.08l50.53 31.08A16.4 16.4 0 0 0 203 211.75l-13.76-58.07l45-38.83a16.43 16.43 0 0 0 4.94-17.59m-15.34 5.47l-48.7 42a8 8 0 0 0-2.56 7.91l14.88 62.8a.37.37 0 0 1-.17.48c-.18.14-.23.11-.38 0l-54.72-33.65a8 8 0 0 0-8.38 0l-54.72 33.67c-.15.09-.19.12-.38 0a.37.37 0 0 1-.17-.48l14.88-62.8a8 8 0 0 0-2.56-7.91l-48.7-42c-.12-.1-.23-.19-.13-.5s.18-.27.33-.29l63.92-5.16a8 8 0 0 0 6.72-4.94l24.62-59.61c.08-.17.11-.25.35-.25s.27.08.35.25L153 91.86a8 8 0 0 0 6.75 4.92l63.92 5.16c.15 0 .24 0 .33.29s0 .4-.16.5",
],
heart: [
"M232 102c0 66-104 122-104 122S24 168 24 102a54 54 0 0 1 54-54c22.59 0 41.94 12.31 50 32c8.06-19.69 27.41-32 50-32a54 54 0 0 1 54 54",
"M178 40c-20.65 0-38.73 8.88-50 23.89C116.73 48.88 98.65 40 78 40a62.07 62.07 0 0 0-62 62c0 70 103.79 126.66 108.21 129a8 8 0 0 0 7.58 0C136.21 228.66 240 172 240 102a62.07 62.07 0 0 0-62-62m-50 174.8c-18.26-10.64-96-59.11-96-112.8a46.06 46.06 0 0 1 46-46c19.45 0 35.78 10.36 42.6 27a8 8 0 0 0 14.8 0c6.82-16.67 23.15-27 42.6-27a46.06 46.06 0 0 1 46 46c0 53.61-77.76 102.15-96 112.8",
],
moon: [
"M227.89 147.89A96 96 0 1 1 108.11 28.11a96.09 96.09 0 0 0 119.78 119.78",
"M233.54 142.23a8 8 0 0 0-8-2a88.08 88.08 0 0 1-109.8-109.8a8 8 0 0 0-10-10a104.84 104.84 0 0 0-52.91 37A104 104 0 0 0 136 224a103.1 103.1 0 0 0 62.52-20.88a104.84 104.84 0 0 0 37-52.91a8 8 0 0 0-1.98-7.98m-44.64 48.11A88 88 0 0 1 65.66 67.11a89 89 0 0 1 31.4-26A106 106 0 0 0 96 56a104.11 104.11 0 0 0 104 104a106 106 0 0 0 14.92-1.06a89 89 0 0 1-26.02 31.4",
],
rocket: [
"m94.81 192l-29.45 22.24a8 8 0 0 1-12.81-4.51L40.19 154.1a8 8 0 0 1 1.66-6.86l30.31-36.33C71 134.25 76.7 161.43 94.81 192m119.34-44.76l-30.31-36.33c1.21 23.34-4.54 50.52-22.65 81.09l29.45 22.24a8 8 0 0 0 12.81-4.51l12.36-55.63a8 8 0 0 0-1.66-6.86",
"M152 224a8 8 0 0 1-8 8h-32a8 8 0 0 1 0-16h32a8 8 0 0 1 8 8m-24-112a12 12 0 1 0-12-12a12 12 0 0 0 12 12m95.62 43.83l-12.36 55.63a16 16 0 0 1-25.51 9.11L158.51 200h-61l-27.26 20.57a16 16 0 0 1-25.51-9.11l-12.36-55.63a16.09 16.09 0 0 1 3.32-13.71l28.56-34.26a123 123 0 0 1 8.57-36.67c12.9-32.34 36-52.63 45.37-59.85a16 16 0 0 1 19.6 0c9.34 7.22 32.47 27.51 45.37 59.85a123 123 0 0 1 8.57 36.67l28.56 34.26a16.09 16.09 0 0 1 3.32 13.71M99.43 184h57.14c21.12-37.54 25.07-73.48 11.74-106.88C156.55 47.64 134.49 29 128 24c-6.51 5-28.57 23.64-40.33 53.12c-13.31 33.4-9.36 69.34 11.76 106.88m-15 5.85q-16.15-29.35-19.6-57.69L48 152.36L60.36 208l.18-.13ZM208 152.36l-16.83-20.2q-3.42 28.28-19.56 57.69l23.85 18l.18.13Z",
],
lightning: [
"m96 240l16-80l-64-24L160 16l-16 80l64 24Z",
"M215.79 118.17a8 8 0 0 0-5-5.66L153.18 90.9l14.66-73.33a8 8 0 0 0-13.69-7l-112 120a8 8 0 0 0 3 13l57.63 21.61l-14.62 73.25a8 8 0 0 0 13.69 7l112-120a8 8 0 0 0 1.94-7.26M109.37 214l10.47-52.38a8 8 0 0 0-5-9.06L62 132.71l84.62-90.66l-10.46 52.38a8 8 0 0 0 5 9.06l52.8 19.8Z",
],
flower: [
"M206.35 136.29c-8.87-5.13-24.46-7.38-39.4-8.29c14.94-.91 30.53-3.16 39.4-8.29a32 32 0 1 0-32-55.42c-8.87 5.12-18.61 17.48-26.87 30C154.17 80.87 160 66.25 160 56a32 32 0 0 0-64 0c0 10.25 5.83 24.87 12.52 38.26c-8.26-12.49-18-24.85-26.87-30a32 32 0 1 0-32 55.42c8.87 5.13 24.46 7.38 39.4 8.29c-14.94.91-30.53 3.16-39.4 8.29a32 32 0 1 0 32 55.42c8.87-5.12 18.61-17.48 26.87-30C101.83 175.13 96 189.75 96 200a32 32 0 0 0 64 0c0-10.25-5.83-24.87-12.52-38.26c8.26 12.49 18 24.85 26.87 30a32 32 0 1 0 32-55.42ZM155.71 144a32 32 0 1 1 4.29-16a31.74 31.74 0 0 1-4.29 16",
"M210.35 129.36c-.81-.47-1.7-.92-2.62-1.36c.92-.44 1.81-.89 2.62-1.36a40 40 0 1 0-40-69.28c-.81.47-1.65 1-2.48 1.59c.08-1 .13-2 .13-3a40 40 0 0 0-80 0c0 .94 0 1.94.13 3c-.83-.57-1.67-1.12-2.48-1.59a40 40 0 1 0-40 69.28c.81.47 1.7.92 2.62 1.36c-.92.44-1.81.89-2.62 1.36a40 40 0 1 0 40 69.28c.81-.47 1.65-1 2.48-1.59c-.08 1-.13 1.94-.13 2.95a40 40 0 0 0 80 0c0-.94-.05-1.94-.13-2.95c.83.57 1.67 1.12 2.48 1.59a39.8 39.8 0 0 0 19.94 5.36a40.4 40.4 0 0 0 10.42-1.38a40 40 0 0 0 9.64-73.28ZM104 128a24 24 0 1 1 24 24a24 24 0 0 1-24-24m74.35-56.79a24 24 0 1 1 24 41.57c-6.27 3.63-18.61 6.13-35.16 7.19a40 40 0 0 0-12.66-21.87c9.2-13.82 17.55-23.26 23.82-26.89M128 32a24 24 0 0 1 24 24c0 7.24-4 19.19-11.36 34.06a39.8 39.8 0 0 0-25.28 0C108.36 75.19 104 63.24 104 56a24 24 0 0 1 24-24M44.86 80a24 24 0 0 1 32.79-8.79c6.27 3.63 14.62 13.07 23.82 26.89A40 40 0 0 0 88.81 120c-16.55-1.06-28.89-3.56-35.16-7.18A24 24 0 0 1 44.86 80m32.79 104.79a24 24 0 1 1-24-41.57c6.27-3.63 14.62-6.13 35.16-7.19a40 40 0 0 0 12.66 21.87c-9.2 13.82-17.55 23.26-23.82 26.89M128 224a24 24 0 0 1-24-24c0-7.24 4-19.19 11.36-34.06a39.8 39.8 0 0 0 25.28 0C148.36 180.81 152 192.76 152 200a24 24 0 0 1-24 24m83.14-48a24 24 0 0 1-32.79 8.79c-6.27-3.63-14.62-13.07-23.82-26.89a40 40 0 0 0 12.66-21.9c16.55 1.06 28.89 3.56 35.16 7.18a24 24 0 0 1 8.79 32.82",
],
};
function DuotoneIcon({ paths }: { paths: [string, string] }) {
return (
<svg viewBox="0 0 256 256" aria-hidden="true" focusable="false">
<g fill="currentColor">
<path d={paths[0]} opacity=".2" />
<path d={paths[1]} />
</g>
</svg>
);
}
function shuffled(): FaceKey[] {
const deck: FaceKey[] = ["star", "heart", "moon", "rocket", "lightning", "flower", "star", "heart", "moon", "rocket", "lightning", "flower"];
for (let i = deck.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const t = deck[i]; deck[i] = deck[j]; deck[j] = t;
}
return deck;
}
export default function MemoryPairFlip({
duration = 2000,
easing = "cubic-bezier(.2, .8, .2, 1)",
accentColor = "#0a4fe8",
}: MemoryPairFlipProps) {
const [deck, setDeck] = useState<FaceKey[]>(shuffled);
const [open, setOpen] = useState<number[]>([]);
const [matched, setMatched] = useState<boolean[]>(Array(TOTAL).fill(false));
const [tries, setTries] = useState(0);
const [best, setBest] = useState(0);
const [demo, setDemo] = useState(true);
const [clearText, setClearText] = useState<string | null>(null);
const lockRef = useRef(false);
const startRef = useRef(0);
const timersRef = useRef<number[]>([]) as TimerBox;
const vars: Vars = { "--duration": `${duration}ms`, "--easing": easing, "--color": accentColor };
useEffect(() => {
try {
const v = Number(window.localStorage.getItem(KEY)) || 0;
if (v) { setBest(v); }
} catch (e) { /* 저장소가 막힌 창은 기본값 그대로 */ }
return () => { timersRef.current.forEach((t) => window.clearTimeout(t)); };
}, []);
// 전부 맞추면 클리어 문구와 최고 기록을 확정한다
useEffect(() => {
if (!matched.length || !matched.every(Boolean)) { return; }
const t = Math.round((Date.now() - (startRef.current || Date.now())) / 100) / 10;
let msg = CLEAR_TEXT.replace("{n}", String(tries)).replace("{t}", String(t));
if (!best || tries < best) {
setBest(tries);
try { window.localStorage.setItem(KEY, String(tries)); } catch (e) { /* 저장 건너뛰기 */ }
msg = msg + " " + NEW_BEST;
}
setClearText(msg);
}, [matched]);
function onCard(i: number) {
if (lockRef.current || matched[i] || open.indexOf(i) >= 0 || clearText) { return; }
setDemo(false);
if (!startRef.current) { startRef.current = Date.now(); }
if (open.length === 0) { setOpen([i]); return; }
const a = open[0];
setOpen([a, i]);
setTries(tries + 1);
lockRef.current = true;
if (deck[a] === deck[i]) {
timersRef.current.push(window.setTimeout(() => {
setMatched((prev) => prev.map((v, k) => (k === a || k === i ? true : v)));
setOpen([]);
lockRef.current = false;
}, 350));
} else {
timersRef.current.push(window.setTimeout(() => {
setOpen([]);
lockRef.current = false;
}, 700));
}
}
function restart() {
timersRef.current.forEach((t) => window.clearTimeout(t));
timersRef.current = [];
lockRef.current = false; startRef.current = 0;
setDemo(false);
setDeck(shuffled());
setOpen([]);
setMatched(Array(TOTAL).fill(false));
setTries(0);
setClearText(null);
}
const left = matched.filter((v) => !v).length / 2;
const cls = [styles.root, demo ? styles.isDemo : ""].filter(Boolean).join(" ");
const cardCls = (i: number): string =>
[styles.card, open.indexOf(i) >= 0 ? styles.isOpen : "", matched[i] ? styles.isMatched : ""]
.filter(Boolean).join(" ");
return (
<main className={styles.stage}>
<div className={cls} style={vars}>
<header className={styles.bar}>
<p className={styles.title}>{TITLE}</p>
<button className={styles.restart} type="button" aria-label={RESTART_LABEL} onClick={restart}>
<svg viewBox="0 0 256 256" aria-hidden="true" focusable="false">
<g fill="currentColor">
<path d="M216 128a88 88 0 1 1-88-88a88 88 0 0 1 88 88" opacity=".2" />
<path d="M240 56v48a8 8 0 0 1-8 8h-48a8 8 0 0 1 0-16h27.4l-26.59-24.36l-.25-.24a80 80 0 1 0-1.67 114.78a8 8 0 0 1 11 11.63A95.44 95.44 0 0 1 128 224h-1.32a96 96 0 1 1 69.07-164L224 85.8V56a8 8 0 1 1 16 0" />
</g>
</svg>
</button>
</header>
<div className={styles.stats}>
<span className={styles.stat}><b className={styles.num}>{tries}</b><span className={styles.label}>{TRIES_LABEL}</span></span>
<span className={styles.stat}><b className={styles.num}>{left}</b><span className={styles.label}>{PAIRS_LABEL}</span></span>
<span className={styles.statBest} aria-label={BEST_LABEL}>
<svg className={styles.trophy} viewBox="0 0 256 256" aria-hidden="true" focusable="false">
<g fill="currentColor">
<path d="M200 48v63.1c0 39.7-31.75 72.6-71.45 72.9A72 72 0 0 1 56 112V48Z" opacity=".2" />
<path d="M232 64h-24V48a8 8 0 0 0-8-8H56a8 8 0 0 0-8 8v16H24A16 16 0 0 0 8 80v16a40 40 0 0 0 40 40h3.65A80.13 80.13 0 0 0 120 191.61V216H96a8 8 0 0 0 0 16h64a8 8 0 0 0 0-16h-24v-24.42c31.94-3.23 58.44-25.64 68.08-55.58H208a40 40 0 0 0 40-40V80a16 16 0 0 0-16-16M48 120a24 24 0 0 1-24-24V80h24v32q0 4 .39 8Zm144-8.9c0 35.52-29 64.64-64 64.9a64 64 0 0 1-64-64V56h128ZM232 96a24 24 0 0 1-24 24h-.5a82 82 0 0 0 .5-8.9V80h24Z" />
</g>
</svg>
<b className={styles.num}>{best || "-"}</b>
</span>
</div>
<div className={styles.grid}>
{deck.map((face, i) => (
<button
key={i}
className={cardCls(i)}
type="button"
data-face={face}
aria-label={CARD_LABEL.replace("{n}", String(i + 1))}
aria-pressed={open.indexOf(i) >= 0 || matched[i] ? "true" : "false"}
disabled={matched[i]}
onClick={() => onCard(i)}
>
<span className={styles.inner}>
<span className={styles.faceBack}><DuotoneIcon paths={BACK_PATHS} /></span>
<span className={styles.faceFront} data-face={face}><DuotoneIcon paths={FACE_PATHS[face]} /></span>
</span>
</button>
))}
<span className={`${styles.ghost} ${styles.ghostA}`} aria-hidden="true">
<span className={styles.ghostInner}>
<span className={styles.faceBack}><DuotoneIcon paths={BACK_PATHS} /></span>
<span className={styles.faceFront}><DuotoneIcon paths={FACE_PATHS.heart} /></span>
</span>
</span>
<span className={`${styles.ghost} ${styles.ghostB}`} aria-hidden="true">
<span className={styles.ghostInner}>
<span className={styles.faceBack}><DuotoneIcon paths={BACK_PATHS} /></span>
<span className={styles.faceFront}><DuotoneIcon paths={FACE_PATHS.heart} /></span>
</span>
</span>
<span className={`${styles.ghost} ${styles.ghostC}`} aria-hidden="true">
<span className={styles.ghostInner}>
<span className={styles.faceBack}><DuotoneIcon paths={BACK_PATHS} /></span>
<span className={styles.faceFront}><DuotoneIcon paths={FACE_PATHS.star} /></span>
</span>
</span>
<span className={`${styles.ghost} ${styles.ghostD}`} aria-hidden="true">
<span className={styles.ghostInner}>
<span className={styles.faceBack}><DuotoneIcon paths={BACK_PATHS} /></span>
<span className={styles.faceFront}><DuotoneIcon paths={FACE_PATHS.star} /></span>
</span>
</span>
<p className={styles.clear} role="status" hidden={clearText === null}>
<b>{clearText || CLEAR_TEXT}</b>
</p>
</div>
</div>
</main>
);
}02 Memory pair cards — Measured area 1.367% · moving frames 16/23Original by GODRICH · SCSS and React ship in the zip · 9 CSS Game Demos — Mini Games in HTML & CSS
The post this demo lives in
9 CSS Game Demos — Mini Games in HTML & CSSA css game runs its rules and its screen on nothing but selectors, keyframes, and transform. These nine were built with See all demos in this post
If you like this effect - similar demos
game01 Ball Pair Exchanging Velocity Through an Elastic Collision9 Bouncing Ball Animation Patterns With Physics
game08 Start-Angle Map Colored by Time Until FlipDouble Pendulum Simulation: 9 Chaos Scenes
game07 A Symmetry Fold View That Merges Positions Equal Under Rotation and Flip Into One BoardCSS Tic Tac Toe: 9 Boards That Count Ahead