02神経衰弱カード
めくった2枚が同じなら残り、違えば裏返る。rotateY の反転と残りペア数がゲームのリズムを作る。
使いどころ暇つぶしミニゲーム、学習カードの表面に問題を入れる
rotateY(preserve-3dbackface-visibility

<main class="stage">
<div class="mm is-demo" id="mm">
<header class="mm__bar">
<p class="mm__title">神経衰弱カード</p>
<button class="mm__restart" id="mmRestart" type="button" aria-label="シャッフル">
<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">試行</span></span>
<span class="mm__stat"><b class="mm__num" id="mmPairs">6</b><span class="mm__label">残りペア</span></span>
<span class="mm__stat mm__stat--best" aria-label="最高記録">
<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="カード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="カード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="カード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="カード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="カード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="カード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="カード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="カード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="カード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="カード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="カード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="カード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">クリア! {n}回 · {t}秒</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 뒤 복귀.
// 최고 기록은 최소 試行 수(p301-02-best)다.
(function () {
var KEY = 'p301-02-best';
var CLEAR_TEXT = 'クリア! {n}回 · {t}秒';
var 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; // 秒 단위 한 자리
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 神経衰弱カード — 計測 累積面積 1.367% · 動いたフレーム 16/23GODRICH オリジナル · SCSS と React は zip に同梱 · CSS ゲーム 作成 — CSSだけで動くミニゲーム9選
このデモが属する記事
CSS ゲーム 作成 — CSSだけで動くミニゲーム9選css ゲームとは、セレクタとキーフレームと transform だけでルールと画面の両方をまかなう仕掛けのことです。この9つはゲームエンジンなしで、素の HTML・CSS・バニラ JS だけで組んであり、下のグリッドでそのまま遊べます。 この記事のデモをすべて見る


