/* ============================================================================
   HNU-SIS — Unified Theme Override  (2026-07-30)
   ----------------------------------------------------------------------------
   ONE professional brand skin applied on top of everything, so the native
   framework chrome and the custom Vue admin modules read as a single product.

   PURELY ADDITIVE. Loaded LAST on every page (see Warehouse.php header_head
   hook), so it wins by cascade order — no edits to the base theme stylesheet
   or base.css. Colours/typography/borders only; no layout-structural changes,
   so it is safe in both LTR (English) and RTL (Arabic) modes.
   ============================================================================ */

:root {
  /* Brand */
  --hnu-navy:      #14293f;
  --hnu-navy-2:    #1e3a5f;
  --hnu-steel:     #2c6e8f;
  --hnu-teal:      #0e7c66;
  --hnu-teal-2:    #12a184;
  --hnu-gold:      #d9a441;
  --hnu-bg:        #f4f7fa;
  --hnu-surface:   #ffffff;
  --hnu-line:      #e3eaf1;
  --hnu-ink:       #1c2733;
  --hnu-muted:     #5b6b7b;

  /* Re-point the custom-module design tokens (base.css) at the brand so every
     Vue page that uses var(--primary-color) recolours consistently. */
  --primary-color: #1e3a5f;
  --primary-dark:  #14293f;
  --primary-light: #2c6e8f;   /* gradient end: navy -> steel */
  --info-color:    #0e7c66;
  --text-primary:  #1c2733;
  --border-color:  #e3eaf1;
  --light-bg:      #f4f7fa;
}

/* ---- Typography: clean professional stack, Arabic-safe fallback ---------- */
body, input, select, textarea, button,
.adminmenu, .wp-submenu, .menu-top, #menu-top,
.button, .button-primary {
  font-family: -apple-system, "Segoe UI", Roboto, system-ui,
               "Cairo", "Tahoma", "Helvetica Neue", Arial, sans-serif;
}

h1, h2, h3, h4, h5, h6 { color: var(--hnu-navy-2); }

/* ============================================================================
   NATIVE FRAMEWORK CHROME — replace the WordPress-admin "tells"
   ============================================================================ */

/* Left sidebar shell (was WordPress blue #0073aa) */
#menu {
  background: linear-gradient(180deg, var(--hnu-navy) 0%, var(--hnu-navy-2) 100%) !important;
  border-color: rgba(0,0,0,.25) !important;
  color: #eaf1f8 !important;
}
#menu-top select {
  background: rgba(255,255,255,.08) !important;
  border-color: rgba(255,255,255,.25) !important;
  color: #fff !important;
  border-radius: 6px;
}
#menu-top select:focus { border-bottom-color: var(--hnu-teal-2) !important; }

/* The closed control is white-on-navy, but the OPEN dropdown list is painted by
   the OS on a white surface — so its options must be dark, or the list reads as
   blank. Applies to every select sitting on dark chrome. */
#menu select option,
#menu-top select option,
.chb-header select option,
.ud-header select option,
[class*="-header"] select option {
  color: #1c2733 !important;
  background-color: #fff !important;
}
#menu select option:checked,
#menu-top select option:checked {
  background-color: var(--hnu-steel) !important;
  color: #fff !important;
}
#menu-top .username { color: #fff !important; }
#menu-top .today-date { color: #b9c9d8 !important; }

/* Module nav groups (were near-black #121212) */
.adminmenu { background: transparent !important; border-color: transparent !important; }
.menu-top {
  background-color: rgba(255,255,255,.04) !important;
  border-top-color: rgba(255,255,255,.06) !important;
  border-bottom-color: rgba(0,0,0,.18) !important;
  color: #eaf1f8 !important;
  text-transform: none !important;      /* de-WordPress: drop the ALL-CAPS look */
  letter-spacing: .2px;
}
a.menu-top, .BottomButton { color: #eaf1f8 !important; }
#selectedModuleLink, .menu-top:focus, .menu-top:hover {
  background-color: var(--hnu-teal) !important;
  color: #fff !important;
}

/* The framework paints EVERY sidebar link with the WordPress blue via
   `.adminmenu a` (and the same rule blues the top-bar buttons on hover). That
   was the last obvious "this is RosarioSIS" tell in the chrome: the nav links
   read as bright blue chips on the navy shell. Let the shell show through and
   use the brand teal only to mark hover / the current page. */
.adminmenu a {
  background-color: transparent !important;
  color: #d6e2ee !important;
}
.adminmenu a:hover, .adminmenu a:focus,
.adminmenu a.current, .adminmenu li.current > a {
  background-color: var(--hnu-teal) !important;
  color: #fff !important;
}
.BottomButton:hover, .BottomButton:focus, .BottomButton:active {
  background-color: rgba(255,255,255,.14) !important;
  color: #fff !important;
}

/* Submenu (was #0073aa) */
.wp-submenu { background: rgba(0,0,0,.16) !important; border-color: rgba(0,0,0,.25) !important; }
.wp-submenu a { color: #d6e2ee !important; }
#selectedMenuLink, .wp-submenu a:focus, .wp-submenu a:hover {
  background-color: var(--hnu-teal) !important;
  color: #fff !important;
}
.menu-inter { border-color: rgba(255,255,255,.08) !important; color: #9fb3c6 !important; }

/* Top icon bar (was rust #c07742) — unify with the sidebar navy */
#footer {
  background: var(--hnu-navy-2) !important;
  box-shadow: 0 2px 6px rgba(14,42,71,.25) !important;
}
#footerwrap {
  background: var(--hnu-navy-2) !important;
  border-color: var(--hnu-navy-2) !important;
}

/* ============================================================================
   CONTROLS — buttons, focus, tables (native pages)
   ============================================================================ */

a.button-primary, button.button-primary, input.button-primary {
  background: var(--hnu-navy-2) !important;
  border-color: var(--hnu-navy) !important;
  color: #fff !important;
  border-radius: 7px;
}
a.button-primary:hover, button.button-primary:hover, input.button-primary:hover,
a.button-primary:focus, button.button-primary:focus, input.button-primary:focus {
  background: var(--hnu-teal) !important;
  border-color: var(--hnu-teal) !important;
}
a.button-primary:active, button.button-primary:active, input.button-primary:active {
  background: var(--hnu-navy) !important;
}
.button { border-radius: 7px; }

/* Text inputs / selects focus accent (was #298cba) */
input:focus, select:focus, textarea:focus {
  border-bottom-color: var(--hnu-teal) !important;
}

/* Native tables: soften the dated look a touch (colour only, no reflow) */
.postbox, .widefat {
  border-color: var(--hnu-line) !important;
  border-radius: 10px;
  overflow: hidden;
}
.postbox > thead th, .widefat thead th, .widefat th {
  background: #eef4f9 !important;
  color: #33475b !important;
}
.postbox .h3selected { border-top-color: var(--hnu-teal) !important; }

/* Page canvas */
body, html { background: var(--hnu-bg) !important; }
body { color: var(--hnu-ink); }
#body { background: var(--hnu-bg) !important; }

/* Links */
a { color: var(--hnu-navy-2); }
a:hover { color: var(--hnu-teal); }

/* ============================================================================
   LOGIN PAGE — rebuilt as a standalone branded sign-in screen
   ----------------------------------------------------------------------------
   The markup is the framework's table-based popTable; everything below
   re-lays it out as a modern centred card over a brand backdrop. CSS only —
   index.php is untouched, so the form, CSRF token and locale links keep working.
   ============================================================================ */
body.login {
  min-height: 100vh;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  box-sizing: border-box;
  background:
    radial-gradient(1100px 620px at 12% -10%, rgba(18,161,132,.30), transparent 60%),
    radial-gradient(900px 560px at 105% 110%, rgba(44,110,143,.38), transparent 62%),
    linear-gradient(135deg, #0c1f33 0%, #14293f 45%, #1e3a5f 100%) !important;
}

body.login #body {
  width: 100%;
  max-width: 430px;
  padding: 0 !important;
  overflow: visible;
  background: transparent !important;
}
body.login #body > br { display: none; }

/* The card */
body.login .postbox-wrapper { width: 100%; }
body.login table.postbox {
  display: block;
  width: 100%;
  background: #fff !important;
  border: none !important;
  border-radius: 18px;
  box-shadow: 0 26px 70px rgba(0,0,0,.45), 0 2px 8px rgba(0,0,0,.25);
  overflow: hidden;
}
body.login table.postbox > thead,
body.login table.postbox > tbody,
body.login table.postbox tr,
body.login table.postbox th,
body.login table.postbox td { display: block; width: 100%; box-sizing: border-box; }

/* Card header strip */
body.login table.postbox > thead th {
  background: linear-gradient(135deg, var(--hnu-navy) 0%, var(--hnu-navy-2) 55%, var(--hnu-steel) 100%) !important;
  padding: 20px 26px !important;
  border: none !important;
  text-align: center;
}
body.login table.postbox > thead th h3.title {
  color: #fff !important;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  margin: 0;
}

/* Card body */
body.login td.popTable { padding: 30px 34px 34px !important; border: none !important; }

body.login img.logo {
  display: block;
  margin: 0 auto 14px;
  max-width: 88px;
  height: auto;
  filter: drop-shadow(0 4px 10px rgba(14,41,63,.22));
}
body.login h4.center {
  text-align: center;
  color: var(--hnu-navy-2) !important;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.5;
  margin: 0 0 22px;
}

/* Form: unwrap the layout table */
body.login #loginform table,
body.login #loginform tbody,
body.login #loginform tr,
body.login #loginform td { display: block; width: 100%; box-sizing: border-box; }
body.login #loginform td { padding: 0 0 16px !important; border: none !important; }

/* Label above field (markup order is input-then-text, so reverse it) */
body.login #loginform label {
  display: flex;
  flex-direction: column-reverse;
  gap: 7px;
  font-size: 12.5px;
  font-weight: 600;
  color: #55677a;
  letter-spacing: .3px;
}
body.login #loginform input[type=text],
body.login #loginform input[type=password] {
  width: 100% !important;
  max-width: none !important;
  box-sizing: border-box;
  padding: 12px 14px !important;
  font-size: 15px;
  color: var(--hnu-ink);
  background: #f7fafc;
  border: 1.5px solid #dde5ee !important;
  border-radius: 10px;
  outline: none;
  transition: border-color .15s, box-shadow .15s, background .15s;
}
body.login #loginform input[type=text]:focus,
body.login #loginform input[type=password]:focus {
  background: #fff;
  border-color: var(--hnu-teal) !important;
  box-shadow: 0 0 0 3px rgba(14,124,102,.16);
}

/* Language chooser: flags become labelled pills (title="English"/"Arabic") */
body.login #loginform tr:first-child td {
  display: flex !important;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 0;              /* hides the stray "Language" caption + <br> */
  padding-bottom: 20px !important;
  border-bottom: 1px solid #eef2f7 !important;
  margin-bottom: 20px;
}
body.login #loginform tr:first-child td br { display: none; }
body.login #loginform tr:first-child a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 15px;
  border: 1.5px solid #dde5ee;
  border-radius: 999px;
  background: #f7fafc;
  text-decoration: none;
  transition: all .15s;
}
body.login #loginform tr:first-child a::after {
  content: attr(title);      /* "English" / "Arabic" */
  font-size: 12.5px;
  font-weight: 600;
  color: #55677a;
  letter-spacing: .2px;
}
body.login #loginform tr:first-child a:hover {
  border-color: var(--hnu-teal);
  background: #eefaf6;
}
body.login #loginform tr:first-child a:hover::after { color: var(--hnu-teal); }
body.login #loginform tr:first-child img {
  width: 20px !important;
  height: auto;
  border-radius: 3px;
  display: inline-block;
}

/* Submit */
body.login p.center { margin: 4px 0 0; }
body.login .button-primary, body.login input.button-primary {
  width: 100%;
  padding: 13px 18px !important;
  font-size: 15px !important;
  font-weight: 700 !important;
  letter-spacing: .4px;
  color: #fff !important;
  border: none !important;
  border-radius: 10px;
  cursor: pointer;
  background: linear-gradient(135deg, var(--hnu-navy-2) 0%, var(--hnu-teal) 100%) !important;
  box-shadow: 0 8px 20px rgba(14,124,102,.28);
  transition: transform .12s, box-shadow .15s, filter .15s;
}
body.login .button-primary:hover {
  filter: brightness(1.07);
  box-shadow: 0 10px 26px rgba(14,124,102,.36);
}
body.login .button-primary:active { transform: translateY(1px); }

/* Messages inside the card */
body.login .error, body.login .note {
  border-radius: 10px;
  font-size: 13px;
  margin-bottom: 16px;
}

@media (max-width: 480px) {
  body.login { padding: 14px; }
  body.login td.popTable { padding: 24px 20px 26px !important; }
}

/* ============================================================================
   CUSTOM ADMIN PAGES — one page-header identity
   ----------------------------------------------------------------------------
   Each Vue page shipped its own gradient (purple, red, orange, green, pink…),
   which is what made the product look like a bundle of unrelated tools.
   Collapse every PAGE/MODAL header banner onto the brand gradient.

   Semantic colours are deliberately NOT touched: .btn-danger stays red,
   .btn-success stays green, blocked/warning banners keep their meaning.
   ============================================================================ */
.page-header-gradient,
.page-header,
.app-header,
.ud-header,   /* University Dashboard   */
.chb-header,  /* Credit Hour Billing    */
.fm-header,   /* Financial Management   */
.sp-header,   /* Student Payment        */
.sr-header,   /* Service Requests       */
.as-header,   /* Admin Services         */
.ads-header,  /* Admission Sync         */
.pm-header,   /* Portal Management      */
.ms-header,   /* Module screen          */
.rm-header,   /* Registration Monitor   */
.st-header,   /* Student Transfer       */
.schedule-header,
.form-header,
.as-modal-header,
.sr-modal-header,
.rm-modal-header,
.transcript-modal-header {
  background: linear-gradient(135deg, var(--hnu-navy) 0%, var(--hnu-navy-2) 55%, var(--hnu-steel) 100%) !important;
  color: #fff !important;
  border-radius: 12px;
  box-shadow: 0 4px 14px rgba(14, 41, 63, .18);
}

/* A heading inside ANY header/banner container must take that container's own
   colour instead of the global dark heading colour set above. Without this, a
   heading on a dark gradient renders dark-on-dark (invisible) whenever its exact
   class isn't in the allowlist below — which is how `.schedule-header h1` broke.
   `inherit` is correct for light containers too: they simply pass down their own
   dark text colour. Generic, so new pages are covered automatically.

   NO `!important` here, deliberately. This selector is (0,1,1), which already
   beats the blanket `h1` (0,0,1) — that is all it needs to do. Adding
   `!important` also overrode headings that declare their OWN light colour, e.g.
   `.course-banner .course-title { color: white }` (0,2,0): the title then
   inherited the page's dark ink and vanished on the indigo banner (1.14:1).
   Let the cascade work: a heading with an explicit colour keeps it, a heading
   without one follows its container. */
[class*="-header"] h1, [class*="-header"] h2, [class*="-header"] h3,
[class*="-header"] h4, [class*="-header"] h5, [class*="-header"] h6,
[class*="-banner"] h1, [class*="-banner"] h2, [class*="-banner"] h3,
[class*="-hero"] h1, [class*="-hero"] h2, [class*="-hero"] h3 {
  color: inherit;
}

/* The same trap catches the NON-heading text in those banners: subtitles,
   straplines and "course info" lines were authored in mid-grey for a light
   header, then the override repainted the header dark and left them at ~1.5:1.
   Make every descriptive line in a header follow the container too.
   NOTE: restricted to TEXT elements (p/span/small) on purpose. A bare
   `[class*="-info"]` also matched `.ce-btn-info` — a BUTTON with its own light
   background — and forced white ink onto it (1.1:1). Never let this block
   select interactive controls. */
[class*="-header"] > p, [class*="-header"] small,
[class*="-header"] p[class*="subtitle"], [class*="-header"] span[class*="subtitle"],
[class*="-header"] div[class*="subtitle"],
[class*="-header"] p[class*="-info"], [class*="-header"] span[class*="-info"],
[class*="-header"] .header-subtitle, [class*="-header"] .strapline,
[class*="-header"] .header-title > span, [class*="-header"] .header-content p {
  color: inherit !important;
  opacity: .92;
}

/* Header text/controls must stay legible on the brand gradient */
.page-header-gradient h1, .page-header-gradient h2, .page-header-gradient h3,
.page-header h1, .page-header h2, .page-header h3,
.ud-header h1, .ud-header h2, .ud-header h3,
.chb-header h2, .fm-header h2, .sp-header h2, .sr-header h2,
.as-header h2, .ads-header h2, .pm-header h2, .ms-header h2,
.rm-header h1, .rm-header h2, .st-header h2, .schedule-header h2,
.as-modal-header h3, .sr-modal-header h3, .rm-modal-header h3,
.transcript-modal-header h3, .form-header h3 {
  color: #fff !important;
}

/* ----------------------------------------------------------------------------
   Remaining low-contrast pairs found by the contrast audit. Each is a case
   where one stylesheet set a text colour and a LATER one replaced only the
   background (or vice-versa), leaving fg and bg on the same side of the scale.
   Fixed here additively so the owning stylesheets stay untouched.
   ---------------------------------------------------------------------------- */

/* Schedule cards: `.course-period-card` sets `color:white` once, then five of
   the eight subject palettes swap in a pastel background — white on pastel.
   `.subject-8` already corrected itself with a dark ink; do the same for 3-7. */
.course-period-card.subject-3, .course-period-card.subject-4,
.course-period-card.subject-5, .course-period-card.subject-6,
.course-period-card.subject-7 {
  color: #1b2a38;
}
.course-period-card.subject-3 .cp-title, .course-period-card.subject-4 .cp-title,
.course-period-card.subject-5 .cp-title, .course-period-card.subject-6 .cp-title,
.course-period-card.subject-7 .cp-title { color: #1b2a38; }

/* Disabled buttons that swapped to a light grey fill but kept white text. */
.add-btn:disabled { color: #5b6673; }
/* Cancel button: a later gradient (#cacaca→#797979) replaced the solid grey but
   left the inherited white text unreadable over the light half. */
.action-btn.cancel { color: #24313d; }

/* Filled pills/badges on a teal→lime gradient: the light end left white text at
   ~1.5:1. Use the solid brand teal, which clears 5:1 with white. */
.rp-badge { background: var(--hnu-teal) !important; color: #fff !important; }

/* "Not applicable" marker in the permissions matrix was #ddd on white — an
   admin could not tell "feature absent" from "cell failed to render". */
.feature-na { color: #94a3b8 !important; }

/* White label on the light emerald success button (#50c878 → #45b06b) measured
   2.1:1. Deepen the green rather than darkening the text, so the button still
   reads as "success" while clearing the contrast floor. */
.btn.btn-success, button.btn-success {
  background: linear-gradient(135deg, #1f9d55 0%, #157f43 100%) !important;
  color: #fff !important;
}

/* Disabled inputs often carry system-computed values the user still must read;
   #999 on #f3f4fa is below the floor. */
.ce-input[disabled], .gpa-input:disabled, .gpa-select:disabled { color: #5b6673 !important; }

/* The `.outline` button variant is used in the markup but was never defined in
   ANY stylesheet, so those buttons fell back to the default dark button text on
   a transparent background — invisible when they sit on a dark page header.
   Define it properly for both contexts. */
.action-btn.outline {
  background: transparent;
  color: var(--hnu-navy-2);
  border: 1px solid rgba(20, 41, 63, .35);
}
.action-btn.outline:hover:not(:disabled) { background: rgba(20, 41, 63, .07); }

/* Same button on a dark header: invert to a light ghost. `[class*="-header"]`
   matches the banner containers (.page-header, .schedule-header, …) but NOT
   `.header-actions`, which is the toolbar inside them. */
[class*="-header"] .action-btn.outline {
  background: rgba(255, 255, 255, .12);
  color: #fff;
  border-color: rgba(255, 255, 255, .5);
}
[class*="-header"] .action-btn.outline:hover:not(:disabled) {
  background: rgba(255, 255, 255, .22);
}

/* Modal headers sit flush inside the dialog — no floating corners */
.as-modal-header, .sr-modal-header, .rm-modal-header, .transcript-modal-header {
  border-radius: 12px 12px 0 0;
  box-shadow: none;
}

/* Shared primary action buttons in the custom modules */
.btn-primary {
  background: var(--hnu-navy-2) !important;
  border-color: var(--hnu-navy) !important;
}
.btn-primary:hover:not(:disabled) {
  background: var(--hnu-teal) !important;
  border-color: var(--hnu-teal) !important;
}

/* ============================================================================
   LAYOUT — content fills the screen
   ----------------------------------------------------------------------------
   The sidebar is a left float and every page wrapper shipped
   `max-width:1800px; margin:0 auto`, which left a dead gutter on wide screens.
   Give the content column its own block-formatting context so it sits flush
   beside the sidebar, and let the page wrappers use the full width.
   ============================================================================ */
#body {
  overflow-x: hidden;          /* BFC → sits beside the floated #menu */
  padding: 14px 18px 38px;
}

.ads-page, .as-page, .brc-page, .bulk-reg-page, .chb-page, .fm-page,
.gpa-report-page, .gpa-test-app, .grade-monitor-page, .grades-editor,
.ms-page, .pm-page, .rm-page, .sp-page, .sr-page, .st-page,
.student-grades-page, .student-status-page, .students-page,
.transfer-page, .ud-page, .program-editor-container,
.data-container, .data-container.centered {
  max-width: none !important;
  width: auto !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
}

/* ============================================================================
   TOP APP BAR — replace the stock raster icons with clean line icons
   ----------------------------------------------------------------------------
   The bar rendered circular PNGs from the framework's own icon set. Rather than
   editing PHP, hide the <img> and paint a crisp SVG via CSS mask, so the icon
   inherits the bar's colour and stays sharp at any DPI.
   ============================================================================ */
#footerwrap {
  height: auto;
  padding: 7px 14px;
  text-align: left;
  border: none;
  display: flex;
  align-items: center;
  gap: 4px;
  overflow-x: auto;
}

.BottomButton {
  display: inline-flex !important;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  border-radius: 8px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .2px;
  text-transform: none;
  white-space: nowrap;
  transition: background .15s ease;
}
.BottomButton:hover { background: rgba(255,255,255,.12); }

/* Drop the framework's PNG glyphs */
.BottomButton img { display: none !important; }

/* Draw the replacement icon */
.BottomButton::before {
  content: "";
  width: 17px;
  height: 17px;
  flex: 0 0 17px;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
  /* default: grid/apps glyph */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1.5'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1.5'/%3E%3C/svg%3E");
}

/* Hamburger — Menu */
#BottomButtonMenu::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 7h16M4 12h16M4 17h16'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M4 7h16M4 12h16M4 17h16'/%3E%3C/svg%3E");
}

/* Program / School — building */
.BottomButton[href*="modname=School_Setup"]::before,
.BottomButton[href*="modname=Program"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 21h18M5 21V7l7-4 7 4v14M9 21v-5h6v5M9 10h.01M15 10h.01M9 13.5h.01M15 13.5h.01'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 21h18M5 21V7l7-4 7 4v14M9 21v-5h6v5M9 10h.01M15 10h.01M9 13.5h.01M15 13.5h.01'/%3E%3C/svg%3E");
}

/* Students — graduation cap */
.BottomButton[href*="modname=Students"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 1 9l11 6 9-4.91V17M5 13.18v4L12 21l7-3.82v-4'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 1 9l11 6 9-4.91V17M5 13.18v4L12 21l7-3.82v-4'/%3E%3C/svg%3E");
}

/* Users / Staff — people */
.BottomButton[href*="modname=Users"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='9' cy='7' r='4'/%3E%3Cpath d='M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='9' cy='7' r='4'/%3E%3Cpath d='M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75'/%3E%3C/svg%3E");
}

/* Scheduling — calendar */
.BottomButton[href*="modname=Scheduling"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='17' rx='2'/%3E%3Cpath d='M3 10h18M8 2v4M16 2v4'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='17' rx='2'/%3E%3Cpath d='M3 10h18M8 2v4M16 2v4'/%3E%3C/svg%3E");
}

/* Grades — chart */
.BottomButton[href*="modname=Grades"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 3v18h18'/%3E%3Cpath d='M7 15l3.5-4 3 2.5L21 7'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 3v18h18'/%3E%3Cpath d='M7 15l3.5-4 3 2.5L21 7'/%3E%3C/svg%3E");
}

/* Billing — credit card */
.BottomButton[href*="modname=Billing"]::before,
.BottomButton[href*="modname=Student_Billing"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='5' width='20' height='14' rx='2'/%3E%3Cpath d='M2 10h20M6 15h4'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='5' width='20' height='14' rx='2'/%3E%3Cpath d='M2 10h20M6 15h4'/%3E%3C/svg%3E");
}

/* Administration — sliders */
.BottomButton[href*="modname=Administration"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6'/%3E%3C/svg%3E");
}

/* Print */
.BottomButton[href*="bottomfunc=print"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9V2h12v7M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2'/%3E%3Crect x='6' y='14' width='12' height='8' rx='1'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9V2h12v7M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2'/%3E%3Crect x='6' y='14' width='12' height='8' rx='1'/%3E%3C/svg%3E");
}

/* Logout */
.BottomButton[href*="modfunc=logout"]::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9'/%3E%3C/svg%3E");
}
.BottomButton[href*="modfunc=logout"]:hover { background: rgba(229,57,53,.85); }

/* Language toggle — globe glyph + a subtle outlined pill so it stands out */
#BottomButtonLang {
  margin-inline-start: 6px;
  border: 1px solid rgba(255,255,255,.30);
  background: rgba(255,255,255,.06);
}
#BottomButtonLang:hover { background: rgba(255,255,255,.16); }
#BottomButtonLang::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M2 12h20M12 2a15 15 0 0 1 0 20M12 2a15 15 0 0 0 0 20'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M2 12h20M12 2a15 15 0 0 1 0 20M12 2a15 15 0 0 0 0 20'/%3E%3C/svg%3E");
}

/* Back button keeps its own arrow */
#BottomButtonBack::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 12H5M12 19l-7-7 7-7'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 12H5M12 19l-7-7 7-7'/%3E%3C/svg%3E");
}

/* The a11y skip-link must not gain an icon */
.a11y-hidden::before { display: none !important; }

/* The busy indicator is also a .BottomButton — it must NOT inherit the default
   grid glyph. Give it a real spinner instead. */
.BottomButton.loading::before {
  -webkit-mask-image: none !important;
          mask-image: none !important;
  background-color: transparent !important;
  width: 15px; height: 15px; flex-basis: 15px;
  border: 2px solid rgba(255,255,255,.28);
  border-top-color: #fff;
  border-radius: 50%;
  animation: hnuSpin .7s linear infinite;
}
@keyframes hnuSpin { to { transform: rotate(360deg); } }

/* Hide it entirely while idle (the framework toggles it during requests) */
.BottomButton.loading { padding: 7px 6px; background: none !important; }

/* Sidebar module icons — the framework ships PNGs here too */
.menu-top img { display: none !important; }

/* ============================================================================
   PAGE-TITLE ICON — the round badge next to every page heading
   ----------------------------------------------------------------------------
   `DrawHeader()` emits <span class="module-icon {Modcat}">, which the base theme
   paints as a circular raster badge with a rust border. Reduce it to a flat
   brand-tinted line icon matching the app bar.
   ============================================================================ */
.module-icon {
  width: 26px !important;
  height: 26px !important;
  border: none !important;
  border-radius: 0 !important;
  background-color: var(--hnu-steel) !important;
  background-image: none !important;
  vertical-align: -5px !important;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
  /* default glyph */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1.5'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='3' width='7' height='7' rx='1.5'/%3E%3Crect x='3' y='14' width='7' height='7' rx='1.5'/%3E%3Crect x='14' y='14' width='7' height='7' rx='1.5'/%3E%3C/svg%3E");
}
.header1 .module-icon { vertical-align: -5px !important; }

.module-icon.Students {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 1 9l11 6 9-4.91V17M5 13.18v4L12 21l7-3.82v-4'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3 1 9l11 6 9-4.91V17M5 13.18v4L12 21l7-3.82v-4'/%3E%3C/svg%3E");
}
.module-icon.Users, .module-icon.Staff_Absences {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='9' cy='7' r='4'/%3E%3Cpath d='M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='9' cy='7' r='4'/%3E%3Cpath d='M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75'/%3E%3C/svg%3E");
}
.module-icon.Scheduling {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='17' rx='2'/%3E%3Cpath d='M3 10h18M8 2v4M16 2v4'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='17' rx='2'/%3E%3Cpath d='M3 10h18M8 2v4M16 2v4'/%3E%3C/svg%3E");
}
.module-icon.Grades, .module-icon.Eligibility {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 3v18h18'/%3E%3Cpath d='M7 15l3.5-4 3 2.5L21 7'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 3v18h18'/%3E%3Cpath d='M7 15l3.5-4 3 2.5L21 7'/%3E%3C/svg%3E");
}
.module-icon.Student_Billing, .module-icon.Accounting {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='5' width='20' height='14' rx='2'/%3E%3Cpath d='M2 10h20M6 15h4'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='5' width='20' height='14' rx='2'/%3E%3Cpath d='M2 10h20M6 15h4'/%3E%3C/svg%3E");
}
.module-icon.School_Setup, .module-icon.misc {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 21h18M5 21V7l7-4 7 4v14M9 21v-5h6v5'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 21h18M5 21V7l7-4 7 4v14M9 21v-5h6v5'/%3E%3C/svg%3E");
}
.module-icon.Administration {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6'/%3E%3C/svg%3E");
}
.module-icon.Reports, .module-icon.Resources {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpath d='M14 2v6h6M8 13h8M8 17h5'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z'/%3E%3Cpath d='M14 2v6h6M8 13h8M8 17h5'/%3E%3C/svg%3E");
}

/* ============================================================================
   RTL (Arabic mode)
   ----------------------------------------------------------------------------
   The framework sets dir="RTL" on <html> from the locale. The override is
   overwhelmingly colour/typography, which is direction-agnostic; only the few
   directional rules above need mirroring.
   ============================================================================ */
html[dir="RTL"] #footerwrap { text-align: right; }
html[dir="RTL"] #menu { float: right; border-width: 0 0 0 1px; }
html[dir="RTL"] #body { padding: 14px 18px 38px; }

/* Modern Arabic typeface (loaded only in Arabic mode; falls back gracefully).
   Scoped to RTL so English pages keep the neutral system stack. */
html[dir="RTL"] body,
html[dir="RTL"] input,
html[dir="RTL"] select,
html[dir="RTL"] textarea,
html[dir="RTL"] button,
html[dir="RTL"] .adminmenu,
html[dir="RTL"] .wp-submenu,
html[dir="RTL"] .menu-top,
html[dir="RTL"] .BottomButton,
html[dir="RTL"] [class*="-header"],
html[dir="RTL"] [class*="-page"],
html[dir="RTL"] [class*="-card"],
html[dir="RTL"] h1, html[dir="RTL"] h2, html[dir="RTL"] h3,
html[dir="RTL"] h4, html[dir="RTL"] h5, html[dir="RTL"] th, html[dir="RTL"] td {
  font-family: "IBM Plex Sans Arabic", "Segoe UI", "Tahoma", sans-serif !important;
}

/* A collapsed disclosure arrow points along the reading direction, so in RTL it
   must point LEFT. Only the closed state needs mirroring — the open state is
   `rotate(90deg)`, which points the glyph down and reads the same either way.
   Applied to both the subject and course levels so they stay consistent. */
html[dir="RTL"] .expand-icon:not(.expanded) { display: inline-block; transform: scaleX(-1); }

/* ----------------------------------------------------------------------------
   Cards that were authored for RTL: their accent bar and absolutely-positioned
   icon were pinned to a FIXED side, so in LTR the icon landed on top of the
   text. Re-express both as logical (start/end) so they follow the direction.
   ---------------------------------------------------------------------------- */
.ud-card {
  border-right: none !important;
  border-inline-start: 5px solid #1a237e !important;
}
.ud-card.green  { border-inline-start-color: #2e7d32 !important; }
.ud-card.red    { border-inline-start-color: #c62828 !important; }
.ud-card.orange { border-inline-start-color: #e65100 !important; }
.ud-card.blue   { border-inline-start-color: #1565c0 !important; }
.ud-card.purple { border-inline-start-color: #6a1b9a !important; }
.ud-card.teal   { border-inline-start-color: #00695c !important; }

/* Icon moves to the far side from the text, in BOTH directions */
.ud-card-icon {
  left: auto !important;
  right: auto !important;
  inset-inline-end: 16px !important;
}
@media (max-width: 640px) {
  .ud-card-icon { inset-inline-end: 12px !important; }
}

/* Same pattern anywhere else a card pins its accent to a fixed side */
.chb-card, .stat-card, .kpi-card {
  border-left-width: 0 !important;
  border-inline-start-width: 4px !important;
  border-inline-start-style: solid !important;
}

/* ============================================================================
   RESPONSIVE / MOBILE
   ----------------------------------------------------------------------------
   The custom admin pages were authored for a wide desktop canvas: fixed-column
   grids, wide tables, toolbars in a single row, and modals sized in vw. Below
   the framework's own 874px breakpoint we collapse all of that to one column.

   Everything here is additive — the page stylesheets are untouched, so a page
   keeps its desktop design and only reflows when the screen is actually small.
   ============================================================================ */

/* --- Tablet and phone ----------------------------------------------------- */
@media only screen and (max-width: 874px) {

  /* The fixed-menu script injects an inline-styled spacer next to #menu to
     reserve the sidebar's width, and the framework collapses it with
     `#menu.fixedmenu-fixed.hide + div`. Do NOT loosen that selector: the
     `fixedmenu-fixed` class is what proves the script has actually run and the
     spacer exists. Without it, on a fresh page load (script not run yet) the
     adjacent sibling of #menu is #BODY ITSELF, so the rule collapses the whole
     content column to width:0 — a blank page that "fixes itself" on resize
     (which finally injects the spacer). Keep the class, and never let this
     match #body. */
  #menu.fixedmenu-fixed.hide + div:not(#body) { width: 0 !important; }

  /* Content column: full width, tighter gutters. `width:auto` is restated with
     !important so nothing can collapse it. */
  #body,
  html[dir="RTL"] #body {
    padding: 12px 12px 32px !important;
    width: auto !important;
    min-width: 0;
  }

  /* The drawer overlays the page, so darken what is behind it and let it
     scroll independently. */
  #menu:not(.hide) {
    box-shadow: 0 0 0 100vmax rgba(6, 18, 30, .45);
    max-width: 100%;
  }

  /* Page banners stack: title over its toolbar, both full width. */
  [class*="-header"], .page-header, .ud-header, .schedule-header {
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 10px !important;
    padding: 16px !important;
    text-align: start;
  }
  [class*="-header"] h1, [class*="-header"] h2 { font-size: 20px !important; }
  .header-actions, .header-filters, [class*="-actions"] {
    flex-wrap: wrap !important;
    width: 100% !important;
    gap: 8px !important;
  }
  .header-actions > *, .header-filters > * { flex: 1 1 auto; min-width: 0; }

  /* Any multi-column grid becomes a single column. Covers the stat-card rows,
     form grids and dashboards without naming each page's class.
     EXCEPT grids whose track list is written inline by Vue — the weekly
     timetables (`:style="gridStyle"`) are real 2-D layouts, and collapsing them
     to one column destroys the schedule. They already scroll inside
     `.timetable-grid-container`. */
  .ud-grid, .stats-grid, .cards-grid, .form-grid, .filters-grid,
  [class*="-grid"]:not([style*="grid-template-columns"]),
  [class*="grid-"]:not([style*="grid-template-columns"]) {
    grid-template-columns: 1fr !important;
  }
  /* Stat-card rows pinned to N columns by an inline style attribute, which
     outranks the page's own mobile query. */
  .pm-cards, .fm-cards { grid-template-columns: 1fr !important; }

  /* Toolbars / filter bars stack instead of overflowing sideways. */
  .toolbar, .filters, .filter-bar, [class*="-toolbar"], [class*="-filters"] {
    flex-direction: column !important;
    align-items: stretch !important;
  }
  .toolbar select, .filters select, .filter-select,
  input[type="text"], input[type="search"], input[type="number"], select {
    max-width: 100% !important;
  }

  /* A <select> is laid out to fit its LONGEST OPTION, and a flex item defaults
     to `min-width: auto` (its min-content), so one long option can push a
     filter bar clean past the screen — `max-width: 100%` cannot save it because
     the parent is itself content-sized. Let both actually shrink. */
  select, input, textarea { min-width: 0 !important; }
  [class*="filter-item"], [class*="filter-group"], [class*="filter-field"] {
    min-width: 0 !important;
    flex: 1 1 100% !important;
  }
  [class*="filter-item"] > select, [class*="filter-group"] > select,
  [class*="filter-item"] > input,  [class*="filter-group"] > input {
    width: 100% !important;
  }

  /* Wide tables scroll inside their own container instead of stretching the
     page. `-webkit-overflow-scrolling` keeps the momentum feel on iOS. */
  .table-wrapper, .table-container, [class*="table-wrap"],
  [class*="-table-wrapper"], .data-table-wrapper {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
  }
  table { max-width: none; }

  /* Modals: near-full-screen sheets rather than fixed-width dialogs. */
  .modal-content, [class*="modal-content"], [class*="-modal"] .modal-content {
    width: 96vw !important;
    max-width: 96vw !important;
    max-height: 88vh !important;
    overflow-y: auto !important;
  }

  /* Cards and panels lose their desktop minimums. */
  .card, .panel, [class*="-card"], [class*="-panel"] { min-width: 0 !important; }
}

/* --- Phone ---------------------------------------------------------------- */
@media only screen and (max-width: 560px) {

  /* App bar: let the module buttons scroll horizontally rather than wrap into
     a tall stack, and keep the row compact. The hamburger, language toggle and
     logout stay reachable because the strip scrolls. */
  #footerwrap {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap !important;
    scrollbar-width: none;
  }
  #footerwrap::-webkit-scrollbar { display: none; }
  #footerwrap .BottomButton {
    flex: 0 0 auto;
    padding-inline: 10px !important;
  }
  /* Labels off, icons only — the bar has ~11 destinations. */
  #footerwrap .BottomButton > span { display: none !important; }
  /* …except the language toggle, whose whole affordance IS its label. */
  #BottomButtonLang > span { display: inline !important; font-size: 12px; }

  #body, html[dir="RTL"] #body { padding: 10px 10px 28px !important; }

  /* Headline sizes that were tuned for a 1400px canvas. */
  [class*="-header"] h1, [class*="-header"] h2 { font-size: 18px !important; }
  h1 { font-size: 20px; }
  h2 { font-size: 18px; }

  /* Stat numbers shrink so a 4-up row reads on one column. */
  .ud-card-value, .stat-value, [class*="-value"] { font-size: 24px !important; }

  /* Buttons become comfortably tappable and stop overflowing their row. */
  button, .btn, .action-btn, [class*="-btn"] {
    min-height: 40px;
    max-width: 100%;
  }

  /* Tabs scroll instead of wrapping into several rows. */
  .tabs, [class*="-tabs"] {
    display: flex !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
    flex-wrap: nowrap !important;
  }
  .tabs > *, [class*="-tabs"] > * { flex: 0 0 auto; }
}

/* ============================================================================
   RESPONSIVE — page-specific fixes
   ----------------------------------------------------------------------------
   Found by auditing every admin page and shared stylesheet at 375px, then
   adversarially verifying each one against the source (83 candidates -> 39
   confirmed). Each rule below is something the blanket rules above genuinely
   cannot reach: a table with no wrapper element, a modal with no class, an
   inline `min-width`, a flex row whose children set a min-content floor, or an
   action that is only revealed on :hover.
   ============================================================================ */
@media only screen and (max-width: 874px) {

  /* --- Wide tables that have NO scrollable wrapper in the markup ------------
     `display: block` turns the table itself into the scroll container; the
     internal row/cell boxes are preserved by the anonymous table box. */
  #student-transcript-app .transcript-table,
  .grad-table,
  table.chb-table,
  table.chb-rates,
  .transfer-page .transfers-table,
  .rm-page .rm-grade-table,
  #elective-groups-app .ce-card-body > table,
  #graduation-app table.gpa-table {
    display: block !important;
    max-width: 100% !important;
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
  }
  /* Let the frozen header text wrap rather than force the table wider. */
  .grad-table th { white-space: normal; }
  /* The rate table's column widths are inline percentages. */
  table.chb-rates th, table.chb-rates td { width: auto !important; min-width: 110px; }
  table.chb-rates th:first-child, table.chb-rates td:first-child { min-width: 170px; }
  table.chb-rates th:last-child,  table.chb-rates td:last-child  { min-width: 44px; }

  /* Containers that clip (overflow:hidden) instead of scrolling their table. */
  #semester-results-app .transcript-section,
  .bulk-reg-page .students-table-container,
  .student-grades-page .course-body,
  #universityDashboardApp .ud-ann-box,
  #universityDashboardApp .ud-ann-box .ud-chart-box,
  #user-management-app .report-content,
  #user-management-app .info-card {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
  }
  #profile-mgmt-app .permission-matrix { overflow: visible; }
  #profile-mgmt-app .group-pages { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  #profile-mgmt-app .matrix-table { min-width: 480px; }

  /* Sticky columns stop making sense once the table scrolls horizontally. */
  .semester-results-container .actions-col,
  .semester-results-container .student-col { position: static !important; left: auto !important; }

  /* --- Hand-rolled modals with inline styles and no class ------------------ */
  #registration-profile-app > div[style*="position: fixed"] {
    align-items: flex-start !important;
    overflow-y: auto !important;
    padding: 12px !important;
    -webkit-overflow-scrolling: touch;
  }
  #registration-profile-app > div[style*="position: fixed"] > div {
    width: 100% !important;
    max-width: 100% !important;
    padding: 16px !important;
  }

  /* --- Inline min-widths that outrank every stylesheet --------------------- */
  #gpa-profile-app .gpa-rounding-decimals {
    min-width: 0 !important;
    width: 100%;
    flex-wrap: wrap;
  }
  #gpa-profile-app .gpa-rounding-decimals > .gpa-select {
    min-width: 0 !important;
    flex: 1 1 100%;
  }
  .transfer-page .searchable-select,
  .transfer-page .mapping-select { min-width: 0 !important; width: 100% !important; }

  /* A grid child still asking to span 2 tracks after the grid became 1 column
     makes CSS Grid invent a second implicit track. */
  #registration-profile-app .rp-gpa-grid > .rp-field[style*="span 2"] {
    grid-column: 1 / -1 !important;
    min-width: 0;
  }

  /* --- Flex rows whose children set a min-content floor -------------------- */
  .course-banner {
    flex-wrap: wrap !important;
    gap: 10px;
    padding: 14px 16px;
  }
  .course-banner .course-info-section { flex: 1 1 100%; }
  .course-banner .course-title { font-size: 18px; }
  .banner-actions { flex: 1 1 100%; }
  .banner-actions > * { flex: 1 1 auto; }

  #control-profile-app .cp-chip-group { flex-wrap: wrap; flex: 1 1 100%; }
  #control-profile-app .cp-chip-input { min-width: 0; flex: 1 1 120px; width: auto !important; }

  #moodleSyncApp .ms-pipeline { padding: 14px; }
  #moodleSyncApp .ms-step { flex-wrap: wrap; gap: 10px; padding: 12px; }
  #moodleSyncApp .ms-step-info { flex: 1 1 100%; min-width: 0; }
  #moodleSyncApp .ms-step code { word-break: break-all; }

  .rm-page .rm-time-slicer-inputs { flex-wrap: wrap !important; }
  .rm-page .rm-time-slicer-inputs input[type="datetime-local"] {
    flex: 1 1 100% !important;
    min-width: 0 !important;
  }

  /* The registration screen is a two-pane desktop layout. */
  .registration-page .main-content { flex-direction: column !important; }
  .registration-page .courses-panel {
    width: 100% !important;
    max-width: 100% !important;
    position: static !important;
    max-height: 55vh !important;
  }

  .students-page .pagination { flex-direction: column !important; align-items: stretch !important; gap: 10px; }
  .students-page .pagination-buttons { flex-wrap: wrap !important; justify-content: center; }

  /* A fixed 30px row cannot hold the 40px tap targets set for phones below. */
  .filter-item.action { height: auto !important; min-height: 40px; }

  /* --- Touch reachability --------------------------------------------------
     The timetable slot actions (split / edit / delete) were revealed only on
     :hover, so on a touch screen they were unreachable and the schedule was
     effectively read-only. */
  .course-period-card .cp-actions {
    display: flex !important;
    position: static !important;
    justify-content: flex-end;
    margin-top: 6px;
  }
  .cp-action-btn { width: 34px !important; height: 34px !important; font-size: 15px; }

  /* Semester Results: the sort bar is `flex-wrap: nowrap` holding a label, a
     select with `min-width: 130px` and a 177px button group — ~386px of
     min-content against a 375px screen. Its parent does not scroll, so the
     surplus was CLIPPED and the sort-direction buttons were unreachable. */
  .semester-results-container .sort-controls-enhanced { flex-wrap: wrap !important; }
  .semester-results-container .sort-select {
    min-width: 0 !important;
    flex: 1 1 100% !important;
  }
  .semester-results-container .sort-direction-btns {
    flex: 1 1 100% !important;
    display: flex;
  }
  .semester-results-container .sort-direction-btns > * { flex: 1 1 auto; }

  /* Charts with a per-day bar keep a usable minimum and scroll. */
  #activity-logs-app .chart-container {
    margin: 0 10px 16px;
    padding: 12px;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  #activity-logs-app .bar-chart, #activity-logs-app .bar-labels { min-width: 330px; }
}

/* ============================================================================
   PHONE — tables become stacked cards
   ----------------------------------------------------------------------------
   A horizontally scrolling table is a poor way to read records on a phone, so
   each row becomes a card of "Label: value" pairs.

   The `sis-cards` class is added by assets_new/codes/mobile-tables.js, and ONLY
   after it has copied every column's <th> text onto the cells below it. That
   ordering matters: card mode without labels (which is what data-table.css did
   on pages that never wrote `data-label`) renders an unlabelled pile of values.
   A table the script cannot label keeps its horizontal scroll instead.
   ============================================================================ */
@media only screen and (max-width: 768px) {

  table.sis-cards,
  table.sis-cards tbody,
  table.sis-cards tr,
  table.sis-cards td {
    display: block !important;
    width: auto !important;
    max-width: none !important;
  }
  /* The header is now printed per-cell, so the header row is redundant. */
  table.sis-cards thead { display: none !important; }

  table.sis-cards { border-collapse: separate; border-spacing: 0; overflow: visible !important; }

  table.sis-cards tr {
    background: #fff;
    border: 1px solid #e3e8ee !important;
    border-radius: 10px;
    box-shadow: 0 1px 3px rgba(20, 41, 63, .06);
    margin: 0 0 10px !important;
    padding: 6px 12px !important;
  }
  table.sis-cards tr:hover { background: #fff; }

  table.sis-cards td {
    display: flex !important;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 7px 0 !important;
    border: 0 !important;
    border-bottom: 1px solid #f1f4f8 !important;
    text-align: start !important;
    white-space: normal !important;
    min-width: 0;
  }
  table.sis-cards tr td:last-child { border-bottom: 0 !important; }

  /* The label the script copied off the column header. */
  table.sis-cards td::before {
    content: attr(data-label);
    flex: 0 0 42%;
    font-weight: 600;
    font-size: 12px;
    color: #5b6673;
    text-align: start;
  }
  /* A cell with no label (extra/action column) spans the full card width. */
  table.sis-cards td:not([data-label])::before { content: none; }
  table.sis-cards td:not([data-label]) { justify-content: flex-end; }

  /* Actions inside a card should be reachable, not crammed. */
  table.sis-cards td button,
  table.sis-cards td .btn,
  table.sis-cards td a.btn { min-height: 34px; }

  /* A "no results" row spanning the table stays a plain centred line. */
  table.sis-cards td[colspan] { justify-content: center; }
  table.sis-cards td[colspan]::before { content: none; }

  /* Once a table is a card list it must not also try to scroll sideways. */
  table.sis-cards { overflow-x: visible !important; }
}

/* Phone-only: nested container padding was eating ~42px of a 375px screen. */
@media only screen and (max-width: 560px) {
  [class*="-container"], [class*="-page"] {
    padding-left: 10px !important;
    padding-right: 10px !important;
  }
  .modal-content .results-summary,
  .bulk-reg-page .results-summary { grid-template-columns: repeat(2, 1fr) !important; }

  /* Semester Results is designed as a dense PRINTED sheet: its content scale
     runs 0.6–0.75rem (≈10–12px), which is fine on paper and unreadable on a
     phone. Lift the content classes to 12px. Scoped to this container and to
     phones only, and it lists the small classes explicitly so headings and
     totals keep their own larger sizes. */
  .semester-results-container .course-name,
  .semester-results-container .subject-name,
  .semester-results-container .course-code,
  .semester-results-container td,
  .semester-results-container th,
  .semester-results-container small,
  .semester-results-container .badge {
    font-size: 12px !important;
  }
}
