Emi Matchu
535a0029f9
Oh sweet, I learned about a new CSS feature with good-enough support! This lets you use CSS transitions for an element as it enters the page, or becomes visible. Firefox only has partial support for this feature rn, but its partial support covers our case, I tested to make sure! (Specifically, it doesn't handle transitioning from `display: none` yet, which isn't what we're doing.)
398 lines
8.5 KiB
Sass
398 lines
8.5 KiB
Sass
@import "../partials/clean/constants"
|
|
@import "../partials/clean/mixins"
|
|
@import "../partials/item_header"
|
|
|
|
#container
|
|
width: 900px // A bit more generous to the preview area!
|
|
|
|
.item-header
|
|
+item-header
|
|
|
|
#item-contributors
|
|
+subtle-banner
|
|
clear: both
|
|
margin:
|
|
bottom: 0
|
|
top: 2em
|
|
|
|
header
|
|
display: inline
|
|
font-weight: bold
|
|
margin-right: .25em
|
|
|
|
footer
|
|
display: inline
|
|
|
|
ul
|
|
display: inline
|
|
list-style: none
|
|
|
|
li
|
|
display: inline
|
|
|
|
&::after
|
|
content: ", "
|
|
|
|
&:last-child::after
|
|
content: "."
|
|
|
|
.nc-icon
|
|
height: 16px
|
|
width: 16px
|
|
|
|
.preview-area
|
|
margin: 0 auto
|
|
position: relative
|
|
|
|
.customize-more
|
|
position: absolute
|
|
top: 1em
|
|
right: 1em
|
|
|
|
display: flex
|
|
align-items: center
|
|
text-decoration: none
|
|
|
|
background: #EDF2F7
|
|
padding-inline: .75em
|
|
border-radius: .375em
|
|
min-height: 2rem
|
|
min-width: 2rem
|
|
box-sizing: border-box
|
|
|
|
.customize-more-label
|
|
width: 0
|
|
overflow: hidden
|
|
transition: width .25s
|
|
white-space: nowrap
|
|
--natural-width: auto
|
|
|
|
measured-content
|
|
padding-right: .5em
|
|
|
|
&:hover, &:focus
|
|
// Expand the label to its natural width. If the JS ran to tell us
|
|
// what it is in px, we can use that for a smooth transition. If not,
|
|
// okay, we just pop out to `auto`, which CSS can't make smooth.
|
|
.customize-more-label
|
|
width: var(--natural-width)
|
|
|
|
outfit-viewer
|
|
display: block
|
|
position: relative
|
|
width: 300px
|
|
height: 300px
|
|
border: 1px solid $module-border-color
|
|
border-radius: 1em
|
|
overflow: hidden
|
|
|
|
// There's no useful text in here, but double-clicking the play/pause
|
|
// button can cause a weird selection state. Disable text selection.
|
|
user-select: none
|
|
-webkit-user-select: none
|
|
|
|
outfit-layer
|
|
display: block
|
|
position: absolute
|
|
inset: 0
|
|
|
|
// We disable pointer-events most importantly for the iframes, which
|
|
// will ignore our `cursor: wait` and show a plain cursor for the
|
|
// inside of its own document. But also, the context menus for these
|
|
// elements are kinda actively misleading, too!
|
|
pointer-events: none
|
|
|
|
img, iframe
|
|
width: 100%
|
|
height: 100%
|
|
|
|
.loading-indicator
|
|
position: absolute
|
|
z-index: 1000
|
|
bottom: 0px
|
|
right: 4px
|
|
padding: 8px
|
|
background: radial-gradient(circle closest-side, white 45%, #ffffff00)
|
|
|
|
opacity: 0
|
|
transition: opacity .5s
|
|
|
|
.play-pause-button
|
|
position: absolute
|
|
z-index: 1001
|
|
left: 8px
|
|
bottom: 8px
|
|
display: none
|
|
align-items: center
|
|
justify-content: center
|
|
color: white
|
|
background: rgba(0, 0, 0, 0.64)
|
|
width: 2.5em
|
|
height: 2.5em
|
|
border-radius: 100%
|
|
border: 2px solid transparent
|
|
transition: all .25s
|
|
|
|
.playing-label, .paused-label
|
|
display: none
|
|
width: 1em
|
|
height: 1em
|
|
|
|
.play-pause-toggle
|
|
// Visually hidden
|
|
clip: rect(0 0 0 0)
|
|
clip-path: inset(50%)
|
|
height: 1px
|
|
overflow: hidden
|
|
position: absolute
|
|
white-space: nowrap
|
|
width: 1px
|
|
|
|
&:checked ~ .playing-label
|
|
display: block
|
|
|
|
&:not(:checked) ~ .paused-label
|
|
display: block
|
|
|
|
&:hover, &:has(.play-pause-toggle:focus)
|
|
border: 2px solid $module-border-color
|
|
background: $module-bg-color
|
|
color: $text-color
|
|
|
|
&:has(.play-pause-toggle:active)
|
|
transform: translateY(2px)
|
|
|
|
&:has(outfit-layer:state(has-animations))
|
|
.play-pause-button
|
|
display: flex
|
|
|
|
.error-indicator
|
|
font-size: 85%
|
|
color: $error-color
|
|
margin-top: .25em
|
|
margin-bottom: .5em
|
|
display: none
|
|
|
|
// When loading, fade in the loading spinner after a brief delay. We are
|
|
// loading when the <turbo-frame> is busy, or when at least one layer
|
|
// is loading.
|
|
//
|
|
// We only apply the delay here, not on the base styles, because fading
|
|
// *out* on load should be instant.
|
|
#item-preview[busy] outfit-viewer, outfit-viewer:has(outfit-layer:state(loading))
|
|
cursor: wait
|
|
|
|
.loading-indicator
|
|
opacity: 1
|
|
transition-delay: 2s
|
|
|
|
// If the outfit *starts* in loading state, still delay the fade-in.
|
|
@starting-style
|
|
opacity: 0
|
|
|
|
#item-preview:has(outfit-layer:state(error))
|
|
outfit-viewer
|
|
border: 2px solid red
|
|
.error-indicator
|
|
display: block
|
|
|
|
species-color-picker
|
|
.error-icon
|
|
cursor: help
|
|
margin-right: .25em
|
|
|
|
form[data-is-valid="false"]
|
|
select
|
|
border-color: $error-border-color
|
|
color: $error-color
|
|
|
|
// If JS is enabled, but auto-loading isn't ready yet (script loading or
|
|
// failed?), hide the submit button for .75sec, to give it time to load.
|
|
@media (scripting: enabled)
|
|
input[type=submit]
|
|
position: absolute
|
|
margin-left: .5em
|
|
opacity: 0
|
|
animation: fade-in .25s forwards
|
|
animation-delay: .75s
|
|
|
|
// Once the auto-loading behavior is ready, remove the submit button.
|
|
&:state(auto-loading)
|
|
input[type=submit]
|
|
display: none
|
|
|
|
species-face-picker
|
|
display: block
|
|
position: relative
|
|
margin-top: -10px
|
|
|
|
species-face-picker-options
|
|
display: flex
|
|
justify-content: center
|
|
flex-wrap: wrap
|
|
isolation: isolate // avoid z-index conflicts between pets and noscript
|
|
overflow: auto
|
|
max-height: 200px // 4 rows of 50px images, and padding will offer a hint of below
|
|
padding: 10px // leave enough room for the zoomed-in selected face
|
|
|
|
img
|
|
width: 54px
|
|
height: 54px
|
|
transition: all 0.2s
|
|
|
|
// Calm down the default color, just a smidge! There's a lot of color
|
|
// on this page already, y'know?
|
|
opacity: .9
|
|
filter: saturate(90%)
|
|
|
|
label
|
|
display: flex
|
|
overflow: hidden
|
|
transition: all 0.2s
|
|
position: relative
|
|
line-height: 1
|
|
|
|
// NOTE: The box-shadows here were copy-pasted from Impress 2020, which uses
|
|
// Chakra UI's styling system to generate them! (The colors are from their
|
|
// color palette, too.)
|
|
&:has(input:checked)
|
|
border-radius: 6px
|
|
z-index: 1
|
|
background: #9AE6B4
|
|
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),0 10px 10px -5px rgba(0, 0, 0, 0.04), #2F855A 0 0 2px 2px
|
|
transform: scale(1.1)
|
|
|
|
&:has(input:focus)
|
|
background: #BEE3F8
|
|
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),0 10px 10px -5px rgba(0, 0, 0, 0.04), #4299e1 0 0 0 3px
|
|
transform: scale(1.2)
|
|
|
|
input[type=radio]
|
|
position: absolute
|
|
left: -10000px
|
|
top: auto
|
|
width: 1px
|
|
height: 1px
|
|
overflow: hidden
|
|
|
|
&:checked + img
|
|
opacity: 1
|
|
filter: saturate(110%)
|
|
|
|
&:disabled + img
|
|
opacity: .6
|
|
filter: saturate(0%)
|
|
|
|
label:has(input[type=radio]:disabled)
|
|
cursor: not-allowed
|
|
|
|
noscript
|
|
position: absolute
|
|
inset: 0
|
|
padding: 1em
|
|
background: rgba(white, .8)
|
|
z-index: 1
|
|
cursor: auto
|
|
|
|
display: flex
|
|
align-items: center
|
|
justify-content: center
|
|
text-align: center
|
|
|
|
&:has(species-face-picker-options[inert])
|
|
cursor: wait
|
|
|
|
.item-preview-meta-info
|
|
display: grid
|
|
grid-template-columns: 1fr auto
|
|
gap: .5em
|
|
align-items: center
|
|
|
|
.item-zones-info
|
|
h3
|
|
display: inline
|
|
font: inherit
|
|
font-weight: bold
|
|
&:after
|
|
content: ": "
|
|
|
|
ul
|
|
list-style-type: none
|
|
display: inline
|
|
|
|
li
|
|
display: inline
|
|
&:not(:last-of-type):after
|
|
content: ", "
|
|
|
|
.no-zones
|
|
font-style: italic
|
|
opacity: .85
|
|
|
|
.zone-species-info
|
|
font-style: italic
|
|
text-decoration: underline dotted
|
|
|
|
// Many of these styles copied from Impress 2020 and its Chakra UI styles!
|
|
.item-html5-info
|
|
display: flex
|
|
align-items: center
|
|
border: 1px solid
|
|
border-radius: .375em
|
|
padding: 4px 8px
|
|
min-height: 30px
|
|
box-sizing: border-box
|
|
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px
|
|
|
|
&[data-status=converted]
|
|
background: $module-bg-color
|
|
color: $text-color
|
|
|
|
svg:nth-of-type(2)
|
|
margin-right: -4px // spacing hacks!
|
|
|
|
&[data-status=unconverted]
|
|
background: $warning-bg-color
|
|
color: #975A16
|
|
gap: .25em // spacing hacks!
|
|
|
|
svg:first-of-type
|
|
width: 12px
|
|
height: 12px
|
|
|
|
svg:nth-of-type(2)
|
|
width: 20px
|
|
height: 20px
|
|
|
|
#item-preview
|
|
display: flex
|
|
flex-direction: column
|
|
gap: .75em
|
|
|
|
@media (min-width: 700px)
|
|
display: grid
|
|
grid-template-areas: "viewer faces" "picker meta"
|
|
gap: .5em
|
|
|
|
.preview-area
|
|
grid-area: viewer
|
|
outfit-viewer
|
|
width: 380px
|
|
height: 380px
|
|
|
|
species-color-picker
|
|
grid-area: picker
|
|
|
|
species-face-picker
|
|
grid-area: faces
|
|
species-face-picker-options
|
|
max-height: 380px
|
|
|
|
.item-preview-meta-info
|
|
grid-area: meta
|
|
|
|
@keyframes fade-in
|
|
from
|
|
opacity: 0
|
|
to
|
|
opacity: 1
|