--- loncom/interface/loncommon.pm	2025/01/25 17:51:52	1.1446
+++ loncom/interface/loncommon.pm	2025/03/18 18:57:28	1.1471
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.1446 2025/01/25 17:51:52 raeburn Exp $
+# $Id: loncommon.pm,v 1.1471 2025/03/18 18:57:28 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -966,7 +966,9 @@ ENDSCRT
 
 sub select_timezone {
    my ($name,$selected,$onchange,$includeempty,$id,$disabled)=@_;
-   my $output='<select name="'.$name.'" '.$id.$onchange.$disabled.'>'."\n";
+   my $labeltext = &HTML::Entities::encode(&mt('Select Time Zone'));
+   my $output='<select name="'.$name.'" '.$id.$onchange.$disabled.
+              ' aria-label="'.$labeltext.'">'."\n";
    if ($includeempty) {
        $output .= '<option value=""';
        if (($selected eq '') || ($selected eq 'local')) {
@@ -1174,7 +1176,8 @@ sub linked_select_forms {
         $menuorder,
         $onchangefirst,
         $onchangesecond,
-        $suffix
+        $suffix,
+        $haslabel
         ) = @_;
     my $second = "document.$formname.$secondselectname";
     my $first = "document.$formname.$firstselectname";
@@ -1240,13 +1243,18 @@ END
         $result.=">".&mt($hashref->{$value}->{'text'})."</option>\n";
     }
     $result .= "</select>\n";
+    if ($haslabel) {
+        $result .= '</label>';
+    }
     my %select2;
     if (ref($hashref->{$firstdefault}) eq 'HASH') {
         if (ref($hashref->{$firstdefault}->{'select2'}) eq 'HASH') {
             %select2 = %{$hashref->{$firstdefault}->{'select2'}};
         }
     }
-    $result .= $middletext;
+    if ($middletext ne '') {
+        $result .= '<label>'.$middletext;
+    }
     $result .= "<select size=\"1\" name=\"$secondselectname\"";
     if ($onchangesecond) {
         $result .= ' onchange="'.$onchangesecond.'"';
@@ -1264,6 +1272,9 @@ END
         $result.=">".&mt($select2{$value})."</option>\n";
     }
     $result .= "</select>\n";
+    if ($middletext ne '') {
+        $result .= '</label>';
+    }
     #    return $debug;
     return $result;
 }   #  end of sub linked_select_forms {
@@ -1342,7 +1353,7 @@ sub help_open_topic {
     }
     $template.=' <a'.$target.' href="'.$link.'" title="'.$title.'">'
               .'<img src="'.$helpicon.'" border="0"'
-              .' alt="'.&mt('Help: [_1]',$topic).'"'
+              .' alt="'.&mt('Help icon').'"'
               .' title="'.$title.'" style="vertical-align:middle;"'.$imgid 
               .' /></a>';
     if ($text ne "") {	
@@ -1451,7 +1462,7 @@ $banner_link
 <a href="$link" title="$title" $linkattr>$text</a>
 END
     } else {
-        return '&nbsp;'.$text.'&nbsp;';
+        return '&nbsp;<h1 class="LC_helpmenu">'.$text.'</h1>&nbsp;';
     }
 }
 
@@ -1463,6 +1474,10 @@ sub help_menu_js {
     my $helptopic=&general_help();
     my $details_link = $httphost.'/adm/help/'.$helptopic.'.hlp';
     my $nothing=&Apache::lonhtmlcommon::javascript_nothing();
+    my $bannertitle = &mt('Help Menu');
+    &js_escape(\$bannertitle);
+    my $bodytitle = &mt('Documentation');
+    &js_escape(\$bodytitle);
     my $start_page =
         &Apache::loncommon::start_page('Help Menu', undef,
 				       {'frameset'    => 1,
@@ -1474,7 +1489,6 @@ sub help_menu_js {
     my $end_page =
         &Apache::loncommon::end_page({'frameset' => 1,
 				      'js_ready' => 1,});
-
     my $template .= <<"ENDTEMPLATE";
 <script type="text/javascript">
 // <![CDATA[
@@ -1499,8 +1513,8 @@ function helpMenu(target) {
     return;
 }
 function writeHelp(caller) {
-    caller.document.writeln('$start_page\\n<frame name="bannerframe" src="'+banner_link+'" marginwidth="0" marginheight="0" frameborder="0">\\n');
-    caller.document.writeln('<frame name="bodyframe" src="$details_link" marginwidth="0" marginheight="0" frameborder="0">\\n$end_page');
+    caller.document.writeln('$start_page\\n<frame name="bannerframe" title="$bannertitle" src="'+banner_link+'" marginwidth="0" marginheight="0" frameborder="0">\\n');
+    caller.document.writeln('<frame name="bodyframe" title="$bodytitle" src="$details_link" marginwidth="0" marginheight="0" frameborder="0">\\n$end_page');
     caller.document.close();
     caller.focus();
 }
@@ -2300,7 +2314,7 @@ sub import_crsauthor_form {
         dire => 'Directory',
         se   => 'Select',
     );
-    $output = $lt{'dire'}.':&nbsp;'.
+    $output = '<label>'.$lt{'dire'}.':&nbsp;'.
               '<select id="'.$firstselectname.'" name="'.$firstselectname.'" '.
               'onchange="populateCrsSelects(this.form,'."'$firstselectname','$secondselectname',1,'$js_only',0,1,0,0,0".');">'.
               '<option value="" selected="selected">'.$lt{'se'}.'</option>';
@@ -2311,10 +2325,10 @@ sub import_crsauthor_form {
         next if ($key eq '/');
         $output .= '<option value="'.$key.'">'.$key.'</option>'."\n";
     }
-    $output .= '</select><br />'."\n".
+    $output .= '</select></label><br /><label>'."\n".
                $lt{'fnam'}.':&nbsp;<select id="'.$secondselectname.'" name="'.$secondselectname.'">'."\n".
                '<option value="" selected="selected"></option>'."\n".
-               '</select>'."\n".
+               '</select></label>'."\n".
                '<input type="hidden" id="crsres_include_'.$suffix.'" value="'.$only.'" />';
     return ($numdirs,$output);
 }
@@ -2786,7 +2800,7 @@ sub create_text_file {
 # ------------------------------------------
 
 sub domain_select {
-    my ($name,$value,$multiple,$incdoms,$excdoms)=@_;
+    my ($name,$value,$multiple,$incdoms,$excdoms,$id)=@_;
     my @possdoms;
     if (ref($incdoms) eq 'ARRAY') {
         @possdoms = @{$incdoms};
@@ -2807,10 +2821,10 @@ sub domain_select {
     if ($multiple) {
 	$domains{''}=&mt('Any domain');
 	$domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))];
-	return &multiple_select_form($name,$value,4,\%domains);
+	return &multiple_select_form($name,$value,4,\%domains,undef,$id);
     } else {
 	$domains{'select_form_order'} = [sort {lc($a) cmp lc($b) } (keys(%domains))];
-	return &select_form($name,$value,\%domains);
+	return &select_form($name,$value,\%domains,'','',$id);
     }
 }
 
@@ -2822,7 +2836,7 @@ sub domain_select {
 
 =over 4
 
-=item * &multiple_select_form($name,$value,$size,$hash,$order)
+=item * &multiple_select_form($name,$value,$size,$hash,$order,$id)
 
 Returns a string containing a <select> element int multiple mode
 
@@ -2834,12 +2848,13 @@ Args:
   $hash - the elements should be 'option' => 'shown text'
           (shown text should already have been &mt())
   $order - (optional) array ref of the order to show the elements in
+  $id = (optional) id for <select> element 
 
 =cut
 
 #-------------------------------------------
 sub multiple_select_form {
-    my ($name,$value,$size,$hash,$order)=@_;
+    my ($name,$value,$size,$hash,$order,$id)=@_;
     my %selected = map { $_ => 1 } ref($value)?@{$value}:($value);
     my $output='';
     if (! defined($size)) {
@@ -2848,7 +2863,10 @@ sub multiple_select_form {
             $size = scalar(keys(%$hash));
         }
     }
-    $output.="\n".'<select name="'.$name.'" size="'.$size.'" multiple="multiple">';
+    if ($id ne '') {
+        $id = ' id="'.$id.'"'; 
+    }
+    $output.="\n".'<select name="'.$name.'" size="'.$size.'" multiple="multiple"'.$id.'>';
     my @order;
     if (ref($order) eq 'ARRAY')  {
         @order = @{$order};
@@ -2872,7 +2890,7 @@ sub multiple_select_form {
 
 =pod
 
-=item * &select_form($defdom,$name,$hashref,$onchange,$readonly)
+=item * &select_form($defdom,$name,$hashref,$onchange,$readonly,$id)
 
 Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select options from a ref to a hash containing:
@@ -2880,7 +2898,8 @@ option_name => displayed text. An option
 a javascript onchange item, e.g., onchange="this.form.submit();".
 An optional arg -- $readonly -- if true will cause the select form
 to be disabled, e.g., for the case where an instructor has a section-
-specific role, and is viewing/modifying parameters. 
+specific role, and is viewing/modifying parameters. An optional arg
+-- $id -- will be used as the id attribute of the select element. 
 
 See lonrights.pm for an example invocation and use.
 
@@ -2888,7 +2907,7 @@ See lonrights.pm for an example invocati
 
 #-------------------------------------------
 sub select_form {
-    my ($def,$name,$hashref,$onchange,$readonly) = @_;
+    my ($def,$name,$hashref,$onchange,$readonly,$id) = @_;
     return unless (ref($hashref) eq 'HASH');
     if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';
@@ -2897,7 +2916,10 @@ sub select_form {
     if ($readonly) {
         $disabled = ' disabled="disabled"';
     }
-    my $selectform = "<select name=\"$name\" size=\"1\"$onchange$disabled>\n";
+    if ($id ne '') {
+        $id = ' id="'.$id.'"';
+    }
+    my $selectform = "<select name=\"$name\" size=\"1\"$onchange$disabled$id>\n";
     my @keys;
     if (exists($hashref->{'select_form_order'})) {
 	@keys=@{$hashref->{'select_form_order'}};
@@ -2948,7 +2970,7 @@ sub display_filter {
     my $onchange = "javascript:toggleHistoryOptions(this,'containingphrase','$context',
                                                     '$secondid','$thirdid')";
     return '<span class="LC_nobreak"><label>'.&mt('Records: [_1]',
-			       &Apache::lonmeta::selectbox('show',$env{'form.show'},'',undef,
+			       &Apache::lonmeta::selectbox('show',$env{'form.show'},'','',undef,
 							   (&mt('all'),10,20,50,100,1000,10000))).
 	   '</label></span> <span class="LC_nobreak">'.
            &mt('Filter: [_1]',
@@ -3050,9 +3072,12 @@ sub gradeleveldescription {
 }
 
 sub select_level_form {
-    my ($deflevel,$name)=@_;
+    my ($deflevel,$name,$id)=@_;
+    if ($id ne '') {
+        $id = ' id="'.$id.'"';
+    }
     unless ($deflevel) { $deflevel=0; }
-    my $selectform = "<select name=\"$name\" size=\"1\">\n";
+    my $selectform = "<select name=\"$name\" size=\"1\"$id>\n";
     for (my $i=0; $i<=18; $i++) {
         $selectform.="<option value=\"$i\" ".
             ($i==$deflevel ? 'selected="selected" ' : '').
@@ -3066,7 +3091,7 @@ sub select_level_form {
 
 =pod
 
-=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms,$disabled)
+=item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms,$disabled,$id)
 
 Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select the domain to preform an operation in.  
@@ -3085,17 +3110,22 @@ The optional $excdoms is a reference to
 
 The optional $disabled argument, if true, adds the disabled attribute to the select tag.
 
+The option $id argument is the value (if any) to set as the (unique) id attribute for the select tag.
+
 =cut
 
 #-------------------------------------------
 sub select_dom_form {
-    my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms,$disabled) = @_;
+    my ($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms,$disabled,$id) = @_;
     if ($onchange) {
         $onchange = ' onchange="'.$onchange.'"';
     }
     if ($disabled) {
         $disabled = ' disabled="disabled"';
     }
+    if ($id ne '') {
+        $id = ' id="'.$id.'"';
+    }
     my (@domains,%exclude);
     if (ref($incdoms) eq 'ARRAY') {
         @domains = sort {lc($a) cmp lc($b)} (@{$incdoms});
@@ -3106,7 +3136,7 @@ sub select_dom_form {
     if (ref($excdoms) eq 'ARRAY') {
         map { $exclude{$_} = 1; } @{$excdoms}; 
     }
-    my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange$disabled>\n";
+    my $selectdomain = "<select name=\"$name\" size=\"1\"$onchange$disabled$id>\n";
     foreach my $dom (@domains) {
         next if ($exclude{$dom});
         $selectdomain.="<option value=\"$dom\" ".
@@ -4842,9 +4872,10 @@ sub filemimetype {
 
 
 sub filecategoryselect {
-    my ($name,$value)=@_;
+    my ($name,$value,$id)=@_;
     return &select_form($value,$name,
-                        {'' => &mt('Any category'), map { $_,$_ } sort(keys(%category_extensions))});
+                        {'' => &mt('Any category'), map { $_,$_ } sort(keys(%category_extensions))},
+                        '','',$id);
 }
 
 =pod
@@ -5328,6 +5359,7 @@ sub get_student_view {
   $userview=~s/\<\/html\>//gi;
   $userview=~s/\<head\>//gi;
   $userview=~s/\<\/head\>//gi;
+  $userview=~s/\Q<div class="LC_landmark" role="main"\E/<div class="LC_landmark"/; 
   $userview=~s/action\s*\=/would_be_action\=/gi;
   $userview=&relative_to_absolute($feedurl,$userview);
   if (wantarray) {
@@ -6933,8 +6965,6 @@ sub bodytag {
         $role = &Apache::lonnet::plaintext($role);
     }
 
-    if (!$realm) { $realm='&nbsp;'; }
-
     my $extra_body_attr = &make_attr_string($forcereg,\%design);
 
 # construct main body tag
@@ -6958,7 +6988,6 @@ sub bodytag {
                 undef($role);
             }
             unless ($ltimenu->{'coursetitle'}) {
-                $realm='&nbsp;';
                 $showcrstitle = 0;
             }
         }
@@ -6968,7 +6997,6 @@ sub bodytag {
                 undef($role);
             }
             unless ($menuref->{'crs'}) {
-                $realm='&nbsp;';
                 $showcrstitle = 0;
             }
         }
@@ -7025,7 +7053,7 @@ sub bodytag {
             my $alttext = &mt('menu state: '.$menustate);
             my $tooltip = &mt($tiptext.' standard menus');
             $bodytag .= <<"END";
-<div id="LC_expandingContainer" style="display:inline;">
+<div id="LC_expandingContainer" style="display:inline;" role="navigation">
 <div id="LC_collapsible" class="LC_collapse_trigger" style="position: absolute;top: -5px;left: 0px; z-index:101; display:inline;">
 <a href="#" style="text-decoration:none;"><img class="LC_collapsible_indicator" alt="$alttext" title="$tooltip" src="/res/adm/pages/$menustate.png" style="border:0;margin:0;padding:0;max-width:100%;height:auto" /></a></div>
 <div class="LC_menus_content $divclass">
@@ -7036,29 +7064,35 @@ END
                                                               $args->{'links_disabled'},
                                                               $args->{'links_target'},
                                                               $collapsible);
-
+            my $labeltext = &HTML::Entities::encode(&mt('Primary links'));
             if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
                 if ($dc_info) {
                     $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;
                 }
-                $bodytag .= qq|<div id="LC_nav_bar">$left $role<br />
-                               <em>$realm</em> $dc_info</div>|;
+                $bodytag .= qq|<div id="LC_nav_bar" role="navigation" aria-label="$labeltext">$left $role</div>|;
+                unless (($realm eq '') && ($dc_info eq '')) {
+                    $bodytag .= qq|<div id="LC_realm" role="complementary"><em>$realm</em> $dc_info</div>|;
+                }
                 if ($need_endlcint) {
                     $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
                 }
                 return $bodytag;
             }
 
+            $bodytag .= '<div class="LC_landmark" style="margin: 3px 0 0 0;" role="navigation" aria-label="'.$labeltext.'">';
             unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
                 $bodytag .= qq|<div id="LC_nav_bar">$left $role</div>|;
             }
 
-            $bodytag .= $right;
+            $bodytag .= $right.'</div>';
 
             if ($dc_info) {
                 $dc_info = &dc_courseid_toggle($dc_info);
             }
-            $bodytag .= qq|<div id="LC_realm">$realm $dc_info</div>|;
+            unless (($realm eq '') && ($dc_info eq '')) {
+                $bodytag .= qq|<div id="LC_realm" role="complementary">$realm $dc_info</div>|;
+            }
+            $bodytag .= qq|<div style="clear: both; margin: 5px 0 0 0;"></div>|;
         }
 
         #if directed to not display the secondary menu, don't.  
@@ -7071,11 +7105,13 @@ END
         #don't show menus for public users
         if (!$public){
             unless ($args->{'no_inline_menu'}) {
-                $bodytag .= Apache::lonmenu::secondary_menu($httphost,$ltiscope,$ltimenu,
+                $bodytag .= '<div class="LC_landmark" role="navigation" aria-label="Secondary Links">'.
+                            Apache::lonmenu::secondary_menu($httphost,$ltiscope,$ltimenu,
                                                             $args->{'no_primary_menu'},
                                                             $menucoll,$menuref,
                                                             $args->{'links_disabled'},
-                                                            $args->{'links_target'});
+                                                            $args->{'links_target'}).
+                            '</div>';
             }
             $bodytag .= Apache::lonmenu::serverform();
             if ($need_endlcint) {
@@ -7090,7 +7126,7 @@ END
                                 $args->{'group'},$args->{'hide_buttons'},
                                 $hostname,$ltiscope,$ltiuri,$showncrumbsref);
             } else {
-                $bodytag .= 
+                $bodytag .=
                     &Apache::lonmenu::prepare_functions($env{'request.noversionuri'},
                                                         $forcereg,$args->{'group'},
                                                         $args->{'bread_crumbs'},
@@ -7099,7 +7135,7 @@ END
         } else {
             # this is to separate menu from content when there's no secondary
             # menu. Especially needed for publicly accessible resources.
-            $bodytag .= '<hr style="clear:both" />';
+            $bodytag .= '<hr style="clear:both" role="complementary" />';
             if ($need_endlcint) {
                 $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
             }
@@ -7301,6 +7337,12 @@ form, .inline {
   display: inline;
 }
 
+.LC_landmark {
+  margin: 0;
+  padding: 0;
+  border: none;
+}
+
 .LC_visually_hidden:not(:focus):not(:active) {
     clip-path: inset(50%);
     height: 1px;
@@ -7311,6 +7353,14 @@ form, .inline {
     display: inline;
 }
 
+.LC_heading_2 {
+  font-size: 1.17em;
+}
+
+.LC_heading_3 {
+  font-size: 1.0em;
+}
+
 .LC_menus_content.shown{
   display: block;
 }
@@ -7323,6 +7373,14 @@ form, .inline {
   text-align:right;
 }
 
+.LC_left {
+  text-align:left;
+}
+
+.LC_center {
+  text-align:center;
+}
+
 .LC_middle {
   vertical-align:middle;
 }
@@ -7466,9 +7524,10 @@ div.LC_confirm_box .LC_success img {
   padding: 4px;
 }
 
-table.LC_pastsubmission {
+.LC_pastsubmission {
   border: 1px solid black;
   margin: 2px;
+  padding: 2px;
 }
 
 table#LC_menubuttons {
@@ -7722,6 +7781,12 @@ table.LC_nested tr.LC_empty_row td {
 table.LC_caption {
 }
 
+caption.LC_caption_prefs {
+  font-weight: normal;
+  text-align: left;
+  padding-bottom: 0.8em;
+}
+
 table.LC_nested tr.LC_empty_row td {
   padding: 4ex
 }
@@ -7892,6 +7957,10 @@ table.LC_data_table tr > td.LC_roles_sel
   border-right: 8px solid #11CC55;
 }
 
+table.LC_data_table tr.LC_prefs_row {
+   line-height: 250%;
+}
+
 span.LC_current_location {
   font-size:larger;
   background: $pgbg;
@@ -7965,39 +8034,68 @@ table.LC_parm_overview_restrictions th {
   border-color: $pgbg;
 }
 
-table#LC_helpmenu {
-  border: none;
-  height: 55px;
-  border-spacing: 0;
+h1.LC_helpmenu {
+  display: inline;
+  font-size: 100%;
+  font-weight: normal;
+  line-height: 1em;
+  margin: 0;
+  padding: 0;
+  border: 0;
 }
 
-table#LC_helpmenu fieldset legend {
-  font-size: larger;
+.LC_helpdesk_headbox {
+  border: 2px groove threedface;
+  padding: 1em;
 }
 
-table#LC_helpmenu_links {
-  width: 100%;
-  border: 1px solid black;
+h1.LC_helpdesk_legend {
+  float: left;
+  margin: -1.7em 0 0;
+  padding: 0 .5em;
   background: $pgbg;
+  font-size: 1em;
+  font-weight: bold;
+}
+
+h1.LC_helpdesk_title {
+  display: inline;
+  font-size: 1em;
+  line-height: 2.5em;
+  margin: 0;
   padding: 0;
-  border-spacing: 1px;
+  vertical-align: bottom;
 }
 
-table#LC_helpmenu_links tr td {
-  padding: 1px;
+.LC_helpdesk_links {
+  border: 1px solid black;
+  padding: 3px;
   background: $tabbg;
   text-align: center;
   font-weight: bold;
+  display: inline;
+  margin-right: -6px;
+}
+
+.LC_helpdesk_img,
+.LC_helpdesk_text {
+  padding: 0;
+  margin: 0;
+  border: 0;
+  display: inline;
 }
 
-table#LC_helpmenu_links a:link,
-table#LC_helpmenu_links a:visited,
-table#LC_helpmenu_links a:active {
+.LC_helpdesk_img a:link,
+.LC_helpdesk_img a:visited,
+.LC_helpdesk_img a:active,
+.LC_helpdesk_text a:link,
+.LC_helpdesk_text a:visited,
+.LC_helpdesk_text a:active {
   text-decoration: none;
   color: $font;
 }
 
-table#LC_helpmenu_links a:hover {
+div.LC_helpdesk_text a:hover {
   text-decoration: underline;
   color: $vlink;
 }
@@ -8024,7 +8122,7 @@ table.LC_pick_box {
   border-spacing: 1px;
 }
 
-table.LC_pick_box td.LC_pick_box_title {
+table.LC_pick_box th.LC_pick_box_title {
   background: $sidebg;
   font-weight: bold;
   text-align: left;
@@ -8227,22 +8325,42 @@ table.LC_prior_tries td {
   padding: 6px;
 }
 
-.LC_prob_status {
-  display: table;
+span.LC_prob_status {
+  margin: 5px 0 0 0;
+  padding: 0 5px 0 0;
+  vertical-align: middle;
+}
+
+div.LC_prob_status_outer {
+  display: inline-block;
+  margin: -5px 0 0 0;
   padding: 0;
-  margin: 0;
 }
 
-.LC_prob_status_row {
-  display: table-row;
+div.LC_prob_status_inner {
+  display: inline-block;
+  margin: 0 5px 0 0;
+  padding: 5px;
 }
 
-.LC_status_cell {
-  display: table-cell;
-  padding-top: 0;
-  padding-left: 0;
-  padding-bottom: 0;
-  padding-right: 5px;
+caption.LC_filesub_status {
+  text-align: left;
+  font-weight: bold;
+}
+
+.LC_mail_actions {
+  float: left;
+  padding: 0;
+  margin: 6px;
+}
+
+.LC_vertical_line {
+  width: 1px;
+  background-color: black;
+  height: 4em;
+  float: left;
+  margin: 0;
+  padding: 0;
 }
 
 span.LC_prior_numerical,
@@ -8398,6 +8516,10 @@ div.LC_grade_show_user div.LC_Box {
   margin-right: 50px;
 }
 
+div.LC_grade_show_user div.LC_Box table tr th {
+  font-weight: normal;
+}
+
 div.LC_grade_submissions,
 div.LC_grade_message_center,
 div.LC_grade_info_links {
@@ -8428,6 +8550,12 @@ table.LC_scantron_action tr th {
   font-style:normal;
 }
 
+div.LC_edit_problem_daxe_header {
+  padding: 3px;
+  background: $tabbg;
+  z-index: 100;
+}
+
 .LC_edit_problem_header,
 div.LC_edit_problem_footer {
   font-weight: normal;
@@ -8493,8 +8621,9 @@ img.stift {
   vertical-align: middle;
 }
 
-table td.LC_mainmenu_col_fieldset {
-  vertical-align: top;
+div.LC_mainmenu {
+  margin: 3px 2px 2px 1px;
+  float: left;
 }
 
 div.LC_createcourse {
@@ -8576,8 +8705,9 @@ fieldset {
 }
 
 fieldset#LC_selectuser {
-    margin: 0;
-    padding: 0;
+  margin: -1px 0 0 0;
+  padding: 0;
+  border: 0;
 }
 
 article.geogebraweb div {
@@ -9135,7 +9265,7 @@ ul#LC_toolbar {
   padding: 0;
   margin: 2px;
   list-style:none;
-  position:relative;
+  display:inline;
   background-color:white;
   overflow: auto;
 }
@@ -9163,6 +9293,13 @@ a.LC_toolbarItem {
   background-color:transparent;
 }
 
+.LC_navtools {
+  display: inline-block;
+  padding: 0;
+  margin: 2px;
+  vertical-align: middle;
+}
+
 ul.LC_funclist {
     margin: 0;
     padding: 0.5em 1em 0.5em 0;
@@ -9267,13 +9404,39 @@ pre.LC_wordwrap {
 /*
   styles used for response display
 */
-div.LC_radiofoil, div.LC_rankfoil {
+div.LC_radiofoil, div.LC_rankfoil, div.LC_optionfoil, div.LC_matchfoil, div.LC_login_links {
   margin: .5em 0em .5em 0em;
 }
 table.LC_itemgroup {
   margin-top: 1em;
 }
 
+table.LC_itemgroup tr th {
+  font-weight: normal;
+}
+
+fieldset.LC_webbubbles {
+  margin: 2px 0 0 0;
+  padding: 0;
+  border: 0;
+}
+
+ul.LC_webbubbles {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+  text-align: left;
+  float: left;
+}
+
+ul.LC_webbubbles li {
+  line-height: 1.8em;
+  border: 1px solid black;
+  padding: 0 2px 0 5px;
+  margin: 0 0 0 -1px;
+  float: left;
+}
+
 /*
   styles used by TTH when "Default set of options to pass to tth/m
   when converting TeX" in course settings has been set
@@ -9697,7 +9860,11 @@ OFFLOAD
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta name="apple-mobile-web-app-capable" content="yes" />';
     }
-    $result .= '<meta name="google" content="notranslate" />'."\n";
+    $result .= '<meta name="google" content="notranslate"';
+    if (!$args->{'frameset'}) {
+        $result .= ' /';
+    }
+    $result .= '>'."\n";
     return $result.'</head>';
 }
 
@@ -9828,7 +9995,7 @@ sub xml_begin {
 	    .'xmlns="http://www.w3.org/1999/xhtml">';
     } elsif ($is_frameset) {
         $output='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'."\n".
-                '<html>'."\n";
+                '<html lang="en">'."\n";
     } else {
 	$output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n".
                 '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'."\n";
@@ -10741,8 +10908,10 @@ sub simple_error_page {
     }
 
     my $page =
-	&Apache::loncommon::start_page($title,'',\%displayargs).
+	&Apache::loncommon::start_page($title,'',\%displayargs)."\n".
+        '<div class="LC_landmark" style="clear:both" role="main">'.
 	'<p class="LC_error">'.$msg.'</p>'.
+        '</div>'.
 	&Apache::loncommon::end_page();
     if (ref($r)) {
 	$r->print($page);
@@ -10764,6 +10933,11 @@ sub simple_error_page {
         return;
     }
 
+    sub set_data_table_count {
+        my ($count) = @_;
+        unshift(@row_count,$count);
+    }
+
     sub start_data_table {
 	my ($add_class,$id) = @_;
 	my $css_class = (join(' ','LC_data_table',$add_class));
@@ -10811,7 +10985,11 @@ sub simple_error_page {
     }
 
     sub start_data_table_header_row {
-	return  '<tr class="LC_header_row">'."\n";;
+	my ($add_class,$id) = @_;
+	my $css_class = 'LC_header_row';
+	$css_class = (join(' ',$css_class,$add_class)) unless ($add_class eq '');
+	$id = (' id="'.$id.'"') unless ($id eq '');
+	return '<tr class="'.$css_class.'"'.$id.'>'."\n";
     }
 
     sub end_data_table_header_row {
@@ -10819,8 +10997,8 @@ sub simple_error_page {
     }
 
     sub data_table_caption {
-        my $caption = shift;
-        return "<caption class=\"LC_caption\">$caption</caption>";
+        my ($caption,$css_class) = @_;
+        return "<caption class=\"LC_caption $css_class\">$caption</caption>";
     }
 }
 
@@ -18938,7 +19116,7 @@ Returns: HTML to display with informatio
 sub check_release_result {
     my ($switchwarning,$switchserver) = @_;
     my $output = &start_page('Selected course unavailable on this server').
-                 '<p class="LC_warning">';
+                 '<div class="LC_landmark" role="main"><p class="LC_warning">';
     if ($switchwarning) {
         $output .= $switchwarning.'<br /><a href="/adm/roles">';
         if (&show_course()) {
@@ -18954,7 +19132,7 @@ sub check_release_result {
                    &mt('Switch Server').
                    '</a>';
     }
-    $output .= '</p>'.&end_page();
+    $output .= '</p></div>'.&end_page();
     return $output;
 }
 
@@ -19038,8 +19216,8 @@ sub needs_coursereinit {
                     $update = 'supp';
                 }
             }
-            return ($update);
         }
+        return ($update);
     }
     return ();
 }
@@ -19570,9 +19748,9 @@ sub create_captcha {
         if (-e $Apache::lonnet::perlvar{'lonCaptchaDir'}.'/'.$md5sum.'.png') {
             $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n".
                       '<span class="LC_nobreak">'.
-                      &mt('Type in the letters/numbers shown below').'&nbsp;'.
-                      '<input type="text" size="5" name="code" value="" autocomplete="new-password" />'.
-                      '</span><br />'.
+                      '<label>'.&mt('Type in the letters/numbers shown below').'&nbsp;'.
+                      '<input type="text" size="5" name="code" value="" autocomplete="new-password" aria-required="true" />'.
+                      '</label></span><br />'.
                       '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" alt="captcha" />';
             last;
         }