Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

HTML

              
                <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: none;">
	<symbol id="star" viewBox="0 0 48 45.7">
		<path d="M24 37.9L9.2 45.7 12 29.1 0 17.4 16.6 15 24 0l7.4 15L48 17.4 36 29.1l2.8 16.6z"/>
	</symbol>
	<symbol id="no-rating" viewBox="0 0 44 44">
		<path d="M22 0C9.9 0 0 9.9 0 22s9.9 22 22 22 22-9.9 22-22S34.1 0 22 0zm16 22c0 3.3-1 6.4-2.8 9L13 8.8C15.6 7 18.7 6 22 6c8.8 0 16 7.2 16 16zM6 22c0-3.3 1-6.4 2.8-9L31 35.2C28.4 37 25.3 38 22 38c-8.8 0-16-7.2-16-16z"/>
	</symbol>
</svg>

<form action="#" method="post">
	<fieldset class="rate-radios">
		<legend>How would you rate the product?</legend>

		<div id="avatar" aria-hidden="true" style="opacity: 0;">
			<div>
				<svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 350 350" width="200">
					<defs>
						<clipPath id="eye-clip">
							<path id="eye-clippath" class="eye-path" fill="none" d="M211 76.91c-11.42.47-23.35.71-35.63.71s-24.21-.24-35.63-.71a39.82 39.82 0 00-4.37 18.18 40.25 40.25 0 001.16 9.57c12.39-.55 25.41-.85 38.84-.85s26.45.3 38.84.85a40.25 40.25 0 001.16-9.57A39.82 39.82 0 00211 76.91z"/>
						</clipPath>
						<clipPath id="mouth-clip">
							<path id="mouth-clippath" class="mouth-path" fill="none" d="M147.32 165.64h56.12a8.94 8.94 0 018.94 8.94 33.06 33.06 0 01-33.06 33.06h-7.88a33.06 33.06 0 01-33.06-33.06 8.94 8.94 0 018.94-8.94z"/>
						</clipPath>
					</defs>
					<circle cx="175" cy="175" r="175" fill="#F8EDFF"/>
					<g id="ear-l">
						<circle cx="66.93" cy="137.42" r="40" fill="#e7cafa" stroke="#62457a" stroke-linecap="round" stroke-width="5"/>
						<path fill="#e7cafa" stroke="#62457a" stroke-linecap="round" stroke-width="5" d="M64.55 123a14.39 14.39 0 000 28.78"/>
					</g>
					<g id="ear-r">
						<circle cx="283.07" cy="137.42" r="40" fill="#e7cafa" stroke="#62457a" stroke-linecap="round" stroke-width="5"/>
						<path fill="#e7cafa" stroke="#62457a" stroke-linecap="round" stroke-width="5" d="M285.45 123a14.39 14.39 0 010 28.78"/>
					</g>
					<rect id="earring" width="12" height="30" x="284.65" y="169.64" fill="#faf18f" stroke="#62457a" stroke-linecap="round" stroke-width="4.73" rx="6"/>
					<path id="horn-2" fill="#f0a6df" stroke="#62457a" stroke-linecap="round" stroke-width="5" d="M224.58 46.46A98.05 98.05 0 01229-1.46 3.94 3.94 0 00223-6a61.34 61.34 0 00-21.44 27.72c-.57 0-2.22 12.57 5.64 20a19.76 19.76 0 0017.38 4.74z"/>
					<path id="horn-1" fill="#f0a6df" stroke="#62457a" stroke-linecap="round" stroke-width="5" d="M122.5 46.46a97.93 97.93 0 00-4.41-47.92 3.94 3.94 0 016-4.53 61.32 61.32 0 0121.43 27.72c.57 0 2.22 12.57-5.64 20a19.76 19.76 0 01-17.38 4.73z"/>
					<path fill="#A45CE0" d="M275 118.7c0-54.6-44.7-101-99.3-101.3C120.1 17 75 61.9 75 117.3v44.5c0 46-9.6 91.1-27.8 132.7C79.1 328.7 124.6 350 175 350s95.9-21.3 127.8-55.5C284.6 253 275 207.8 275 161.9v-43.2z"/>
					<path fill="none" stroke="#62457A" stroke-linecap="round" stroke-linejoin="round" stroke-width="5" d="M302.8 294.5C284.6 253 275 207.8 275 161.9v-43.2c0-54.6-44.7-101-99.3-101.3C120.1 17 75 61.9 75 117.3v44.5c0 46-9.6 91.1-27.8 132.7"/>
					<path id="horn-5" fill="#f0a6df" stroke="#62457a" stroke-linecap="round" stroke-width="5" d="M169.31-24.43l-8.77 51.28a15.57 15.57 0 0026 0l-8.77-51.28a4.29 4.29 0 00-8.46 0z"/>
					<path id="horn-4" fill="#f0a6df" stroke="#62457a" stroke-linecap="round" stroke-width="5" d="M253.74 61.74c2.54-14.44 6.9-25.16 15.5-36.94a4 4 0 00-4.52-6c-11.41 3.88-26.8 15.66-34.48 25.2a15.39 15.39 0 004.39 16 24.18 24.18 0 0013.12 6.1 5.3 5.3 0 005.99-4.36z"/>
					<path id="horn-3" fill="#f0a6df" stroke="#62457a" stroke-linecap="round" stroke-width="5" d="M93.34 61.74c-2.54-14.44-6.9-25.16-15.5-36.94a4 4 0 014.52-6c11.41 3.88 26.8 15.66 34.48 25.2a15.39 15.39 0 01-4.39 16 24.18 24.18 0 01-13.12 6.1 5.3 5.3 0 01-5.99-4.36z"/>
					<g id="nose">
						<circle cx="168.38" cy="147.81" r="3.5" fill="#62457a"/>
						<circle cx="182.38" cy="147.81" r="3.5" fill="#62457a"/>
					</g>
					<path id="chin" fill="#a45ce0" stroke="#62457a" stroke-linecap="round" stroke-linejoin="round" stroke-width="5" d="M150.38 215.64a12.59 12.59 0 0011.87 8.36h1.26a12.59 12.59 0 0011.87-8.39 12.59 12.59 0 0011.87 8.39h1.26a12.59 12.59 0 0011.87-8.39"/>
					<path id="eye-bg" class="eye-path" fill="#fff" d="M211 76.91c-11.42.47-23.35.71-35.63.71s-24.21-.24-35.63-.71a39.82 39.82 0 00-4.37 18.18 40.25 40.25 0 001.16 9.57c12.39-.55 25.41-.85 38.84-.85s26.45.3 38.84.85a40.25 40.25 0 001.16-9.57A39.82 39.82 0 00211 76.91z"/>
					<g id="eye" clip-path="url(#eye-clip)">
						<g id="pupil">
							<circle cx="175.38" cy="95.09" r="25" fill="#ace4eb"/>
							<circle cx="175.38" cy="95.09" r="15" fill="#62457a"/>
							<circle cx="168.95" cy="84.37" r="4.29" fill="#fff"/>
						</g>
					</g>
					<path id="eye-outline" class="eye-path" fill="none" stroke="#62457a" stroke-linecap="round" stroke-linejoin="round" stroke-width="5" d="M211 76.91c-11.42.47-23.35.71-35.63.71s-24.21-.24-35.63-.71a39.82 39.82 0 00-4.37 18.18 40.25 40.25 0 001.16 9.57c12.39-.55 25.41-.85 38.84-.85s26.45.3 38.84.85a40.25 40.25 0 001.16-9.57A39.82 39.82 0 00211 76.91z"/>
					<path id="mouth-bg" class="mouth-path" fill="#775196" d="M179.32 207.64h-7.88a33 33 0 01-33.06-33.06 8.94 8.94 0 018.94-8.94h56.12a8.94 8.94 0 018.94 8.94 33 33 0 01-33.06 33.06z"/>
					<g id="mouth" clip-path="url(#mouth-clip)">
						<g id="tongue">
							<circle cx="175.61" cy="204.34" r="16" fill="#e3468a"/>
							<ellipse cx="175.61" cy="191.34" fill="#fff" opacity=".1" rx="6" ry="3"/>
						</g>
						<path id="tooth-bot" fill="#fff" d="M160.95 200.64h4a4 4 0 014 4v7h-12v-7a4 4 0 014-4z"/>
						<path id="tooth-top" fill="#fff" d="M177.95 161.64h16v9a4 4 0 01-4 4h-8a4 4 0 01-4-4v-9z"/>
					</g>
					<path id="mouth-outline" class="mouth-path" fill="none" stroke="#62457a" stroke-linecap="round" stroke-linejoin="round" stroke-width="5" d="M179.32 207.64h-7.88a33 33 0 01-33.06-33.06h0a8.94 8.94 0 018.94-8.94h56.12a8.94 8.94 0 018.94 8.94h0a33 33 0 01-33.06 33.06z"/>
				</svg>
			</div>
			</div>
		
		<input checked type="radio" name="rate-input" id="rate-input_0" data-num="0">
		<label for="rate-input_0" class="rate-radio rate-radio--none">
			<svg aria-hidden="true" focusable="false">
				<use xlink:href="#no-rating"/>
			</svg>
			<span role="presentation">No rating</span>
		</label>

		<input type="radio" name="rate-input" id="rate-input_1" data-num="1">
		<label for="rate-input_1" class="rate-radio">
			<svg aria-hidden="true" focusable="false">
				<use xlink:href="#star"/>
			</svg>
			<span role="presentation">1 Star</span>
		</label>

		<input type="radio" name="rate-input" id="rate-input_2" data-num="2">
		<label for="rate-input_2" class="rate-radio">
			<svg aria-hidden="true" focusable="false">
				<use xlink:href="#star"/>
			</svg>
			<span role="presentation">2 Stars</span>
		</label>

		<input type="radio" name="rate-input" id="rate-input_3" data-num="3">
		<label for="rate-input_3" class="rate-radio">
			<svg aria-hidden="true" focusable="false">
				<use xlink:href="#star"/>
			</svg>
			<span role="presentation">3 Stars</span>
		</label>

		<input type="radio" name="rate-input" id="rate-input_4" data-num="4">
		<label for="rate-input_4" class="rate-radio">
			<svg aria-hidden="true" focusable="false">
				<use xlink:href="#star"/>
			</svg>
			<span role="presentation">4 Stars</span>
		</label>

		<input type="radio" name="rate-input" id="rate-input_5" data-num="5">
		<label for="rate-input_5" class="rate-radio">
			<svg aria-hidden="true" focusable="false">
				<use xlink:href="#star"/>
			</svg>
			<span role="presentation">5 Stars</span>
		</label>
	</fieldset>
</form>
              
            
!

CSS

              
                @import url('https://rsms.me/inter/inter.css');

body, html {width: 100%; height: 100%; font-family: 'Inter', sans-serif;}
body * {box-sizing: border-box;}

:root {
	--purple-bare: #F8EDFF;
	--purple-light: #e7cafa;
	--purple-core: #7E26C8;
	--purple-dark: #62457a;
	--red: #e3468a;
	--red-dark: #9e1852;
	--gold: #faf18f;
}

form {
	width: 100%; height: 100%;
	display: flex; justify-content: center; align-items: center;
}
symbol {overflow: visible;}

legend {
	margin: 0 0 1.5em;
	display: block; width: 100%;
	font-size: 1.25em; font-weight: 700; text-align: center;
	color: var(--purple-core);
}

#avatar {
	margin: 0 auto 1em;
	width: 150px;
	div {
		position: relative;
		width: 100%; height: 0;
		padding-bottom: 100%;
		svg {
			position: absolute; 
			width: 100%; height: 100%;
			overflow: visible;
		}
	}
}

input[type="radio"] {
	/* Visually hide radio buttons while still allowing them to receive keyboard focus. */
	position: absolute; top: auto; z-index: 2;
	width: 1.5em; height: 2em;
	-webkit-appearance: none; -moz-appearance: none; appearance: none;
	opacity: .0001;
}

.rate-radio {
	margin: 0 .5em 0 0;
	position: relative;	
	display: inline-block; vertical-align: top;
	color: #2a2a2a; line-height: 1;
	&:last-of-type {margin-right: 0;}
	svg {
		display: block;
		width: 3em; height: 2.85em;
		fill: var(--purple-bare);
		stroke: #000; stroke-width: 3px; stroke-linejoin: round;
		transform: scale(.625);
		transition: transform .2s ease-in-out;
		overflow: visible;
	}
	span {
		padding: .4em .5em;	
		position: absolute; left: 50%; top: 100%;
		background: #333; border: solid 2px var(--purple-dark); border-radius: .25em;
		color: #fff; font-size: .8em; font-weight: 600;
		text-align: center; white-space: nowrap;	
		opacity: 0;
		transform: translateY(.5em) translateX(-50%) scale(0);
		transition:
			opacity .25s ease-in-out,
			transform .25s ease-in-out
		;
		&::before {
			content: "";
			position: absolute; top: 0; left: 0; z-index: -1;
			width: 100%; height: 100%;
			border-radius: inherit;
			background: var(--purple-core);
			opacity: 0;
			transition: opacity .25s ease;
		}
	}
	
	@media (prefers-reduced-motion: reduce) {
		svg {
			transform: none;
			transition: transform .5s ease-in-out;
		}
		span {
			transform: translateY(.5em) translateX(-50%);
			transition:
				opacity .5s ease-in-out,
				transform .5s ease-in-out
			;
		}
	}
}
.rate-radio--none {
	svg {
		width: 2.85em; height: 2.85em;
		fill: #FFF; stroke: var(--red-dark);
	}
	span {}
}

input:focus + .rate-radio {
	outline: dotted .25em #CCC; outline-offset: .5em;
}

fieldset:not([disabled]) input:not([disabled]):hover + .rate-radio span,
.rate-radio:hover span,
input:focus + .rate-radio span {
	opacity: 1;
	transform: translateY(.5em) translateX(-50%) scale(1);
}

fieldset:not([disabled]) input:not([disabled]):checked + .rate-radio span,
.rate-radio:checked span,
input:checked + .rate-radio span {
	opacity: 1;
	background: var(--purple-core);
	transform: translateY(.5em) translateX(-50%) scale(1);
	&::before {opacity: 1;}
}

input:checked + .rate-radio span {
	background: #333;
	border: 2px solid var(--purple-dark);
}

input:checked + .rate-radio--none span {
	
}

/**
* Set any rating icon that appears in the DOM, AFTER the checked input as appearing unselected.
* If no input was checked by default, the first radio item will be auto selected, and that's the "none" option
*/
input:checked ~ .rate-radio svg {
	fill: var(--purple-bare);
	transform: scale(.625);
	@media (prefers-reduced-motion: reduce) {
		transform: none;
	}
}

/**
* If the no-rating option isn't checked get it to look all unselected again
*/
input:not(:checked) ~ .rate-radio--none svg {
	fill: var(--purple-dark);
	transform: scale(.625);
	@media (prefers-reduced-motion: reduce) {
		transform: none;
	}
}


/**
* The selectors that create the "selected" styling for the actual checked input, and the inputs previous to it in the DOM.
*/
.rate-radio svg, 
input:checked + .rate-radio svg {
	fill: var(--gold); stroke: var(--purple-dark);
	transform: scale(1) translateY(-.25em);
	@media (prefers-reduced-motion: reduce) {
		transform: none;
	}
}

/**
* Coloring for when the "no rating" selection is currently active
*/
input:checked + .rate-radio--none svg {
	fill: var(--red); stroke: var(--red-dark);
	transform: scale(1);
}

              
            
!

JS

              
                console.clear();

/* selector functions */
const $ = (s, o = document) => o.querySelector(s);
const $$ = (s, o = document) => o.querySelectorAll(s);

/* store references to all of the elements we'll need */
const inputs = $$('input[type="radio"]');
const horn1 = $('#horn-1'), horn2 = $('#horn-2'), horn3 = $('#horn-3'), horn4 = $('#horn-4'), horn5 = $('#horn-5');
const earL = $('#ear-l'), earR = $('#ear-r'), earring = $('#earring');
const pupil = $('#pupil');
const eyePaths = $$('.eye-path'), mouthPaths = $$('.mouth-path');
const chin = $('#chin'), tongue = $('#tongue'), toothTop = $('#tooth-top'), toothBot = $('#tooth-bot');
const avatar = $('#avatar');

/* path data for shape morphing */
const eye0 = "M175.4,75.3c-12,0-23.4-0.9-33.7-2.5c-4.2,6.4-6.7,14-6.7,22.2c0,12.4,5.7,23.5,14.6,30.9c6.9,5.7,15.8,9.1,25.4,9.1c9.7,0,18.5-3.4,25.4-9.1c8.9-7.3,14.6-18.4,14.6-30.9c0-8.2-2.5-15.8-6.7-22.1C198.3,74.5,187.1,75.3,175.4,75.3z";
const eye1 = "M213.3,82.3c-9.7,4-23.1,6.5-37.9,6.5s-28.2-2.5-37.9-6.5c-1.3,4-2.1,8.3-2.1,12.8c0,11,4.4,20.9,11.6,28.1c8.2-1.8,18-2.9,28.4-2.9s20.2,1.1,28.4,2.9c7.2-7.2,11.6-17.2,11.6-28.1C215.4,90.6,214.6,86.3,213.3,82.3z";
const eye2 = "M215.4,95.1c0-7.4-2-14.3-5.5-20.3c-9.3,2.5-21.3,4-34.5,4s-25.1-1.5-34.5-4c-3.5,6-5.5,12.9-5.5,20.3c0,13.1,6.3,24.7,16,32c7.2-1.1,15.4-1.7,24-1.7s16.8,0.6,24,1.7C209.1,119.8,215.4,108.2,215.4,95.1z";
const eye3 = "M152.9,128.2c6.8-0.9,14.5-1.5,22.5-1.5s15.7,0.5,22.5,1.5c10.6-7.2,17.5-19.3,17.5-33.1c0-12.8-6-24.2-15.4-31.5c-7.4,2-15.7,3.2-24.6,3.2s-17.3-1.2-24.6-3.2c-9.4,7.3-15.4,18.7-15.4,31.5C135.4,108.8,142.3,121,152.9,128.2z";
const eye4 = "M150.7,128.1c7.3-1.1,15.6-1.7,24.3-1.7s17,0.6,24.3,1.7c10.1-7.5,16.7-19.5,16.7-33c0-13.4-6.4-25.3-16.4-32.8c-6.9-5.2-15.4-8.2-24.6-8.2c-9.5,0-18.2,3.2-25.2,8.6c-9.6,7.5-15.8,19.2-15.8,32.4C134,108.6,140.6,120.6,150.7,128.1z";
const eye5 = "M219,95.1c0,12-4.7,23-12.4,30.9c-7.9,8.1-19,13.1-31.6,13.1c-12.2,0-23.2-4.9-31.1-12.9c-8-8-12.9-19-12.9-31.1c0-13.7,6.2-25.9,16-34c7.6-6.3,17.4-10,28-10c9.9,0,19.1,3.3,26.4,8.8C212.1,67.9,219,80.7,219,95.1z";
const mouth0 = "M174.6,178.2h5.1H215c0,0,0.1,0,0.1,0c0,0,0,0-0.1,0h-35.3L174.6,178.2l-4.6,0.1h-35c0,0-0.1,0-0.1,0c0,0,0,0,0.1,0h35H174.6z";
const mouth1 = "M175,172.6h7c8.9,0,16.2,6.4,17.7,14.9c0.2,1,0.3,2,0.3,3.1c0,0.8-0.5,2-2,2l-16,0h-7h-7l-16,0c-1.4,0-2-1.2-2-2c0-1,0.1-1.9,0.2-2.8c1.4-8.6,8.8-15.1,17.7-15.1H175z";
const mouth2 = "M175,187c5.5,0,9.7-2.1,13.8-4.1c5.5-2.7,11.3-5.5,17.6-0.4c0.1,0.1,0.3,0.3,0.2,0.4c-0.1,0.1-0.3,0.1-0.4,0c-5.6-5.1-11.7-2.6-17.4,0.2c-4.2,2-7.3,4.1-13.9,4.1c-6.5,0-9-2.1-12.9-4.1c-5.1-2.8-10.6-5.8-18.6-0.6c-0.1,0-0.1,0-0.1,0c0,0,0-0.1,0.1-0.1c7.9-5.4,13.4-2.4,18.8,0.5C165.9,185,169.7,187,175,187z";
const mouth3 = "M175,179.8c2,0,4-0.1,6-0.2c11-0.9,22-4.1,32.9-9.7c0.1,0,0.2-0.1,0.2,0c0,0.1-0.1,0.2-0.2,0.2c-11.6,6-21.7,9-33,9.7c-2,0.1-4,0.3-6,0.3c-2.3,0-4.6-0.1-6.8-0.3c-10.9-0.8-20.8-3.9-32.1-9.7c-0.1,0-0.1-0.1-0.1-0.1c0,0,0.1,0,0.2,0c10.7,5.5,21.4,8.7,32.1,9.6C170.5,179.7,172.7,179.8,175,179.8z";
const mouth4 = "M174.8,172.6h10H200l0,4.9c0,1.4-0.2,2.7-0.6,4c-1.8,5.9-7.5,10.1-14.3,10.1h-10.4h-9.9c-6.7,0-12.3-4.2-14.2-9.9c-0.4-1.3-0.7-2.7-0.7-4.2v-4.9h14.3H174.8z";
const mouth5 = "M175,165.6h4.8l23.3,0c5.6,0,8.9,4.7,8.9,8.9c0,3-0.4,6-1.2,8.7c-3.8,14-16.7,24.3-31.9,24.3H175h-3.9c-15.5,0-28.6-10.7-32.1-25.2c-0.6-2.5-0.9-5.2-0.9-7.9c0-5,4.1-8.9,8.9-8.9l23.9,0H175z";

/* vars */
let curRating = 0;
let tl;
let durReduced = 0, durNoPref = .5, dur;
let eyeTarg, mouthTarg, chinY, pupilS, earS, earY, earRotL, earRotR, earringX, earringY, tongueY, toothTopY, toothBotY;
const horns = [horn1,horn2,horn3,horn4,horn5];
let hornsU = [], hornsD = horns;
let mq;



// set up matchMedia instance to detect the reduced motion media query
mq = window.matchMedia('(prefers-reduced-motion: reduce)');
// safari doesn't support 'matchMedia.addEventListener' so we have to check support for that and add the legacy 'addListener' if not.
if(mq.addEventListener) {
	mq.addEventListener('change', onReduceMotionMQ);
} else {
	mq.addListener(onReduceMotionMQ);
}
// manually check media query initially
onReduceMotionMQ();



// activate any gsap plugins
gsap.registerPlugin(MorphSVGPlugin);

// set initial visual properties of avatar
gsap.set(earL, 		{transformOrigin: "40px 40px", rotate: "-15deg", y: 10, scale: .9});
gsap.set(earR, 		{transformOrigin: "40px 40px", rotate: "15deg", y: 10, scale: .9});
gsap.set(earring, 		{transformOrigin: "50% 0", x: -12, y: 8});
gsap.set(pupil,		{transformOrigin: "50% 50%"});
gsap.set(eyePaths, 		{morphSVG: eye0});
gsap.set(mouthPaths,	{morphSVG: mouth0});
gsap.set(chin, 		{y: 0});
gsap.set(horn1,		{transformOrigin: "20px 45px", scale: 0});
gsap.set(horn2,		{transformOrigin: "12px 45px", scale: 0});
gsap.set(horn3,		{transformOrigin: "32px 38px", scale: 0});
gsap.set(horn4,		{transformOrigin: "12px 38px", scale: 0});
gsap.set(horn5,		{transformOrigin: "50% 90%", scale: 0});
gsap.set(avatar, 		{opacity: 1});



/* add click handler to inputs */
inputs.forEach(function(i) {
	i.addEventListener("click", onRatingClick);
});

function onRatingClick(e) {
	// determine which rating was clicked
	let num = parseInt(e.target.getAttribute('data-num'));
	
	// crate new timeline
	tl = gsap.timeline({paused: true, defaults:{duration: dur, ease: "sine.out"}});
	
	// determine which horns go up/down
	hornsU = horns.slice(0,num);
	if(hornsU.length > curRating) {hornsU = hornsU.slice(curRating);}
	hornsD = horns.slice(num,curRating);
	
	// set props based on which rating was clicked on
	switch (num) {
		case 0:
			eyeTarg = eye0;
			mouthTarg = mouth0;
			chinY = 0;
			pupilS = 1;
			earS = .9; earY = 10; earRotL = "-15deg"; earRotR = "15deg"; earringX = -12; earringY = 8;
			tongueY = 0; toothTopY = 0; toothBotY = 0;
			break;
		case 1:
			eyeTarg = eye1;
			mouthTarg = mouth1;
			chinY = 3;
			pupilS = .84;
			earS = 1.1; earY = -4; earRotL = "10deg"; earRotR = "-10deg"; earringX = 0; earringY = 0;
			tongueY = 2; toothTopY = 5; toothBotY = -17;
			break;
		case 2:
			eyeTarg = eye2;
			mouthTarg = mouth2;
			chinY = -2;
			pupilS = .94;
			earS = 1.05; earY = -2; earRotL = "5deg"; earRotR = "-5deg"; earringX = -2; earringY = -1;
			tongueY = 0; toothTopY = 0; toothBotY = 0;
			break;
		case 3:
			eyeTarg = eye3;
			mouthTarg = mouth3;
			chinY = -4;
			pupilS = 1;
			earS = 1; earY = 0; earRotL = "0deg"; earRotR = "0deg"; earringX = -4; earringY = -2;
			tongueY = 0; toothTopY = 0; toothBotY = 0;
			break;
		case 4:
			eyeTarg = eye4;
			mouthTarg = mouth4;
			chinY = 3;
			pupilS = 1.1;
			earS = .95; earY = -3; earRotL = "2deg"; earRotR = "-2deg"; earringX = -2; earringY = -5;
			tongueY = -4; toothTopY = 6; toothBotY = -16;
			break;
		case 5:
			eyeTarg = eye5;
			mouthTarg = mouth5;
			chinY = 14;
			pupilS = 1.2;
			earS = .9; earY = -6; earRotL = "4deg"; earRotR = "-4deg"; earringX = 0; earringY = -10;
			tongueY = 0; toothTopY = 2; toothBotY = -2;
			break;
		default:
			break;
	}
	
	tl
		.to(eyePaths, 			{morphSVG: eyeTarg}, 0)
		.to(mouthPaths, 		{morphSVG: mouthTarg}, 0)
		.to(chin, 			{y: chinY}, 0)
		.to(pupil, 			{scale: pupilS}, 0)
		.to(earL, 			{scale: earS, y: earY, rotate: earRotL}, 0)
		.to(earR, 			{scale: earS, y: earY, rotate: earRotR}, 0)
		.to(earring, 			{x: earringX, y: earringY}, 0)
		.to(tongue, 			{y: tongueY}, 0)
		.to(toothTop, 			{y: toothTopY}, 0)
		.to(toothBot, 			{y: toothBotY}, 0)
	;
	
	if(hornsU.length) {
		if(dur) {
			gsap.to(hornsU, 	{scale: 1, stagger:{each:.1, ease: "power1.out"}, duration: dur, ease: "back.out"});
		} else {
			gsap.set(hornsU, 	{scale: 1});
		}		
	}
	if(hornsD.length) {
		if(dur) {
			gsap.to(hornsD,	{scale: 0, stagger: {each:-.08, ease: "power2.out"}, duration: dur, ease: "back.in"});
		} else {
			gsap.set(hornsD,	{scale: 0});
		}
	}
	
	curRating = num;
	
	tl.play();
}



function onReduceMotionMQ() {
	// change animation time depending on user preference
	if(mq.matches) {
		dur = durReduced;
	} else {
		dur = durNoPref;
	}
}
              
            
!
999px

Console