So yeah, doing the backend was easier than I thought it would be. I had to reorder some of the stuff in the initialization sequence; because blocks can't be chosen until themes are chosen, and themes can depend on a lot of factors including vars, user prefs, and so on, I had to move blocks to fairly late in the initialization process.
The logic for choosing themes and layering orders is completely, totally configurable. Between the vars and the box, you can change the entire behaviour. The only thing hardcoded into the codebase is the ability to layer themes, all it asks is a comma-separated list of themes. If you have themes turned off, it gets a "list" of a single item, the default theme.
I actually had to split the initialization process in two, and have scoop parse the path before themes are decided, because I needed to have either the section or the sid (so I could get the section) of the page being requested for per-section themes. Doing that required that I move everything in the block category block_programs to vars, because the block_programs (like, oh, op_template) are required for parsing the path, or getting user permissions (which are also set before themes). So I had to make small changes to lots of modules, changing $S->{UI}->{BLOCKS}->{block_program_name} to $S->{UI}->{VARS}->{block_program_name}.
The admin interface for setting themes is pretty simple, and allows you as much flexibility as you care to put in.
Basically, there's a var called "order" in which you specify what order themes should be loaded in. Later themes overwrite earlier ones if there are any duplicates. Currently, there are 5 options for "order": section, group (user group), agent (browser user_agent; the detection script still needs to be written - I have to brush up on regexes), siteid (by request from theantix), and pref (user preference). You can put any, all, or none of these in, in any order. If all you want is section-based themes, just put the word "section" in, and so on.
If you're in the section "news", and "section" is listed in the "order" var somewhere, scoop looks for the var "section_news", and adds the theme name contained in the var (if it exists) to the list of themes to be applied. It works similarly for all the other options: "group_Anonymous" would set the theme for anybody in the anonymous group, and so on.
Finally, the code that does all this deciding is a box called theme_chooser, which outputs a simple comma-separated list of themes for the backend to chew on. If you want to add any more criteria (say if you wanted to theme by op, or by topic, or whatever) this is where you add the code to handle it. However, you have to be even more careful than usual in changing this box; putting it on a page by itself to test just isn't an option, because it's called in the initialization process, and if you bork it you'll get ISE's no matter what. Fortunately the recovery procedure is simple, assuming you can get at the database directly, and can stop/start your server to force it to flush the cache. Or you could make a separate box to test your code logic in, then integrate it; you just have to watch out that you don't try to call stuff that hasn't been loaded yet when the real box is called... I tried to put theme and block loading as late as I could, but there's still a lot that hasn't happened yet. Like, oh, most of the program. :-)
Anyhow, all of the above works, except that the box "theme_chooser" is still fairly simple and needs work. I've been admiring my section-based themes on my test site :-)
What still needs work is the block admin interface. It's annoying me right now; you appear to be able to edit different themes, and the block admin tool only lists those blocks that are in the selected theme, but the value it displays is the value for the theme that's currently applied, whatever is in the database. I'm not sure if it's an issue with my code or with the cache, or something else entirely...