style(fitness/exercises): wrap muscle filter in card, widen layout
Align the muscle picker with the site card language (matches /fitness/check-in and /fitness/stats) and unlock the full desktop width via the 1400px container used by nutrition/check-in. - Sidebar card layout at ≥900px (200/620 grid, sticky) - Larger sidebar at ≥1180px (460/720) with figures uncapped - Tablet tier (900–1179px) stacks figures vertically inside the card - Below 900px the card sits on top of the content column
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "homepage",
|
"name": "homepage",
|
||||||
"version": "1.47.2",
|
"version": "1.47.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
* @typedef {{ groups: string[], label: { en: string, de: string } }} MuscleRegion
|
* @typedef {{ groups: string[], label: { en: string, de: string } }} MuscleRegion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @type {{ selectedGroups?: string[], lang?: string, split?: boolean }} */
|
/** @type {{ selectedGroups?: string[], lang?: string }} */
|
||||||
let { selectedGroups = $bindable([]), lang = 'en', split = false } = $props();
|
let { selectedGroups = $bindable([]), lang = 'en' } = $props();
|
||||||
|
|
||||||
const isEn = $derived(lang === 'en');
|
const isEn = $derived(lang === 'en');
|
||||||
|
|
||||||
@@ -78,7 +78,6 @@
|
|||||||
/** Currently hovered region for tooltip */
|
/** Currently hovered region for tooltip */
|
||||||
/** @type {MuscleRegion | null} */
|
/** @type {MuscleRegion | null} */
|
||||||
let hovered = $state(null);
|
let hovered = $state(null);
|
||||||
let hoveredSide = $state('front');
|
|
||||||
|
|
||||||
const hoveredLabel = $derived.by(() => {
|
const hoveredLabel = $derived.by(() => {
|
||||||
if (!hovered) return null;
|
if (!hovered) return null;
|
||||||
@@ -108,9 +107,8 @@
|
|||||||
/**
|
/**
|
||||||
* @param {HTMLDivElement | null} container
|
* @param {HTMLDivElement | null} container
|
||||||
* @param {Record<string, MuscleRegion>} map
|
* @param {Record<string, MuscleRegion>} map
|
||||||
* @param {string} side
|
|
||||||
*/
|
*/
|
||||||
function setupEvents(container, map, side) {
|
function setupEvents(container, map) {
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
container.addEventListener('mouseover', (/** @type {Event} */ e) => {
|
container.addEventListener('mouseover', (/** @type {Event} */ e) => {
|
||||||
@@ -118,7 +116,6 @@
|
|||||||
const g = target?.closest('g[id]');
|
const g = target?.closest('g[id]');
|
||||||
if (g && map[g.id]) {
|
if (g && map[g.id]) {
|
||||||
hovered = map[g.id];
|
hovered = map[g.id];
|
||||||
hoveredSide = side;
|
|
||||||
g.classList.add('highlighted');
|
g.classList.add('highlighted');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -143,66 +140,44 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
setupEvents(frontEl, FRONT_MAP, 'front');
|
setupEvents(frontEl, FRONT_MAP);
|
||||||
setupEvents(backEl, BACK_MAP, 'back');
|
setupEvents(backEl, BACK_MAP);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if split}
|
<div class="muscle-filter">
|
||||||
<div class="muscle-filter-split">
|
<div class="body-figures">
|
||||||
<div class="split-left">
|
<div class="figure">
|
||||||
<div class="figure">
|
<span class="figure-label">{isEn ? 'Front' : 'Vorne'}</span>
|
||||||
<div class="svg-wrap" bind:this={frontEl}>
|
<div class="svg-wrap" bind:this={frontEl}>
|
||||||
{@html frontSvg}
|
{@html frontSvg}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{#if hoveredLabel && hoveredSide === 'front'}
|
|
||||||
<div class="hover-label">{hoveredLabel}</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="split-right">
|
<div class="figure">
|
||||||
<div class="figure">
|
<span class="figure-label">{isEn ? 'Back' : 'Hinten'}</span>
|
||||||
<div class="svg-wrap" bind:this={backEl}>
|
<div class="svg-wrap" bind:this={backEl}>
|
||||||
{@html backSvg}
|
{@html backSvg}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{#if hoveredLabel && hoveredSide === 'back'}
|
|
||||||
<div class="hover-label">{hoveredLabel}</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
|
||||||
<div class="muscle-filter">
|
|
||||||
<div class="body-figures">
|
|
||||||
<div class="figure">
|
|
||||||
<div class="svg-wrap" bind:this={frontEl}>
|
|
||||||
{@html frontSvg}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="figure">
|
|
||||||
<div class="svg-wrap" bind:this={backEl}>
|
|
||||||
{@html backSvg}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if hoveredLabel}
|
<div class="hover-label" aria-live="polite">
|
||||||
<div class="hover-label">{hoveredLabel}</div>
|
{hoveredLabel ?? (isEn ? 'Tap a muscle to filter' : 'Muskel antippen zum Filtern')}
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.muscle-filter {
|
.muscle-filter {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.35rem;
|
gap: 0.5rem;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.body-figures {
|
.body-figures {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.75rem;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -211,12 +186,47 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 0.3rem;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
max-width: 150px;
|
min-width: 0;
|
||||||
|
max-width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tablet sidebar: narrow column, stack figures vertically */
|
||||||
|
@media (min-width: 900px) and (max-width: 1179px) {
|
||||||
|
.body-figures {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.6rem;
|
||||||
|
}
|
||||||
|
.figure {
|
||||||
|
flex: initial;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 170px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wide sidebar: let figures grow with the card width instead of capping at 180px */
|
||||||
|
@media (min-width: 1180px) {
|
||||||
|
.body-figures {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
.figure {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.figure-label {
|
||||||
|
font-size: 0.6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.12em;
|
||||||
|
color: var(--color-text-tertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.svg-wrap {
|
.svg-wrap {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.svg-wrap :global(svg) {
|
.svg-wrap :global(svg) {
|
||||||
@@ -245,25 +255,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hover-label {
|
.hover-label {
|
||||||
font-size: 0.7rem;
|
min-height: 1.1em;
|
||||||
|
font-size: 0.72rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--color-text-primary);
|
color: var(--color-text-secondary);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Split mode: two independent columns for parent to position */
|
|
||||||
.muscle-filter-split {
|
|
||||||
display: contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
.split-left, .split-right {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.35rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.split-left .figure, .split-right .figure {
|
|
||||||
max-width: none;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -76,6 +76,9 @@
|
|||||||
const isMeasureIndex = $derived(
|
const isMeasureIndex = $derived(
|
||||||
/^\/fitness\/(check-in|erfassung)\/?$/.test($page.url.pathname)
|
/^\/fitness\/(check-in|erfassung)\/?$/.test($page.url.pathname)
|
||||||
);
|
);
|
||||||
|
const isExercisesIndex = $derived(
|
||||||
|
/^\/fitness\/(exercises|uebungen)\/?$/.test($page.url.pathname)
|
||||||
|
);
|
||||||
/** @param {number} secs */
|
/** @param {number} secs */
|
||||||
function formatElapsed(secs) {
|
function formatElapsed(secs) {
|
||||||
const m = Math.floor(secs / 60);
|
const m = Math.floor(secs / 60);
|
||||||
@@ -108,7 +111,7 @@
|
|||||||
<UserHeader {user} />
|
<UserHeader {user} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
<div class="fitness-content" style:--fitness-max-width={isNutritionPage || isMeasureIndex ? '1400px' : null}>
|
<div class="fitness-content" style:--fitness-max-width={isNutritionPage || isMeasureIndex || isExercisesIndex ? '1400px' : null}>
|
||||||
{@render children()}
|
{@render children()}
|
||||||
</div>
|
</div>
|
||||||
</Header>
|
</Header>
|
||||||
|
|||||||
@@ -116,127 +116,124 @@
|
|||||||
<svelte:head><title>{lang === 'en' ? 'Exercises' : 'Übungen'} - Bocken</title></svelte:head>
|
<svelte:head><title>{lang === 'en' ? 'Exercises' : 'Übungen'} - Bocken</title></svelte:head>
|
||||||
|
|
||||||
<div class="exercises-page">
|
<div class="exercises-page">
|
||||||
<!-- Desktop: split front/back absolutely positioned outside content -->
|
|
||||||
<div class="desktop-filter">
|
|
||||||
<MuscleFilter bind:selectedGroups={muscleGroups} {lang} split />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h1 class="sr-only">{t('exercises_title', lang)}</h1>
|
<h1 class="sr-only">{t('exercises_title', lang)}</h1>
|
||||||
|
|
||||||
<!-- Mobile: inline, not split -->
|
<aside class="muscle-card" aria-label={isEn ? 'Filter by muscle' : 'Nach Muskel filtern'}>
|
||||||
<div class="mobile-filter">
|
|
||||||
<MuscleFilter bind:selectedGroups={muscleGroups} {lang} />
|
<MuscleFilter bind:selectedGroups={muscleGroups} {lang} />
|
||||||
</div>
|
</aside>
|
||||||
|
|
||||||
<div class="search-bar">
|
<div class="exercises-content">
|
||||||
<Search size={16} />
|
<div class="search-bar">
|
||||||
<input type="text" placeholder={t('search_exercises', lang)} bind:value={query} />
|
<Search size={16} />
|
||||||
</div>
|
<input type="text" placeholder={t('search_exercises', lang)} bind:value={query} />
|
||||||
|
|
||||||
<div class="type-toggle" role="tablist" aria-label={isEn ? 'Exercise type filter' : 'Filter nach Übungsart'}>
|
|
||||||
<button
|
|
||||||
role="tab"
|
|
||||||
aria-selected={typeFilter === 'all'}
|
|
||||||
class="type-btn"
|
|
||||||
class:active={typeFilter === 'all'}
|
|
||||||
onclick={() => typeFilter = 'all'}
|
|
||||||
>
|
|
||||||
<Layers size={14} strokeWidth={2.2} />
|
|
||||||
<span>{t('type_any', lang)}</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
role="tab"
|
|
||||||
aria-selected={typeFilter === 'non-stretch'}
|
|
||||||
class="type-btn"
|
|
||||||
class:active={typeFilter === 'non-stretch'}
|
|
||||||
onclick={() => typeFilter = 'non-stretch'}
|
|
||||||
>
|
|
||||||
<BicepsFlexed size={14} strokeWidth={2.2} />
|
|
||||||
<span>{t('type_weights', lang)}</span>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
role="tab"
|
|
||||||
aria-selected={typeFilter === 'stretch'}
|
|
||||||
class="type-btn"
|
|
||||||
class:active={typeFilter === 'stretch'}
|
|
||||||
onclick={() => typeFilter = 'stretch'}
|
|
||||||
>
|
|
||||||
<PersonStanding size={14} strokeWidth={2.2} />
|
|
||||||
<span>{t('type_stretches', lang)}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<section class="pill-group">
|
|
||||||
<div class="pill-group-header">
|
|
||||||
<span class="pill-group-label">{isEn ? 'Equipment' : 'Ausrüstung'}</span>
|
|
||||||
{#if equipmentFilters.length > 0}
|
|
||||||
<button class="mini-clear" onclick={() => equipmentFilters = []}>
|
|
||||||
{isEn ? 'clear' : 'löschen'}
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="pill-scroll">
|
|
||||||
{#each filterOptions.equipment as eq (eq)}
|
<div class="type-toggle" role="tablist" aria-label={isEn ? 'Exercise type filter' : 'Filter nach Übungsart'}>
|
||||||
{@const active = equipmentFilters.includes(eq)}
|
<button
|
||||||
{@const Icon = equipmentIcon(eq)}
|
role="tab"
|
||||||
<button
|
aria-selected={typeFilter === 'all'}
|
||||||
class="chip equipment-chip"
|
class="type-btn"
|
||||||
class:active
|
class:active={typeFilter === 'all'}
|
||||||
aria-pressed={active}
|
onclick={() => typeFilter = 'all'}
|
||||||
onclick={() => toggleEquipment(eq)}
|
>
|
||||||
>
|
<Layers size={14} strokeWidth={2.2} />
|
||||||
<Icon size={14} strokeWidth={2.2} />
|
<span>{t('type_any', lang)}</span>
|
||||||
<span>{equipmentLabel(eq)}</span>
|
</button>
|
||||||
</button>
|
<button
|
||||||
|
role="tab"
|
||||||
|
aria-selected={typeFilter === 'non-stretch'}
|
||||||
|
class="type-btn"
|
||||||
|
class:active={typeFilter === 'non-stretch'}
|
||||||
|
onclick={() => typeFilter = 'non-stretch'}
|
||||||
|
>
|
||||||
|
<BicepsFlexed size={14} strokeWidth={2.2} />
|
||||||
|
<span>{t('type_weights', lang)}</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
role="tab"
|
||||||
|
aria-selected={typeFilter === 'stretch'}
|
||||||
|
class="type-btn"
|
||||||
|
class:active={typeFilter === 'stretch'}
|
||||||
|
onclick={() => typeFilter = 'stretch'}
|
||||||
|
>
|
||||||
|
<PersonStanding size={14} strokeWidth={2.2} />
|
||||||
|
<span>{t('type_stretches', lang)}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section class="pill-group">
|
||||||
|
<div class="pill-group-header">
|
||||||
|
<span class="pill-group-label">{isEn ? 'Equipment' : 'Ausrüstung'}</span>
|
||||||
|
{#if equipmentFilters.length > 0}
|
||||||
|
<button class="mini-clear" onclick={() => equipmentFilters = []}>
|
||||||
|
{isEn ? 'clear' : 'löschen'}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="pill-scroll">
|
||||||
|
{#each filterOptions.equipment as eq (eq)}
|
||||||
|
{@const active = equipmentFilters.includes(eq)}
|
||||||
|
{@const Icon = equipmentIcon(eq)}
|
||||||
|
<button
|
||||||
|
class="chip equipment-chip"
|
||||||
|
class:active
|
||||||
|
aria-pressed={active}
|
||||||
|
onclick={() => toggleEquipment(eq)}
|
||||||
|
>
|
||||||
|
<Icon size={14} strokeWidth={2.2} />
|
||||||
|
<span>{equipmentLabel(eq)}</span>
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="pill-group">
|
||||||
|
<div class="pill-group-header">
|
||||||
|
<span class="pill-group-label">{isEn ? 'Muscle Group' : 'Muskelgruppe'}</span>
|
||||||
|
{#if muscleGroups.length > 0}
|
||||||
|
<button class="mini-clear" onclick={() => muscleGroups = []}>
|
||||||
|
{isEn ? 'clear' : 'löschen'}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="pill-scroll no-left-fade">
|
||||||
|
{#each orderedMuscleOptions as group (group)}
|
||||||
|
{@const active = muscleGroups.includes(group)}
|
||||||
|
<button
|
||||||
|
class="chip muscle-chip"
|
||||||
|
class:active
|
||||||
|
aria-pressed={active}
|
||||||
|
onclick={() => toggleMuscle(group)}
|
||||||
|
>{muscleLabel(group)}</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<ul class="exercise-list">
|
||||||
|
{#each filtered as exercise (exercise.id)}
|
||||||
|
<li>
|
||||||
|
<a href="/fitness/{sl.exercises}/{exercise.id}" class="exercise-row">
|
||||||
|
<div class="exercise-info">
|
||||||
|
<span class="exercise-name">
|
||||||
|
{exercise.localName}
|
||||||
|
{#if isStretchType(exercise.exerciseType)}
|
||||||
|
<span class="stretch-badge">{t('stretch_pill', lang)}</span>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
<span class="exercise-meta">{exercise.localBodyPart} · {exercise.localEquipment}</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
{#if filtered.length === 0}
|
||||||
</section>
|
<li class="no-results">{t('no_exercises_match', lang)}</li>
|
||||||
|
|
||||||
<section class="pill-group">
|
|
||||||
<div class="pill-group-header">
|
|
||||||
<span class="pill-group-label">{isEn ? 'Muscle Group' : 'Muskelgruppe'}</span>
|
|
||||||
{#if muscleGroups.length > 0}
|
|
||||||
<button class="mini-clear" onclick={() => muscleGroups = []}>
|
|
||||||
{isEn ? 'clear' : 'löschen'}
|
|
||||||
</button>
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</ul>
|
||||||
<div class="pill-scroll no-left-fade">
|
</div>
|
||||||
{#each orderedMuscleOptions as group (group)}
|
|
||||||
{@const active = muscleGroups.includes(group)}
|
|
||||||
<button
|
|
||||||
class="chip muscle-chip"
|
|
||||||
class:active
|
|
||||||
aria-pressed={active}
|
|
||||||
onclick={() => toggleMuscle(group)}
|
|
||||||
>{muscleLabel(group)}</button>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<ul class="exercise-list">
|
|
||||||
{#each filtered as exercise (exercise.id)}
|
|
||||||
<li>
|
|
||||||
<a href="/fitness/{sl.exercises}/{exercise.id}" class="exercise-row">
|
|
||||||
<div class="exercise-info">
|
|
||||||
<span class="exercise-name">
|
|
||||||
{exercise.localName}
|
|
||||||
{#if isStretchType(exercise.exerciseType)}
|
|
||||||
<span class="stretch-badge">{t('stretch_pill', lang)}</span>
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
<span class="exercise-meta">{exercise.localBodyPart} · {exercise.localEquipment}</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{/each}
|
|
||||||
{#if filtered.length === 0}
|
|
||||||
<li class="no-results">{t('no_exercises_match', lang)}</li>
|
|
||||||
{/if}
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* Default (mobile + tablet): single column, card on top */
|
||||||
.exercises-page {
|
.exercises-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -245,34 +242,49 @@
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
/* Mobile: show inline filter, hide desktop split */
|
|
||||||
.desktop-filter {
|
.exercises-content {
|
||||||
display: none;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Desktop: front/back absolutely positioned outside content flow */
|
.muscle-card {
|
||||||
@media (min-width: 1024px) {
|
background: var(--color-surface);
|
||||||
.mobile-filter {
|
border: 1px solid var(--color-border);
|
||||||
display: none;
|
border-radius: var(--radius-card);
|
||||||
|
padding: 0.85rem 1rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tablet + wide: two-column sidebar layout (card fixed on the left) */
|
||||||
|
@media (min-width: 900px) {
|
||||||
|
.exercises-page {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 200px minmax(0, 620px);
|
||||||
|
gap: 1.5rem;
|
||||||
|
max-width: calc(200px + 1.5rem + 620px);
|
||||||
|
width: 100%;
|
||||||
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.desktop-filter {
|
.muscle-card {
|
||||||
display: contents;
|
position: sticky;
|
||||||
}
|
|
||||||
|
|
||||||
.exercises-page :global(.split-left),
|
|
||||||
.exercises-page :global(.split-right) {
|
|
||||||
position: fixed;
|
|
||||||
top: calc(8.5rem + env(safe-area-inset-top, 0px));
|
top: calc(8.5rem + env(safe-area-inset-top, 0px));
|
||||||
width: clamp(140px, 14vw, 200px);
|
padding: 1rem 0.9rem 0.85rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wide: larger sidebar so the figure pair gets meaningful size */
|
||||||
|
@media (min-width: 1180px) {
|
||||||
|
.exercises-page {
|
||||||
|
grid-template-columns: 460px minmax(0, 720px);
|
||||||
|
gap: 2rem;
|
||||||
|
max-width: calc(460px + 2rem + 720px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.exercises-page :global(.split-left) {
|
.muscle-card {
|
||||||
right: calc(50% + 310px + 1.5rem);
|
padding: 1.1rem 1.2rem 0.95rem;
|
||||||
}
|
|
||||||
|
|
||||||
.exercises-page :global(.split-right) {
|
|
||||||
left: calc(50% + 310px + 1.5rem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +467,7 @@
|
|||||||
.exercise-row:hover {
|
.exercise-row:hover {
|
||||||
background: var(--color-surface-hover);
|
background: var(--color-surface-hover);
|
||||||
}
|
}
|
||||||
.exercise-info {
|
.exercise-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user