diff --git a/cpn.install b/cpn.install
index 2ded691..ad24fc3 100644
--- a/cpn.install
+++ b/cpn.install
@@ -73,6 +73,14 @@ function cpn_uninstall() {
   variable_del('cpn_aggregation_js');
   variable_del('cpn_path');
   variable_del('cpn_syntax_highlighting');
+
+  // Delete the content type variables.
+  foreach (array_keys(node_get_types('names')) as $node_type) {
+    foreach (array('css', 'js') as $type) {
+      variable_del('cpn_' . $type . '_enabled_' . $node_type);
+      variable_del('cpn_' . $type . '_' . $node_type);
+    }
+  }
 }
 
 /**
@@ -137,3 +145,19 @@ function cpn_update_6100() {
 
   return $ret;
 }
+
+/**
+ * Update variables to new format.
+ */
+function cpn_update_6101() {
+  $ret = array();
+  foreach (array_keys(node_get_types('names')) as $node_type) {
+    foreach (array('css', 'js') as $type) {
+      if (variable_get('cpn_' . $type . '_' . $node_type, FALSE)) {
+        variable_set('cpn_' . $type . '_enabled_' . $node_type, TRUE);
+        variable_del('cpn_' . $type . '_' . $node_type);
+      }
+    }
+  }
+  return $ret;
+}
diff --git a/cpn.module b/cpn.module
index 387d504..94a8be1 100644
--- a/cpn.module
+++ b/cpn.module
@@ -77,19 +77,34 @@ function cpn_form_alter(&$form, $form_state, $form_id) {
       '#collapsed' => TRUE,
     );
     $form['cpn']['cpn_css'] = array(
+      '#type' => 'textarea',
+      '#title' => t('CSS'),
+      '#default_value' => variable_get('cpn_css_' . $form['#node_type']->type, ''),
+      '#description' => t('Custom CSS rules for this content type. Do not include @style tags.', array('@style' => '<style>')),
+    );
+    $form['cpn']['cpn_js'] = array(
+      '#type' => 'textarea',
+      '#title' => t('JavaScript'),
+      '#default_value' => variable_get('cpn_js_' . $form['#node_type']->type, ''),
+      '#description' => t('Custom JavaScript for this content type. Do not include @script tags.', array('@script' => '<script>')),
+    );
+    $form['cpn']['cpn_css_enabled'] = array(
       '#type' => 'checkbox',
-      '#title' => t('Enable custom CSS.'),
+      '#title' => t('Enable custom CSS per node.'),
       '#return_value' => 1,
-      '#default_value' => variable_get('cpn_css_'. $form['#node_type']->type, FALSE),
+      '#default_value' => variable_get('cpn_css_enabled_' . $form['#node_type']->type, FALSE),
       '#description' => t('Users with the <em>edit node css</em> permission will be able to edit custom CSS rules per node.'),
     );
-    $form['cpn']['cpn_js'] = array(
+    $form['cpn']['cpn_js_enabled'] = array(
       '#type' => 'checkbox',
-      '#title' => t('Enable custom JavaScript.'),
+      '#title' => t('Enable custom JavaScript per node.'),
       '#return_value' => 1,
-      '#default_value' => variable_get('cpn_js_'. $form['#node_type']->type, FALSE),
+      '#default_value' => variable_get('cpn_js_enabled_' . $form['#node_type']->type, FALSE),
       '#description' => t('Users with the <em>edit node javascript</em> permission will be able to edit custom JavaScript per node.'),
     );
+    $form['#validate'][] = 'cpn_node_type_validate';
+    $form['#submit'][] = 'cpn_node_type_submit';
+    $form['#after_build'][] = 'cpn_after_build';
   }
 
   // Block form (editing any block, or creating a Block module block).
@@ -137,7 +152,6 @@ function cpn_form_alter(&$form, $form_state, $form_id) {
       $form['#submit'][] = 'cpn_block_submit';
     }
   }
-
 }
 
 /**
@@ -162,6 +176,32 @@ function cpn_after_build($form_element, &$form_state) {
 }
 
 /**
+ * Node type validation callback.
+ * 
+ * Ensures no "style" or "script" tags are included.
+ */
+function cpn_node_type_validate($form, &$form_state) {
+  if (cpn_validate($form_state['values']['cpn_css'], 'css')) {
+    form_set_error('cpn_css', t('Do not include @style tags in the CSS.', array('@style' => '<style>')));
+  }
+  if (cpn_validate($form_state['values']['cpn_js'], 'js')) {
+    form_set_error('cpn_js', t('Do not include @script tags in the JavaScript.', array('@script' => '<script>')));
+  }
+}
+
+/**
+ * Node type submit callback.
+ */
+function cpn_node_type_submit($form, &$form_state) {
+  // Delete existing files, then save them.
+  foreach (array('css', 'js') as $type) {
+    // Remove the existing file.
+    file_delete(file_create_path($form_state['values']['type'] . '.' . $type));
+    cpn_save_file($form_state['values']['cpn_' . $type], $form_state['values']['type'] . '.' . $type);
+  }
+}
+
+/**
  * Implementation of hook_nodeapi().
  */
 function cpn_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
@@ -210,6 +250,22 @@ function cpn_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
 
     // Viewing & Previewing.
     case 'view':
+      // Attach the content type CSS/JS.
+      $css = variable_get('cpn_css_' . $node->type, '');
+      if (!empty($css)) {
+        $css = file_create_path(variable_get('cpn_path', 'cpn') . '/'. $node->type .'.css');
+        if (is_file($css)) {
+          drupal_add_css($css, 'theme', NULL, variable_get('cpn_aggregation_css', TRUE));
+        }
+      }
+      $js = variable_get('cpn_js_' . $node->type, '');
+      if (!empty($js)) {
+        $js = file_create_path(variable_get('cpn_path', 'cpn') . '/'. $node->type .'.js');
+        if (is_file($js)) {
+          drupal_add_js($js, 'theme', FALSE, TRUE, variable_get('cpn_aggregation_js', TRUE));
+        }
+      }
+
       // Previewing: add CSS and/or JS to the page, inline.
       if ($previous_op == 'validate') {
         if (drupal_strlen(trim($node->cpn['css']))) {
@@ -312,7 +368,7 @@ function cpn_save_file($data, $filename) {
   if (!drupal_strlen(trim($data))) {
     return FALSE;
   }
-  $path = file_create_path('cpn');
+  $path = file_create_path(variable_get('cpn_path', 'cpn'));
   file_check_directory($path, FILE_CREATE_DIRECTORY) or mkdir($path, 0755, TRUE);
   return file_save_data($data, $path .'/'. $filename, FILE_EXISTS_REPLACE);
 }
