diff --git a/app/assets/stylesheets/wardrobe/show.css b/app/assets/stylesheets/wardrobe/show.css index 00f9ff7d..1955e9e0 100644 --- a/app/assets/stylesheets/wardrobe/show.css +++ b/app/assets/stylesheets/wardrobe/show.css @@ -1,5 +1,10 @@ @import "../application/item-badges.css"; +/* =================================================================== + Shared Components + Buttons, item cards, pagination, and other reusable patterns. + =================================================================== */ + /* Base button defaults - applied to all interactive controls */ button, input[type="submit"], @@ -124,6 +129,68 @@ select, } } +/* Item card - shared layout for worn items and search results */ +.item-card { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem; + background: #f9f9f9; + margin-bottom: 0.5rem; + border-radius: 8px; + color: #333; + transition: background 0.2s, box-shadow 0.2s; + position: relative; + + &:hover { + background: #f0f0f0; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + } + + &:hover :is(.item-add-button, .item-remove-button) { + opacity: 1; + } + + .item-thumbnail { + flex-shrink: 0; + width: 50px; + height: 50px; + border-radius: 6px; + overflow: hidden; + background: white; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + + img { + width: 100%; + height: 100%; + object-fit: contain; + display: block; + } + } + + .item-info { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 0.5rem; + } + + .item-name { + font-weight: 500; + color: #2D3748; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .item-badges { + display: flex; + gap: 0.375rem; + flex-wrap: wrap; + } +} + /* Pagination links - treated as buttons for consistency */ .pagination { a, @@ -169,6 +236,11 @@ select, } } +/* =================================================================== + Page Layout + Top-level grid: preview on left/top, controls on right/bottom. + =================================================================== */ + body.wardrobe-v2 { margin: 0; padding: 0; @@ -197,6 +269,11 @@ body.wardrobe-v2 { } } +/* =================================================================== + Outfit Preview + Left/top panel: outfit viewer, floating controls, pose picker. + =================================================================== */ + .outfit-preview-section { grid-area: preview; display: flex; @@ -292,308 +369,6 @@ body.wardrobe-v2 { display: none; } - /* Pose picker button */ - .pose-picker-button { - anchor-name: --pose-picker-anchor; - display: flex; - align-items: center; - gap: 0.5rem; - border-color: transparent; - font-size: 85%; - - .pose-emoji { - font-size: 1.1rem; - } - - .pose-label { - font-weight: normal; - min-width: 3.5rem; - } - - .chevron { - font-size: 0.8rem; - opacity: 0.7; - } - - &:focus, - &[popovertargetopen] { - border-color: rgba(255, 255, 255, 0.8); - } - } - - /* Pose picker popover */ - pose-picker-popover { - position: absolute; - position-anchor: --pose-picker-anchor; - margin: 0; - inset: auto; - position-area: top; - background: rgba(0, 0, 0, 0.9); - backdrop-filter: blur(12px); - -webkit-backdrop-filter: blur(12px); - border-radius: 12px; - padding: 1.25rem; - border: 1px solid rgba(255, 255, 255, 0.2); - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); - width: 20rem; - - .pose-picker-form { - display: flex; - flex-direction: column; - } - - .pose-picker-table { - border-collapse: separate; - border-spacing: 0.5rem; - - th { - text-align: center; - color: white; - padding: 0.25rem; - font-weight: normal; - } - - td { - padding: 0; - } - } - - .emoji-icon { - font-size: 1.25rem; - display: inline-block; - user-select: none; - } - - .pose-option { - display: block; - cursor: pointer; - position: relative; - width: 60px; - height: 60px; - margin: 0 auto; - - input[type="radio"] { - position: absolute; - opacity: 0; - width: 0; - height: 0; - } - - .pose-thumbnail { - width: 60px; - height: 60px; - border-radius: 8px; - overflow: hidden; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); - background: rgba(255, 255, 255, 0.1); - border: 2px solid transparent; - transition: all 0.2s; - display: flex; - align-items: center; - justify-content: center; - } - - .pose-thumbnail-viewer { - width: 60px !important; - height: 60px !important; - transform: scale(0.8); - } - - .pose-unavailable { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - opacity: 0.4; - - .question-mark { - font-size: 2rem; - } - } - - /* Selected state */ - input[type="radio"]:checked + .pose-thumbnail { - border-color: #48BB78; - box-shadow: 0 0 0 3px rgba(72, 187, 120, 0.4); - transform: scale(1.05); - } - - /* Hover state (only for available poses) */ - &.available:hover .pose-thumbnail { - border-color: rgba(255, 255, 255, 0.5); - transform: scale(1.05); - } - - /* Focus state */ - input[type="radio"]:focus + .pose-thumbnail { - border-color: rgba(255, 255, 255, 0.8); - box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.3); - } - - /* Unavailable state */ - &.unavailable { - cursor: not-allowed; - - .pose-thumbnail { - opacity: 0.5; - background: rgba(128, 128, 128, 0.2); - } - } - } - - /* Submit button: progressive enhancement pattern */ - .pose-submit-button { - margin-top: 1rem; - width: 100%; - } - - /* If JS is enabled, hide the submit button initially with a delay */ - @media (scripting: enabled) { - .pose-submit-button { - opacity: 0; - animation: fade-in 0.25s forwards; - animation-delay: 0.75s; - } - } - - /* Once auto-submit is enabled, hide the submit button completely */ - &:state(auto-loading) .pose-submit-button, - &:state(auto-loading) .style-submit-button { - display: none; - } - - /* Tab panel layout */ - .tab-list { - display: flex; - gap: 0.25rem; - margin-top: 1rem; - } - - .tab-button { - flex: 1; - padding: 0.4rem 0.75rem; - font-size: 0.85rem; - border-radius: 999px; - border: 1px solid rgba(255, 255, 255, 0.2); - background: rgba(255, 255, 255, 0.1); - color: rgba(255, 255, 255, 0.6); - cursor: pointer; - transition: all 0.2s; - - &:hover { - background: rgba(255, 255, 255, 0.15); - color: rgba(255, 255, 255, 0.8); - border-color: rgba(255, 255, 255, 0.3); - } - - &.active { - background: rgba(255, 255, 255, 0.2); - color: white; - border-color: rgba(255, 255, 255, 0.4); - } - } - - /* Without JS, hide tab buttons and show both panels stacked */ - tab-panel:not(:defined) .tab-list { - display: none; - } - - tab-panel:not(:defined) .tab-content[hidden] { - display: block !important; - } - - /* Style picker form */ - .style-picker-form { - display: flex; - flex-direction: column; - } - - .style-picker-list { - display: flex; - flex-direction: column; - gap: 0.25rem; - max-height: 200px; - overflow-y: auto; - } - - .style-option { - display: block; - cursor: pointer; - - input[type="radio"] { - position: absolute; - opacity: 0; - width: 0; - height: 0; - } - - .style-option-content { - display: flex; - align-items: center; - gap: 0.5rem; - padding: 0.375rem 0.5rem; - border-radius: 8px; - border: 2px solid transparent; - transition: all 0.2s; - } - - .style-option-thumbnail { - flex-shrink: 0; - width: 40px; - height: 40px; - border-radius: 6px; - overflow: hidden; - background: rgba(255, 255, 255, 0.1); - - img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - } - } - - .style-option-name { - color: white; - font-size: 0.9rem; - } - - /* Hover */ - &:hover .style-option-content { - border-color: rgba(255, 255, 255, 0.3); - background: rgba(255, 255, 255, 0.05); - } - - /* Selected state */ - input[type="radio"]:checked + .style-option-content { - border-color: #48BB78; - box-shadow: 0 0 0 2px rgba(72, 187, 120, 0.3); - background: rgba(72, 187, 120, 0.1); - } - - /* Focus state */ - input[type="radio"]:focus + .style-option-content { - border-color: rgba(255, 255, 255, 0.8); - box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.2); - } - } - - /* Style submit button: same progressive enhancement as pose */ - .style-submit-button { - margin-top: 1rem; - width: 100%; - } - - @media (scripting: enabled) { - .style-submit-button { - opacity: 0; - animation: fade-in 0.25s forwards; - animation-delay: 0.75s; - } - } - } - /* Species/color picker */ species-color-picker { display: contents; @@ -659,6 +434,316 @@ body.wardrobe-v2 { } } +/* =================================================================== + Pose Picker Popover + Floating panel for choosing expression/pose and alt styles. + =================================================================== */ + +.pose-picker-button { + anchor-name: --pose-picker-anchor; + display: flex; + align-items: center; + gap: 0.5rem; + border-color: transparent; + font-size: 85%; + + .pose-emoji { + font-size: 1.1rem; + } + + .pose-label { + font-weight: normal; + min-width: 3.5rem; + } + + .chevron { + font-size: 0.8rem; + opacity: 0.7; + } + + &:focus, + &[popovertargetopen] { + border-color: rgba(255, 255, 255, 0.8); + } +} + +pose-picker-popover { + position: absolute; + position-anchor: --pose-picker-anchor; + margin: 0; + inset: auto; + position-area: top; + background: rgba(0, 0, 0, 0.9); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-radius: 12px; + padding: 1.25rem; + border: 1px solid rgba(255, 255, 255, 0.2); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); + width: 20rem; + + .pose-picker-form { + display: flex; + flex-direction: column; + } + + .pose-picker-table { + border-collapse: separate; + border-spacing: 0.5rem; + + th { + text-align: center; + color: white; + padding: 0.25rem; + font-weight: normal; + } + + td { + padding: 0; + } + } + + .emoji-icon { + font-size: 1.25rem; + display: inline-block; + user-select: none; + } + + .pose-option { + display: block; + cursor: pointer; + position: relative; + width: 60px; + height: 60px; + margin: 0 auto; + + input[type="radio"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; + } + + .pose-thumbnail { + width: 60px; + height: 60px; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); + background: rgba(255, 255, 255, 0.1); + border: 2px solid transparent; + transition: all 0.2s; + display: flex; + align-items: center; + justify-content: center; + } + + .pose-thumbnail-viewer { + width: 60px !important; + height: 60px !important; + transform: scale(0.8); + } + + .pose-unavailable { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + opacity: 0.4; + + .question-mark { + font-size: 2rem; + } + } + + /* Selected state */ + input[type="radio"]:checked + .pose-thumbnail { + border-color: #48BB78; + box-shadow: 0 0 0 3px rgba(72, 187, 120, 0.4); + transform: scale(1.05); + } + + /* Hover state (only for available poses) */ + &.available:hover .pose-thumbnail { + border-color: rgba(255, 255, 255, 0.5); + transform: scale(1.05); + } + + /* Focus state */ + input[type="radio"]:focus + .pose-thumbnail { + border-color: rgba(255, 255, 255, 0.8); + box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.3); + } + + /* Unavailable state */ + &.unavailable { + cursor: not-allowed; + + .pose-thumbnail { + opacity: 0.5; + background: rgba(128, 128, 128, 0.2); + } + } + } + + /* Submit button: progressive enhancement pattern */ + .pose-submit-button { + margin-top: 1rem; + width: 100%; + } + + /* If JS is enabled, hide the submit button initially with a delay */ + @media (scripting: enabled) { + .pose-submit-button { + opacity: 0; + animation: fade-in 0.25s forwards; + animation-delay: 0.75s; + } + } + + /* Once auto-submit is enabled, hide the submit button completely */ + &:state(auto-loading) .pose-submit-button, + &:state(auto-loading) .style-submit-button { + display: none; + } + + /* Tab panel layout */ + .tab-list { + display: flex; + gap: 0.25rem; + margin-top: 1rem; + } + + .tab-button { + flex: 1; + padding: 0.4rem 0.75rem; + font-size: 0.85rem; + border-radius: 999px; + border: 1px solid rgba(255, 255, 255, 0.2); + background: rgba(255, 255, 255, 0.1); + color: rgba(255, 255, 255, 0.6); + cursor: pointer; + transition: all 0.2s; + + &:hover { + background: rgba(255, 255, 255, 0.15); + color: rgba(255, 255, 255, 0.8); + border-color: rgba(255, 255, 255, 0.3); + } + + &.active { + background: rgba(255, 255, 255, 0.2); + color: white; + border-color: rgba(255, 255, 255, 0.4); + } + } + + /* Without JS, hide tab buttons and show both panels stacked */ + tab-panel:not(:defined) .tab-list { + display: none; + } + + tab-panel:not(:defined) .tab-content[hidden] { + display: block !important; + } + + /* Style picker form */ + .style-picker-form { + display: flex; + flex-direction: column; + } + + .style-picker-list { + display: flex; + flex-direction: column; + gap: 0.25rem; + max-height: 200px; + overflow-y: auto; + } + + .style-option { + display: block; + cursor: pointer; + + input[type="radio"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; + } + + .style-option-content { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.375rem 0.5rem; + border-radius: 8px; + border: 2px solid transparent; + transition: all 0.2s; + } + + .style-option-thumbnail { + flex-shrink: 0; + width: 40px; + height: 40px; + border-radius: 6px; + overflow: hidden; + background: rgba(255, 255, 255, 0.1); + + img { + width: 100%; + height: 100%; + object-fit: contain; + display: block; + } + } + + .style-option-name { + color: white; + font-size: 0.9rem; + } + + /* Hover */ + &:hover .style-option-content { + border-color: rgba(255, 255, 255, 0.3); + background: rgba(255, 255, 255, 0.05); + } + + /* Selected state */ + input[type="radio"]:checked + .style-option-content { + border-color: #48BB78; + box-shadow: 0 0 0 2px rgba(72, 187, 120, 0.3); + background: rgba(72, 187, 120, 0.1); + } + + /* Focus state */ + input[type="radio"]:focus + .style-option-content { + border-color: rgba(255, 255, 255, 0.8); + box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.2); + } + } + + /* Style submit button: same progressive enhancement as pose */ + .style-submit-button { + margin-top: 1rem; + width: 100%; + } + + @media (scripting: enabled) { + .style-submit-button { + opacity: 0; + animation: fade-in 0.25s forwards; + animation-delay: 0.75s; + } + } +} + +/* =================================================================== + Outfit Controls + Right/bottom panel: worn items, search, and results. + =================================================================== */ + .outfit-controls-section { grid-area: controls; background: #fff; @@ -710,70 +795,6 @@ body.wardrobe-v2 { padding: 0; margin: 0.5rem 0; } - - .item-card { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.75rem; - background: #f9f9f9; - margin-bottom: 0.5rem; - border-radius: 8px; - color: #333; - transition: background 0.2s, box-shadow 0.2s; - position: relative; - - &:hover { - background: #f0f0f0; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - } - - &:hover .item-remove-button { - opacity: 1; - } - } - - .item-thumbnail { - flex-shrink: 0; - width: 50px; - height: 50px; - border-radius: 6px; - overflow: hidden; - background: white; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - - img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - } - } - - .item-info { - flex: 1; - min-width: 0; - /* Allow text to truncate */ - display: flex; - flex-direction: column; - gap: 0.5rem; - } - - .item-name { - font-weight: 500; - color: #2D3748; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .item-badges { - display: flex; - gap: 0.375rem; - flex-wrap: wrap; - } - - /* .item-remove-button styles are defined in button system above */ } .item-search-form { @@ -801,8 +822,6 @@ body.wardrobe-v2 { box-shadow: 0 0 0 3px rgba(68, 136, 68, 0.1); } } - - /* input[type="submit"] styles are defined in button system above */ } } @@ -811,69 +830,6 @@ body.wardrobe-v2 { list-style: none; padding: 0; margin: 1rem 0; - - .item-card { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.75rem; - background: #f9f9f9; - margin-bottom: 0.5rem; - border-radius: 8px; - color: #333; - transition: background 0.2s, box-shadow 0.2s; - position: relative; - - &:hover { - background: #f0f0f0; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - } - - &:hover :is(.item-add-button, .item-remove-button) { - opacity: 1; - } - } - - .item-thumbnail { - flex-shrink: 0; - width: 50px; - height: 50px; - border-radius: 6px; - overflow: hidden; - background: white; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - - img { - width: 100%; - height: 100%; - object-fit: contain; - display: block; - } - } - - .item-info { - flex: 1; - min-width: 0; - display: flex; - flex-direction: column; - gap: 0.5rem; - } - - .item-name { - font-weight: 500; - color: #2D3748; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .item-badges { - display: flex; - gap: 0.375rem; - flex-wrap: wrap; - } - - /* .item-add-button styles are defined in button system above */ } .empty-state { @@ -887,11 +843,13 @@ body.wardrobe-v2 { display: flex; justify-content: center; gap: 0.5rem; - - /* Pagination link styles are defined in button system above */ } } +/* =================================================================== + Animations + =================================================================== */ + @keyframes fade-in { from { opacity: 0;