I just finished implementing some cool features for customizing CiviCRM look and feel in v1.7. As most of you'll are aware CiviCRM follows a pretty good modular MVC (model-view-controller) architecture. We seperate the view (Smarty templates) from the code and business logic quite stringently and most of the display can be customized at the template level.
In 1.6 and prior, you had to hack the CiviCRM templates to make your changes. This is not very good from an upgrade perspective, since you need to reapply your changes on every upgrade. In v1.7 we've introduced a new path in the settings file. The user can store their customized templates there and it overrides the default CiviCRM templates. You dont need to override all the template files. You just change the files you want to, and the system uses the default files for the rest.
Most people want to change the profiles look and feel. Unfortunately all profiles also share the same template files. So if you change the template file for one profile, you change it for all of them (unless you put in conditional logic in the template). To fix this issue, we've implemented a per profile template hierarchy. So for each profile, the system checks if a template is present for that specific profile. If so, it uses that template, else it uses the generic template. This allows the end user to customize profiles at a very granular level and hence gives the end user more power and flexibility. You can read the sparse details on our Issue Tracker
and can see the relevant changeset on FishEye