}
 
 sub add_stylesheet {
-  $::form->use_stylesheet('lx-office-erp/background_jobs.css');
+  $::request->{layout}->use_stylesheet('lx-office-erp/background_jobs.css');
 }
 
 1;
 
   Menu->new('menu.ini');
 }
 
+##########################################
+#  inheritable/overridable
+##########################################
+
 sub pre_content {
 }
 
 sub post_content {
 }
 
+sub stylesheets_inline {
+}
+
+sub javascript_inline {
+}
+
+#########################################
+# Interface
+########################################
+
+sub use_stylesheet {
+  my $self = shift;
+  push @{ $self->{stylesheets} ||= [] }, @_ if @_;
+  @{ $self->{stylesheets} ||= [] };
+}
+
 sub stylesheets {
+  my ($self) = @_;
+  my $css_path = $self->get_stylesheet_for_user;
+
+  return grep { $_ } map { $self->_find_stylesheet($_, $css_path)  } $self->use_stylesheet;
 }
 
-sub stylesheets_inline {
+sub _find_stylesheet {
+  my ($self, $stylesheet, $css_path) = @_;
+
+  return "$css_path/$stylesheet" if -f "$css_path/$stylesheet";
+  return "css/$stylesheet"       if -f "css/$stylesheet";
+  return $stylesheet             if -f $stylesheet;
 }
 
-sub javascript_inline {
+sub get_stylesheet_for_user {
+  my $css_path = 'css';
+  if (my $user_style = $::myconfig{stylesheet}) {
+    $user_style =~ s/\.css$//; # nuke trailing .css, this is a remnand of pre 2.7.0 stylesheet handling
+    if (-d "$css_path/$user_style" &&
+        -f "$css_path/$user_style/main.css") {
+      $css_path = "$css_path/$user_style";
+    } else {
+      $css_path = "$css_path/lx-office-erp";
+    }
+  } else {
+    $css_path = "$css_path/lx-office-erp";
+  }
+  $::myconfig{css_path} = $css_path; # needed for menunew, FIXME: don't do this here
+
+  return $css_path;
+}
+
+
+sub use_javascript {
+  my $self = shift;
+  $::lxdebug->dump(0,  "class", \@_);
+  push @{ $self->{javascripts} ||= [] }, @_ if @_;
+  @{ $self->{javascripts} ||= [] };
+}
+
+sub javascripts {
+  my ($self) = @_;
+
+  $::lxdebug->dump(0,  "called", [ map { $self->find_javascript($_)  } $self->use_javascript ]);
+  return map { $self->_find_javascript($_)  } $self->use_javascript;
+}
+
+sub _find_javascript {
+  my ($self, $javascript) = @_;
+
+  return "js/$javascript"        if -f "js/$javascript";
+  return $javascript             if -f $javascript;
 }
 
 1;
 
   $self->{top}  = SL::Controller::Layout::Top->new;
   $self->{left} = SL::Controller::Layout::MenuLeft->new;
 
+  $self->use_stylesheet(
+    $self->{top}->stylesheets,
+    $self->{left}->stylesheets,
+  );
+
+  $self->use_javascript(
+    $self->{top}->javascripts,
+    $self->{left}->javascripts,
+  );
+
   $self;
 }
 
   "</div>\n";
 }
 
-sub stylesheets {
-  $_[0]{top}->stylesheets,
-  $_[0]{left}->stylesheets;
-}
-
-sub javascripts {
-  $_[0]{top}->javascripts,
-  $_[0]{left}->javascripts;
-}
-
 1;
 
 
 use List::MoreUtils qw(apply);
 
-sub stylesheets {
-  qw(css/icons16.css css/icons24.css);
+sub new {
+  my ($class, @slurp) = @_;
+
+  my $self = $class->SUPER::new(@slurp);
+
+  $self->use_stylesheet(qw(css/icons16.css css/icons24.css));
+
+  $self;
 }
 
 sub render {
 
   return ($module, $submodule);
 }
 
-my @dont_save = qw(login password stylesheet action);
+my @dont_save = qw(login password action);
 
 sub save {
   $main::lxdebug->enter_sub();
 
   return $output;
 }
 
-sub use_stylesheet {
-  my $self = shift;
-
-  $self->{stylesheet} = [ $self->{stylesheet} ] unless ref $self->{stylesheet} eq 'ARRAY';
-
-  if (@_) {
-    $self->{stylesheet} =
-      [ grep { -f                       }
-        map  { m:^css/: ? $_ : "css/$_" }
-        grep { $_                       }
-             (@{ $self->{stylesheet} }, @_)
-      ];
-  }
-
-  return @{ $self->{stylesheet} };
-}
-
-sub get_stylesheet_for_user {
-  my $css_path = 'css';
-  if (my $user_style = $::myconfig{stylesheet}) {
-    $user_style =~ s/\.css$//; # nuke trailing .css, this is a remnand of pre 2.7.0 stylesheet handling
-    if (-d "$css_path/$user_style" &&
-        -f "$css_path/$user_style/main.css") {
-      $css_path = "$css_path/$user_style";
-    } else {
-      $css_path = "$css_path/lx-office-erp";
-    }
-  } else {
-    $css_path = "$css_path/lx-office-erp";
-  }
-  $::myconfig{css_path} = $css_path; # needed for menunew, FIXME: don't do this here
-
-  return $css_path;
-}
-
 sub header {
   $::lxdebug->enter_sub;
 
-  # extra code is currently only used by menuv3 and menuv4 to set their css.
-  # it is strongly deprecated, and will be changed in a future version.
   my ($self, %params) = @_;
   my $db_charset = $::lx_office_conf{system}->{dbcharset} || Common::DEFAULT_CHARSET;
   my @header;
 
+  my $layout = $::request->{layout};
+
   $::lxdebug->leave_sub and return if !$ENV{HTTP_USER_AGENT} || $self->{header}++;
 
-  my $css_path = $self->get_stylesheet_for_user;
+  # standard css for all
+  $layout->use_stylesheet("$_.css") for qw(
+    main menu tabcontent list_accounts jquery.autocomplete
+    jquery.multiselect2side frame_header/header
+    ui-lightness/jquery-ui-1.8.12.custom
+    js/jscalendar/calendar-win2k-1
+  );
+
+  $layout->use_javascript("$_.js") for qw(
+    jquery common jscalendar/calendar jscalendar/lang/calendar-de
+    jscalendar/calendar-setup part_selection jquery-ui jquery.cookie jqModal
+    switchmenuframe
+  );
 
   $self->{favicon} ||= "favicon.ico";
   $self->{titlebar} = join ' - ', grep $_, $self->{title}, $self->{login}, $::myconfig{dbname}, $self->{version} if $self->{title};
     push @header, "<meta http-equiv='refresh' content='$refresh_time;$refresh_url'>";
   }
 
-  push @header, map { qq|<link rel="stylesheet" href="$_" type="text/css" title="Stylesheet">| } $self->use_stylesheet, $::request->{layout}->stylesheets;
-
-  push @header, "<style type='text/css'>\@page { size:landscape; }</style>" if $self->{landscape};
-  push @header, "<link rel='shortcut icon' href='$self->{favicon}' type='image/x-icon'>" if -f $self->{favicon};
-  push @header, map { qq|<script type="text/javascript" src="js/$_.js"></script>| }
-       qw(jquery common jscalendar/calendar jscalendar/lang/calendar-de jscalendar/calendar-setup part_selection jquery-ui jquery.cookie jqModal switchmenuframe);
+  push @header, map { qq|<link rel="stylesheet" href="$_" type="text/css" title="Stylesheet">| } $layout->stylesheets;
+  push @header, "<style type='text/css'>\@page { size:landscape; }</style> "                     if $self->{landscape};
+  push @header, "<link rel='shortcut icon' href='$self->{favicon}' type='image/x-icon'>"         if -f $self->{favicon};
+  push @header, map { qq|<script type="text/javascript" src="$_"></script>| }                 $layout->javascripts;
   push @header, $self->{javascript} if $self->{javascript};
-  push @header, map { qq|<link rel="stylesheet" type="text/css" href="$css_path/$_.css">| }
-       qw(main menu tabcontent list_accounts jquery.autocomplete jquery.multiselect2side frame_header/header ui-lightness/jquery-ui-1.8.12.custom);
-  push @header, map { qq|<link rel="stylesheet" type="text/css" href="js/jscalendar/calendar-win2k-1.css">| }
   push @header, map { $_->show_javascript } @{ $self->{AJAX} || [] };
   push @header, "<script type='text/javascript'>function fokus(){ document.$self->{fokus}.focus(); }</script>" if $self->{fokus};
 
     strict       => qq|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">|,
     transitional => qq|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">|,
     frameset     => qq|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">|,
+    html5        => qq|<!DOCTYPE html>|,
   );
 
   # output
    ***********************************************/
 
   </script>
-  $params{extra_code}
  </head>
  <body>
 
 sub footer {
   # TODO: fix abort conditions
 
+  print $::request->{layout}->end_content;
   print $::request->{layout}->post_content;
-  print "<script type='text/javascript' src='$_'></script>\n" for $::request->{layout}->javascripts;
-  if (my @inline_scripts = $::request->{layout}->javascript_inline) {
-    print "<script type='text/javascript'>$_</script>\n" for @inline_scripts;
-  }
+#  print "<script type='text/javascript' src='$_'></script>\n" for $::request->{layout}->javascripts;
+#  if (my @inline_scripts = $::request->{layout}->javascript_inline) {
+#    print "<script type='text/javascript'>$_</script>\n" for @inline_scripts;
+#  }
 
   print <<EOL
  </body>
 
     $dbh->disconnect;
 
     if ($update_available) {
-      $form->{"stylesheet"} = "lx-office-erp.css";
       $form->{"title"} = $main::locale->text("Dataset upgrade");
       $form->header();
       print $form->parse_html_template("dbupgrade/header");
 
   $locale = $::locale;
   $auth   = $::auth;
 
-  $form->{stylesheet} = "lx-office-erp.css";
+  $request->{layout}->use_stylesheet("lx-office-erp.css");
   $form->{favicon}    = "favicon.ico";
 
   if ($form->{action}) {
   my $form            = $main::form;
   my $locale          = $main::locale;
 
-  $form->{stylesheet} = "lx-office-erp.css";
+  $::request->{layout}->use_stylesheet("lx-office-erp.css");
   $form->{title}      = $locale->text("Dataset upgrade");
   $form->header();
 
 
     $ca->{link_edit_account} = $link_edit_account . '&id=' . E($ca->{id});
   }
 
-  $form->use_stylesheet("list_accounts.css");
+  $::request->{layout}->use_stylesheet("list_accounts.css");
   $form->{title}       = $locale->text('Chart of Accounts');
 
   $form->header;
 
     restore_form($form->{SAVED_FORM}, 1) if ($form->{SAVED_FORM});
     delete $form->{SAVED_FORM};
 
-    $form->{SAVED_FORM}   = save_form(qw(stylesheet login password));
+    $form->{SAVED_FORM}   = save_form(qw(login password));
     $form->{remove_draft} = 1;
 
     $form->header();
   $draft_nextsub = "add" unless ($draft_nextsub);
 
   delete $form->{action};
-  my $saved_form = save_form(qw(stylesheet login password));
+  my $saved_form = save_form(qw(login password));
 
   $form->header();
   print($form->parse_html_template("drafts/load",
     $form->{draft_description}     = $description;
     $form->{remove_draft}          = 'checked';
   }
-  # Ich vergesse bei Rechnungsentwürfe das Rechnungsdatum zu ändern. Dadurch entstehen 
+  # Ich vergesse bei Rechnungsentwürfe das Rechnungsdatum zu ändern. Dadurch entstehen
   # ungültige Belege. Vielleicht geht es anderen ähnlich jan 19.2.2011
   $form->{invdate} = $form->current_date(\%myconfig); # Aktuelles Rechnungsdatum  ...
   $form->{duedate} = $form->current_date(\%myconfig); # Aktuelles Fälligkeitsdatum  ...
 
     $form->error($locale->text("Invoice has already been storno'd!"));
   }
 
-  map({ my $key = $_; delete($form->{$key}) unless (grep({ $key eq $_ } qw(id login password stylesheet type))); } keys(%{ $form }));
+  map({ my $key = $_; delete($form->{$key}) unless (grep({ $key eq $_ } qw(id login password type))); } keys(%{ $form }));
 
   invoice_links();
   prepare_invoice();
 
 
   $form->{simple_save} = 1;
   if(!$form->{print_and_save}) {
-    delete @{$form}{ary_diff([keys %{ $form }], [qw(login stylesheet id script type cursor_fokus)])};
+    delete @{$form}{ary_diff([keys %{ $form }], [qw(login id script type cursor_fokus)])};
     edit();
     ::end_of_request();
   }