/**
 * Twine app shell
 *
 * Restyles the authorised app chrome (sidebar, top/bottom bars, cards,
 * tables, buttons) to the Twine dashboard design from design/new.html:
 * soft slate background, white sidebar, teal accent, Plus Jakarta Sans.
 *
 * Loaded from Warehouse.php as a <link> AFTER the active theme stylesheet,
 * so it overrides the WPadmin base (imported by every WPadmin-* theme)
 * regardless of the selected theme. Everything is scoped under body.modules
 * so only authorised pages are affected — the login page is untouched.
 *
 * @package RosarioSIS
 * @subpackage Twine
 */

body.modules {
	--pri: #0e7490;        /* teal */
	--pri-deep: #0b5c73;
	--pri-soft: #e0f2fe;
	--bg: #eef1f5;
	--card: #ffffff;
	--line: #e4e9ef;
	--line-soft: #eef2f6;
	--ink: #0f172a;
	--ink-mid: #475569;
	--ink-soft: #64748b;
	--ink-faint: #94a3b8;
	--label: #b3bcc9;
	--hover: #f3f6f9;
	--field: #f8fafc;
	--field-line: #dce3ea;
	--tab-active: #1e40af; /* dark blue — active tab underline/label */
	--pane-pad: 26px;      /* content-pane side gutter; header full-bleeds past it */
	--field-h: 36px;       /* single-line field height (input = its click-to-edit text) */

	background: var(--bg);
	font-family: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
	color: var(--ink);
}

/* Always keep the vertical scrollbar present/reserved so the viewport width
   never changes between scroll positions — otherwise the pinned full-bleed
   header (sized from #body's width) jumps horizontally by the scrollbar width
   when the scrollbar toggles on scroll. (This file only loads on app pages.) */
html {
	/* Paint the root/canvas gray too: on a tall page the <body> box can be
	   shorter than the scroll height, and scrolling past it would otherwise
	   reveal the white canvas below. Gray on <html> fills the whole scroll.
	   Literal (not var(--bg)): --bg is defined on body.modules, which <html>
	   — its parent — cannot inherit. Keep this in sync with --bg. */
	background: #eef1f5;
	overflow-y: scroll;      /* always show the scrollbar (broad support) */
	scrollbar-gutter: stable; /* + reserve its gutter where supported */
}

/* Use the UI font for the serif header cells the base theme sets. */
body.modules .postbox > thead th,
body.modules .widefat th,
body.modules .header1 h2,
body.modules h1,
body.modules h2,
body.modules h3 {
	font-family: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
}

/* =====================================================
   SIDEBAR
   ===================================================== */
body.modules #menuback,
body.modules #menu {
	width: 256px;
	background: var(--card);
	border-right: 1px solid var(--line);
	background-image: none;
}

body.modules #menushadow {
	display: none;
}

body.modules #menu-top {
	padding: 4px 4px 8px;
}

/* Brand block (teal tile + wordmark) replacing the logo image. */
body.modules .twine-brand {
	display: flex;
	align-items: center;
	gap: 11px;
	padding: 16px 16px 6px;
	text-decoration: none;
}

body.modules .twine-brand-mark {
	width: 42px;
	height: 42px;
	flex: none;
	border-radius: 12px;
	background: linear-gradient(135deg, #22b8cf, #0e7490);
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 2px 8px rgba(14, 116, 144, .28);
}

body.modules .twine-brand-mark svg {
	width: 25px;
	height: 25px;
}

body.modules .twine-brand-name {
	font-size: 19px;
	font-weight: 800;
	letter-spacing: -.02em;
	color: var(--pri);
	line-height: 1.05;
}

body.modules #menu form {
	padding: 0 12px;
	text-align: left;
}

body.modules #menu .username {
	display: block;
	font-size: 13.5px;
	font-weight: 700;
	color: #1e293b;
	letter-spacing: -.01em;
}

body.modules #menu .today-date {
	display: block;
	font-size: 11.5px;
	font-weight: 600;
	color: var(--ink-faint);
	margin-bottom: 10px;
}

body.modules #menu select {
	box-sizing: border-box;
	width: 100%;
	height: 34px;
	margin: 3px 0;
	padding: 0 10px;
	line-height: 32px;
	border: 1px solid var(--field-line);
	border-radius: 8px;
	background-color: var(--field);
	font: 600 12px 'Plus Jakarta Sans', sans-serif;
	color: #334155;
	cursor: pointer;
}

body.modules .current-person {
	margin: 6px 12px;
	padding: 8px 11px;
	border-radius: 9px;
	background: var(--hover);
	font-size: 12.5px;
}

body.modules .current-person a {
	color: var(--ink-mid);
}

/* nav ------------------------------------------------- */
body.modules .adminmenu {
	background: transparent;
	padding: 6px 8px 20px;
}

body.modules .adminmenu a {
	padding: 2px 6px;
	line-height: 1.4;
}

body.modules .menu-module {
	margin-bottom: 5px;
}

/* Top-level module row. */
body.modules .menu-top {
	display: block;
	border: 0;
	border-radius: 9px;
	padding: 9px 11px;
	min-width: 0;
	font-size: 13px;
	font-weight: 700;
	color: var(--ink-mid);
	background-image: none;
	transition: background .12s, color .12s;
}

body.modules .menu-top img {
	height: 20px;
	width: 20px;
	object-fit: contain;
	margin-right: 6px;
}

body.modules .menu-top:hover,
body.modules .menu-top:focus {
	background: var(--hover);
	background-image: none;
	color: var(--ink);
}

/* Active module. */
body.modules #selectedModuleLink.menu-top {
	color: var(--ink);
}

/* Submenu (inline for the active module, fly-out on hover for others). */
body.modules .wp-submenu {
	background: var(--card);
	border: 0;
	padding: 2px 0 6px;
}

/* The sidebar scrolls independently, so its overflow would clip an
   absolutely-positioned fly-out. Hide the base CSS hover fly-out; twine-app.js
   re-shows it as a fixed .twine-flyout that sits ON TOP of the content.
   NB: no `.no-touch` prefix — that class lives on <html> (an ancestor of
   <body>), so a `body.modules .no-touch …` selector would never match. */
body.modules .menu-module:hover > .wp-submenu:not(.twine-flyout) {
	top: -1000em !important;
	left: -9999px !important;
}

/* Keep the active module's inline submenu visible on hover. */
body.modules #selectedModuleLink + .wp-submenu {
	top: 0 !important;
	left: 0 !important;
}

/* JS-driven fly-out: fixed so it escapes the scrolling sidebar and floats
   above the content. Its `left`/`top` are set inline by twine-app.js (with
   containing-block offset correction) to line up with the hovered module. */
body.modules .wp-submenu.twine-flyout {
	position: fixed !important;
	/* Base .wp-submenu has `transition-delay:.15s` on top/left, which defers
	   our positioning by 150ms (and makes getComputedStyle read stale). */
	transition: none !important;
	width: 222px !important;
	min-width: 0 !important;
	max-height: calc(100vh - 24px);
	overflow-y: auto;
	overflow-x: hidden;
	padding: 6px;
	border: 1px solid var(--line);
	border-radius: 12px;
	background: var(--card);
	box-shadow: 0 18px 44px -18px rgba(15, 23, 42, .32);
	z-index: 99998;
}

/* Inline submenu under the active module: left guide rail. */
body.modules #selectedModuleLink + .wp-submenu {
	margin: 2px 0 8px 14px !important;
	padding-left: 8px;
	border-left: 2px solid var(--line-soft);
	border-radius: 0;
}

body.modules .wp-submenu a {
	margin: 0;
	padding: 6px 11px;
	border-radius: 8px;
	font-size: 12.5px;
	font-weight: 600;
	color: var(--ink-soft);
	background-image: none;
}

body.modules .wp-submenu a:hover {
	background: var(--hover);
	color: var(--ink);
}

/* Current page in the submenu. */
body.modules #selectedMenuLink {
	background: var(--pri-soft) !important;
	color: var(--pri) !important;
	font-weight: 700;
}

/* Section separators inside a submenu (numeric menu keys). */
body.modules .menu-inter {
	border: 0;
	padding: 8px 11px 4px;
	font-size: 10px;
	font-weight: 800;
	letter-spacing: .07em;
	text-transform: uppercase;
	color: var(--label);
}

/* =====================================================
   INDEPENDENT-SCROLL SIDEBAR (desktop / tablet ≥ 737px)
   The sidebar is a fixed, full-height column with its own scrollbar,
   decoupled from the main content scroll. Below 737px the base theme's
   stacked/toggled mobile menu takes over (this block does not apply).
   ===================================================== */
@media only screen and (min-width: 737px) {
	body.modules #menu {
		position: fixed;
		top: 0;
		left: 0;
		bottom: 0;
		width: 256px;
		float: none;
		overflow-y: auto;
		overflow-x: hidden;
		padding-bottom: 16px;
		z-index: 30;
		overscroll-behavior: contain;
	}

	/* Background strip is redundant now the fixed sidebar has its own bg. */
	body.modules #menuback {
		display: none;
	}

	/* Main content clears the fixed sidebar and scrolls on its own. */
	body.modules #body {
		margin-left: 256px;
		transition: margin-left .2s ease;
	}

	/* Bottom bar spans only the content area, next to the sidebar. */
	body.modules #footer {
		left: 256px;
		width: calc(100% - 256px);
		transition: left .2s ease, width .2s ease;
	}

	/* Sidebar toggled off (footer Menu button adds .hide to #menu): reclaim its
	   256px so the content pane and bottom bar stretch to the full window width. */
	body.modules:has(#menu.hide) #body {
		margin-left: 0;
	}

	body.modules:has(#menu.hide) #footer {
		left: 0;
		width: 100%;
	}

	/* Slim, unobtrusive sidebar scrollbar. */
	body.modules #menu::-webkit-scrollbar {
		width: 8px;
	}
	body.modules #menu::-webkit-scrollbar-thumb {
		background: #d5dbe3;
		border-radius: 8px;
	}
	body.modules #menu {
		scrollbar-width: thin;
		scrollbar-color: #d5dbe3 transparent;
	}
}

/* =====================================================
   CONTENT AREA
   ===================================================== */
body.modules #body {
	padding: 22px var(--pane-pad) 46px;
	background: transparent;
	/* #body carries class="mod" (.mod { overflow: hidden }), which turns it
	   into a scroll container so the sticky header pins to #body (which never
	   scrolls) instead of the viewport — i.e. it scrolls away. flow-root still
	   contains floats but is NOT a scroll container, so sticky reaches the
	   viewport. */
	overflow: visible;
	display: flow-root;
}

/* Page header (title + module icon tile). */
body.modules .header1 h2 {
	display: flex;
	align-items: center;
	gap: 12px;
	margin: 0;
	padding: 10px 0 12px;
	font-size: 22px;
	font-weight: 800;
	letter-spacing: -.02em;
	color: var(--ink);
	text-shadow: none;
}

body.modules .header1 .headerIcon {
	box-sizing: content-box;
	width: 22px;
	height: 22px;
	padding: 8px;
	border-radius: 11px;
	background: var(--pri-soft);
	vertical-align: middle;
}

/* Person header (design/new.html): program title over a name · ID subtitle,
   with a copy-to-clipboard button by the ID. Lives inside .header1 h2. */
body.modules .header1 h2 .header-textcol {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

body.modules .header-title {
	font-size: 21px;
	font-weight: 800;
	letter-spacing: -.02em;
	line-height: 1.05;
	color: var(--ink);
}

body.modules .header-person {
	display: flex;
	align-items: center;
	gap: 7px;
	margin-top: 3px;
	font-size: 13px;
	font-weight: 600;
	color: #7c899a;
}

body.modules .header-person .header-sep {
	color: #c4ccd6;
}

/* Copy-to-clipboard icon button next to the ID. */
body.modules .twine-copy {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	padding: 0;
	border: 0;
	border-radius: 6px;
	background: none;
	color: var(--ink-soft);
	cursor: pointer;
	transition: background .12s, color .12s;
}

body.modules .twine-copy:hover {
	background: var(--hover);
	color: var(--pri);
}

body.modules .twine-copy svg {
	width: 15px;
	height: 15px;
}

body.modules .twine-copy.copied {
	color: #16a34a; /* brief green confirmation */
}

body.modules .header2 {
	padding: 4px 2px 10px;
}

/* Secondary header bars (.header2 rows: the Save button, view-toggle links like
   "Expanded View | Group by Family", the "Include Inactive" toggle, …) render as
   white rounded cards app-wide (same language as .postbox). The Portal greeting
   opts out via the .tw-welcome reset below. */
body.modules #body table.header:has(td.header2):not(.tw-welcome *) {
	background: var(--card);
	border: 1px solid #e6ebf1;
	border-radius: 14px;
	box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
	margin: 4px 0 14px;
}

body.modules #body table.header:has(td.header2):not(.tw-welcome *) td.header2 {
	padding: 11px 16px;
	vertical-align: middle;
	/* Base theme (colors.css) paints .header2 #f9f9f9, which would cover the
	   card's white rounded background — clear it so the card shows through. */
	background: transparent;
}

/* Portal welcome greeting — wrap the salute + welcome lines in a white card
   (same language as .postbox: soft border, 14px radius, subtle shadow). */
body.modules .tw-welcome {
	background: var(--card);
	border: 1px solid #e6ebf1;
	border-radius: 14px;
	box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
	padding: 20px 24px;
	margin: 4px 0 18px;
	color: var(--ink-mid);
	line-height: 1.55;
}

/* The greeting is two DrawHeader tables (.header2) inside its own .tw-welcome
   card — flatten them and opt out of the secondary-header card styling above
   (#body raises specificity to beat that rule, which also targets #body). */
body.modules #body .tw-welcome table.header,
body.modules #body .tw-welcome .header2 {
	width: auto;
	margin: 0;
	padding: 0;
	background: none;
	border: 0;
	box-shadow: none;
	border-radius: 0;
}

body.modules .tw-welcome #salute {
	display: block;
	margin-bottom: 8px;
	font-size: 20px;
	font-weight: 700;
	color: var(--ink);
}

body.modules .tw-welcome b {
	font-weight: 700;
	color: var(--ink);
}

/* Primary header (title + Save) — a full-width white bar pinned to the top,
   so the whole header (title + tab row below it) stays put while the page
   scrolls (design/new.html). It full-bleeds past the #body gutter so it spans
   the whole content pane edge-to-edge, then re-insets its own contents.
   Scoped to the primary header via .header1 so secondary (.header2) headers
   keep flowing normally. */
body.modules #body table.header:has(.header1) {
	position: sticky;
	top: 0;
	z-index: 21;
	box-sizing: border-box;
	width: calc(100% + 2 * var(--pane-pad));
	margin: -22px calc(-1 * var(--pane-pad)) 0;
	padding: 0 var(--pane-pad);
	background: var(--card);
	border-bottom: 1px solid var(--line);
}

/* Drop the <br> the page prints between the title bar and the tab card, so
   the two pinned bars sit flush. */
body.modules #body table.header:has(.header1) + br {
	display: none;
}

/* Cards -------------------------------------------------*/
body.modules .postbox {
	background: var(--card);
	border: 1px solid #e6ebf1;
	border-bottom-width: 1px;
	border-radius: 14px;
	box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
	overflow: hidden;
	margin-bottom: 18px;
}

body.modules .postbox > thead th {
	background: var(--card);
	background-image: none;
	border-bottom: 1px solid var(--line-soft);
	padding: 4px 16px;
	color: var(--ink);
}

body.modules .postbox th h3,
body.modules .postbox th h3 a {
	font-size: 15px;
	font-weight: 700;
	color: var(--ink);
}

/* Titled (non-tabbed) PopTable body — the "Permissions" box on Staff Profiles /
   Staff Permissions, the search form's Widgets / User Fields boxes: the base
   theme pads .popTable a bare 5px, which reads as no inset at all inside a
   14px-radius card. Give the content a proper card inset. (Tabbed PopTables
   are the flattened sheet of the TABBED HEADER section below and keep their
   own padding.) */
body.modules #body .postbox:not(:has(.h3multi)) td.popTable {
	padding: 16px 18px;
}

/* =====================================================
   TABBED HEADER (Student Info & co.) — design/new.html
   PopTable('header', $tabs) puts the tab menu in a card <thead>:
   a .h3multi row of <h3> tabs (active = .h3selected; linked tabs wrap
   an <a>). Make it a fully-white bar pinned to the top, tabs left-
   aligned, with the active tab underlined in dark blue and the inactive
   ones bare.
   ===================================================== */

/* Flatten the tab card into a full-width header band: full-bleed past the
   #body gutter, no card border/shadow. overflow:visible also frees the sticky
   tab row (a card's overflow:hidden would trap it in its own non-scrolling
   box and it would never pin).
   Scoped to PopTable('header') tabs ONLY via :has(> tbody > tr > td.popTable):
   ListOutput's $options['header'] tabs (e.g. Gradebook's All/assignment-type
   row) sit in a thead-only .postbox table above the list — those are mid-page
   tabs and must NOT be pinned to the top or full-bled. */
body.modules .postbox:has(.h3multi):has(> tbody > tr > td.popTable) {
	overflow: visible;
	box-sizing: border-box;
	width: calc(100% + 2 * var(--pane-pad));
	margin: 0 calc(-1 * var(--pane-pad)) 18px;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	background: transparent;
}

/* Pin the tab row just under the title bar while the body scrolls under it.
   --twine-hdr-h is the measured title-bar height (set by twine-app.js). Tabs
   are inset to the pane gutter so they line up with the content below. */
body.modules .postbox:has(.h3multi):has(> tbody > tr > td.popTable) > thead > tr > th {
	position: sticky;
	top: var(--twine-hdr-h, 52px);
	z-index: 20;
	padding: 0 var(--pane-pad);
	text-align: left;
	background: var(--card);
	border-bottom: 1px solid var(--line);
}

/* Tab body: white sheet, contents re-inset to the pane gutter. */
body.modules .postbox:has(.h3multi) > tbody > tr > td.popTable {
	padding: 22px var(--pane-pad);
	background: var(--card);
}

/* Mid-page ListOutput tabs (thead-only .postbox — e.g. Gradebook's
   All/assignment-type row above the student list): the tab table and the list
   wrapper div.postbox after it are two separate boxes that must read as ONE
   card — square the tab card's bottom corners and drop its shadow so it fuses
   with the list sheet below (which already ships inline square top corners,
   no top border and no shadow). */
body.modules #body table.postbox:has(.h3multi):not(:has(> tbody > tr > td.popTable)) {
	border-bottom-left-radius: 0;
	border-bottom-right-radius: 0;
	box-shadow: none;
}

/* ...and give the list sheet a real card inset (ListOutput hardcodes an inline
   padding:5px on the wrapper, hence the !important). */
body.modules #body table.postbox:has(.h3multi):not(:has(> tbody > tr > td.popTable)) + div.postbox {
	padding: 14px 16px !important;
}

/* Tab row: flat, left-aligned text tabs like the mockup. */
body.modules .h3multi {
	display: flex;
	gap: 4px;
	overflow: visible;
}

body.modules .h3multi h3 {
	height: auto;
	margin: 0 0 -1px; /* let the underline overlap the header's bottom rule */
	border: 0;
	border-bottom: 2.5px solid transparent; /* underline slot (bare when inactive) */
	background: none; /* drop the base gray gradient on the active tab */
}

body.modules .h3multi h3,
body.modules .h3multi h3 a {
	display: block;
	font-size: 14px;
	font-weight: 700;
	line-height: 1.2;
	color: var(--ink-soft);
}

body.modules .h3multi h3 a,
body.modules .h3multi h3:not(:has(a)) {
	padding: 13px 6px;
}

/* Active tab: dark-blue underline + dark-blue label. */
body.modules .h3multi h3.h3selected {
	border-bottom-color: var(--tab-active);
}

body.modules .h3multi h3.h3selected,
body.modules .h3multi h3.h3selected a {
	color: var(--tab-active);
}

/* Hover feedback on inactive tabs. */
body.modules .h3multi h3:not(.h3selected):hover,
body.modules .h3multi h3:not(.h3selected):hover a {
	color: var(--ink);
}

/* Data tables ------------------------------------------*/
body.modules .widefat {
	background: var(--card);
	border: 1px solid #e6ebf1;
	border-radius: 12px;
	overflow: hidden;
}

body.modules .widefat th,
body.modules .widefat tfoot tr th {
	background: var(--field);
	background-image: none;
	font-size: 11.5px !important;
	font-weight: 700;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--ink-soft);
	line-height: 1.5em;
}

body.modules .widefat th a {
	font-size: 11.5px;
	color: var(--ink-soft);
}

body.modules .widefat tr:nth-child(odd),
body.modules .alternate,
body.modules .alt {
	background: #fbfcfe;
}

body.modules .widefat tr:nth-child(even) {
	background: var(--card);
}

body.modules .widefat tr.highlight,
body.modules .widefat tr:hover {
	background: var(--hover);
}

/* List rows with editable inputs are tall, but the base squares every cell to
   vertical-align:top — so the lone icon in the first column rides high. Center
   the icon cells vertically against the row: the delete link (svg inside an <a>)
   on data rows, and the bare "+" add-icon svg on the add row. */
body.modules #body table.list td:has(> a[href*="modfunc=remove"]),
body.modules #body table.list td:has(> svg.button) {
	vertical-align: middle;
}

/* =====================================================
   BUTTONS
   ===================================================== */
/* Inline SVG icon buttons (e.g. button('x')): fixed 17x17, overriding the
   base .button / .button.bigger heights so the cross stays square. */
body.modules svg.button {
	width: 17px !important;
	height: 17px !important;
	vertical-align: middle;
}

/* Calendar trigger: a <span class="button cal"> wrapping an inline SVG. The
   wrapper must be an HTML element so jscalendar can read its offset* to place
   the popup (a bare <svg> exposes none, dropping the popup at 0,0). Reset the
   base .button.cal (img) sizing and size the inner icon. */
body.modules span.button.cal {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: auto;
	height: auto !important; /* override base .button.cal { height: 32px } */
	margin: 0 0 0 2px;
	padding: 0;
	vertical-align: middle;
	color: var(--ink-mid);
	cursor: pointer;
}

body.modules span.button.cal:hover {
	color: var(--pri);
}

body.modules span.button.cal svg {
	width: 19px;
	height: 19px;
}

/* jscalendar popup: appended to <body> with an inline position:absolute but no
   z-index (calendar-blue.css only sets position:relative). The sticky page
   header (z-index 21) and fixed sidebar (z-index 30) are opaque and paint over
   its top rows when it opens near them. Lift it above those layers — but below
   the modal/colorbox stack (z-index 100000) — so the whole calendar shows. */
body.modules div.calendar {
	z-index: 9999;
}

body.modules input[type=submit],
body.modules input[type=reset],
body.modules input[type=button],
body.modules a.button-primary,
body.modules button.button-primary,
body.modules input.button-primary {
	border-radius: 9px;
}

/* Secondary / default buttons. */
body.modules input[type=submit],
body.modules input[type=reset],
body.modules input[type=button] {
	background: var(--card);
	background-image: none;
	border: 1px solid var(--field-line);
	color: #334155;
	font-weight: 700;
	box-shadow: none;
}

body.modules input[type=submit]:hover,
body.modules input[type=reset]:hover,
body.modules input[type=button]:hover {
	background: var(--hover);
}

/* Primary buttons -> teal. */
body.modules input.button-primary,
body.modules button.button-primary,
body.modules a.button-primary {
	background: var(--pri);
	background-image: none;
	border-color: var(--pri-deep);
	color: #fff;
	font-weight: 700;
	text-shadow: none;
	box-shadow: 0 2px 8px rgba(14, 116, 144, .25);
}

body.modules input.button-primary:hover,
body.modules button.button-primary:hover,
body.modules a.button-primary:hover,
body.modules input.button-primary:focus,
body.modules button.button-primary:focus,
body.modules a.button-primary:focus {
	background: var(--pri-deep);
	background-image: none;
	color: #fff;
}

/* Save button in the header carries the mockup's disk icon (SubmitButton() is
   an <input>, so the glyph rides in as a left-aligned background image; the
   teal background-color set above is preserved). */
body.modules .header1 input[type=submit] {
	background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23fff%22%20stroke-width%3D%222%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M19%2021H5a2%202%200%200%201-2-2V5a2%202%200%200%201%202-2h11l5%205v11a2%202%200%200%201-2%202Z%22%2F%3E%3Cpath%20d%3D%22M17%2021v-8H7v8M7%203v5h8%22%2F%3E%3C%2Fsvg%3E");
	background-repeat: no-repeat;
	background-position: 15px center;
	background-size: 16px 16px;
	padding-left: 39px;
}

/* Form fields (design/new.html) — text inputs, textareas, selects.
   Applied project-wide to authorised content (#body). */
body.modules #body input[type=text],
body.modules #body input[type=password],
body.modules #body input[type=email],
body.modules #body input[type=number],
body.modules #body input[type=search],
body.modules #body input[type=tel],
body.modules #body input[type=url],
body.modules #body input[type=date],
body.modules #body input[type=time],
body.modules #body textarea {
	box-sizing: border-box;
	padding: 8px 11px;
	border: 1px solid var(--field-line);
	border-radius: 8px;
	background: var(--card);
	font-family: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
	font-size: 13.5px;
	font-weight: 500;
	color: var(--ink);
	outline: none;
	transition: border-color .12s, box-shadow .12s;
}

body.modules #body textarea {
	padding: 11px 13px;
	line-height: 1.5;
	resize: vertical;
}

/* Custom student field CUSTOM_60 (long text): 90% width. */
body.modules #body #studentsCUSTOM_60 {
	width: 90%;
	min-width: 0;
}

/* School Setup > Calendar: the per-day "Minutes" inputs are emitted at size=3,
   which the base input padding (8/11px) squeezes down to ~1 visible digit.
   Give them a fixed width wide enough for the full 3-digit value. */
body.modules #body input[type=text][name^="minutes"],
body.modules #body input[type=number][name^="minutes"] {
	width: 5em;
	min-width: 0;
}

/* School Setup > Calendar event popup: the "Event Repeat" field (#REPEAT) is
   emitted at size=1, which the base input padding squeezes to no usable width.
   Widen it so the value shows; the "Days" label stays inline to its right. */
body.modules #body #REPEAT {
	width: 4.5em;
	min-width: 0;
}

/* School Setup > School Information: "Number of Days for the Rotation" is
   emitted at size=1 — same squeeze. Widen to fit its 1-digit value comfortably. */
body.modules #body #valuesNUMBER_DAYS_ROTATION {
	width: 4.5em;
	min-width: 0;
}

/* School Setup > School Configuration > Security: "Failed Login Attempts Limit"
   is emitted at size=2 — widen it like the other small numeric fields. */
body.modules #body #valuesCONFIGFAILED_LOGIN_LIMIT {
	width: 4.5em;
	min-width: 0;
}

/* School Setup > School Configuration: the form is a stack of nested <fieldset>s
   inside auto-width tables, so each section shrinks to its content and reads
   narrow (Security most of all, with its single small field). Force the config
   sections and their tables to full width so every section fills the card. */
body.modules #body fieldset:has(input[name^="values[CONFIG]"]),
body.modules #body fieldset:has(input[name^="values[CONFIG]"]) > table {
	width: 100%;
	box-sizing: border-box;
}

/* Default Theme choices render as a multi-column radio table; stack them one
   option per line. Match ONLY the radio table itself (via the direct child
   path) — a plain :has() would also match every ancestor table that merely
   contains these radios and break the layout. */
body.modules #body table:has(> tbody > tr > td > label > input[name="values[CONFIG][THEME]"]) tr,
body.modules #body table:has(> tbody > tr > td > label > input[name="values[CONFIG][THEME]"]) td {
	display: block;
}

/* The two Attendance config fields have long labels, so their tooltip "i" sits
   at the card's right edge and the default centered popup (.tooltip > i {
   left:-55px; width:120px }) spills past the card and is clipped by its
   overflow:hidden. Anchor JUST these two popups to the icon's right so they open
   leftward, staying inside the card. */
body.modules #body label[for="valuesPROGRAM_CONFIGATTENDANCE_EDIT_DAYS_BEFORE"] .tooltip > i,
body.modules #body label[for="valuesPROGRAM_CONFIGATTENDANCE_EDIT_DAYS_AFTER"] .tooltip > i {
	left: auto;
	right: 0;
}

body.modules #body select {
	box-sizing: border-box;
	padding: 7px 9px;
	border: 1px solid var(--field-line);
	border-radius: 7px;
	background-color: var(--card);
	font-family: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
	font-size: 12.5px;
	font-weight: 500;
	color: var(--ink-mid);
	cursor: pointer;
	outline: none;
	transition: border-color .12s, box-shadow .12s;
}

/* Single-line inputs and selects share one height so they line up in a row
   (selects were shorter than inputs). box-sizing:border-box is set above. */
body.modules #body input[type=text],
body.modules #body input[type=password],
body.modules #body input[type=email],
body.modules #body input[type=number],
body.modules #body input[type=search],
body.modules #body input[type=tel],
body.modules #body input[type=url],
body.modules #body input[type=date],
body.modules #body input[type=time],
body.modules #body select {
	height: var(--field-h);
}

/* Click-to-edit fields (InputDivOnclick): the value first shows as text in a
   .underline-dots box, and clicking swaps it for the real input/select. Give
   the text box the same height as the field so nothing jumps when the field
   opens, and drop the base dotted underline for a flat, clean value. */
body.modules #body .underline-dots {
	border-bottom: 0; /* remove the base dotted underline under the value */
}

body.modules #body .onclick .underline-dots {
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	min-height: var(--field-h);
	margin: 2px 0; /* aligned flush-left under the caption */
	padding: 0 2px;
	line-height: 1.35;
	vertical-align: middle;
}

/* Checkbox click-to-edit display renders "<Yes/No value box> Label" in one
   .onclick; the value box is min-height:36px (inline-flex, vertical-align
   middle), so a bare trailing label baseline-aligns low against it. The label
   is wrapped in .checkbox-value-label (CheckboxInput) — align it to the middle
   of the value box so the two line up. */
body.modules #body .onclick > .checkbox-value-label {
	vertical-align: middle;
}

/* Focus ring (teal). */
body.modules #body input[type=text]:focus,
body.modules #body input[type=password]:focus,
body.modules #body input[type=email]:focus,
body.modules #body input[type=number]:focus,
body.modules #body input[type=search]:focus,
body.modules #body input[type=tel]:focus,
body.modules #body input[type=url]:focus,
body.modules #body input[type=date]:focus,
body.modules #body input[type=time]:focus,
body.modules #body textarea:focus,
body.modules #body select:focus {
	border-color: var(--pri);
	box-shadow: 0 0 0 3px rgba(14, 116, 144, .13);
}

/* Placeholders + disabled state. */
body.modules #body input::placeholder,
body.modules #body textarea::placeholder {
	color: var(--ink-faint);
}

/* Disabled text fields get a gray fill. Exclude checkbox/radio: they render
   their own box via appearance:none, and this `background` shorthand would wipe
   the :checked green fill + checkmark (leaving a checked box empty). */
body.modules #body input:disabled:not([type=checkbox]):not([type=radio]),
body.modules #body textarea:disabled,
body.modules #body select:disabled {
	background: var(--field);
	color: var(--ink-faint);
	cursor: default;
}

/* Content links -> teal. */
body.modules #body a:not(.button):not(.button-primary):not(.BottomButton) {
	color: var(--pri);
}

/* Checkboxes -> custom green box with white tick (matches button('check')). */
body.modules input[type=checkbox] {
	-webkit-appearance: none;
	appearance: none;
	box-sizing: border-box;
	width: 17px;
	height: 17px;
	margin: 0 3px;
	padding: 0;
	border: 1.5px solid var(--field-line);
	border-radius: 5px;
	background: #fff;
	vertical-align: -3px;
	cursor: pointer;
	transition: background .12s, border-color .12s, box-shadow .12s;
}

body.modules input[type=checkbox]:hover {
	border-color: #16a34a;
}

body.modules input[type=checkbox]:focus-visible {
	outline: none;
	box-shadow: 0 0 0 3px rgba(22, 163, 74, .25);
}

body.modules input[type=checkbox]:checked {
	border-color: #16a34a;
	background-color: #16a34a;
	background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23fff%27%20stroke-width%3D%273.5%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27m20%206-11%2011-5-5%27%2F%3E%3C%2Fsvg%3E");
	background-repeat: no-repeat;
	background-position: center;
	background-size: 12px 12px;
}

body.modules input[type=checkbox]:disabled {
	opacity: .5;
	cursor: default;
}

/* A checked + disabled checkbox means "already selected / locked in" (e.g. the
   Advanced Report field pickers) — show it at full strength, not dimmed. */
body.modules input[type=checkbox]:checked:disabled {
	opacity: 1;
}

/* Search forms (#search): space out the stacked toggle options at the bottom
   (Group by Family, Search All Schools, Include Inactive Students) — the base
   markup packs them with only <br>. Scoped to #search .center, so the inline
   Grade-Level checkboxes in the fields table above are untouched. */
body.modules #body #search .center label:has(> input[type=checkbox]) {
	display: block;
	margin: 10px 0;
}

body.modules #body #search .center label:has(> input[type=checkbox]) + br {
	display: none;
}

/* Field editors (Fields.fnc.php) lay Default / Required / Sort Order in one row.
   The text fields stack a caption on top (pushing their input down ~26px), but
   the Required checkbox cell has no caption, so a top-aligned cell floats it up
   at caption level. Middle-align the checkbox cell so it lines up with the
   inputs beside it. */
body.modules #body td:has(> label.checkbox-label) {
	vertical-align: middle;
}

/* Field captions ------------------------------------ */
/* FormatInputTitle() labels each input with <span class="legend-gray">
   (or .legend-red when the field is required). The base markup emits the
   caption AFTER the field; the flex rule below re-stacks each field group so
   the caption reads ABOVE its field. Style: small, bold, uppercase,
   letter-spaced slate, with a small gap down to its field and a clear
   vertical break up from the previous one. */
body.modules .legend-gray,
body.modules .legend-red {
	display: block;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .05em;
	text-transform: uppercase;
	margin-top: 14px;   /* vertical break up from the previous field */
	margin-bottom: 2px; /* small gap down to this caption's field */
}

body.modules .legend-gray {
	color: var(--ink-faint);
}

body.modules .legend-red {
	color: #dc2626;
}

/* Caption above field: each field group is [field][<br>][caption]. Reverse-
   stack the caption's direct parent so the caption renders on top, and drop
   the now-redundant <br>. This targets only the click-to-edit <div> wrappers —
   the .onclick box (display state) and the #div<id> wrapper (opened field) —
   which cover every populated / editable field.

   NB: we deliberately do NOT flex a bare <td> (an empty field, or the sub-
   inputs of a grouped field like Name). `display:flex` strips a cell of its
   table-cell role, and two flexed cells in one row collapse into a single
   stacked block — turning a row of fields into a column. So a bare empty
   field keeps its caption below; populated fields (the norm) get it on top.

   :not(.hide) — this rule outspecifies the theme's .hide{display:none}, so
   without it a hidden captioned box (e.g. the .user-photo-form upload panel
   on Users/User.php, revealed by the "+" toggle) would be forced visible. */
body.modules #body div:not(.hide):has(> label > .legend-gray),
body.modules #body div:not(.hide):has(> label > .legend-red),
body.modules #body div:not(.hide):has(> .legend-gray),
body.modules #body div:not(.hide):has(> .legend-red) {
	display: flex;
	flex-direction: column-reverse;
	align-items: flex-start;
}

body.modules #body div:not(.hide):has(> label > .legend-gray) > br,
body.modules #body div:not(.hide):has(> label > .legend-red) > br,
body.modules #body div:not(.hide):has(> .legend-gray) > br,
body.modules #body div:not(.hide):has(> .legend-red) > br {
	display: none;
}

/* Multi-select field group under ONE caption — the PrepareDate() month/day/year
   triple (every date field's open state) and the Preferences > Display Options
   "Date Format" selects. The column-reverse stack above would put each select
   on its own line, in reverse order. Lay these out as a wrapping row instead:
   the caption is forced onto a full first line (order/flex-basis), and the
   selects (+ the jscalendar button, if any) sit side by side below it.
   NB: the caption :has() qualifier is repeated here so this rule OUTRANKS the
   column-reverse rule above (same class count, more element count) — with only
   :has(> select + select) it loses on specificity and never applies. */
body.modules #body div:not(.hide):has(> select + select):has(> .legend-gray),
body.modules #body div:not(.hide):has(> select + select):has(> .legend-red),
body.modules #body div:not(.hide):has(> select + select):has(> label > .legend-gray),
body.modules #body div:not(.hide):has(> select + select):has(> label > .legend-red) {
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
}

body.modules #body div:not(.hide):has(> select + select) > .legend-gray,
body.modules #body div:not(.hide):has(> select + select) > .legend-red,
body.modules #body div:not(.hide):has(> select + select) > label:has(> .legend-gray),
body.modules #body div:not(.hide):has(> select + select) > label:has(> .legend-red) {
	order: -1;
	flex-basis: 100%;
}

/* Grouped field editor (Name & co.), OPEN state: a click-to-edit field whose
   editor is a nested <table> of captioned sub-inputs (First / Middle / Last /
   Suffix). Flexing the sub-cells directly would collapse the row (see note
   above), so lay the row out with flex at the <tr> level instead: the sub-
   fields stay side by side, each with its caption stacked on top.

   Scoped to the InputDivOnclick wrapper via div[id^="div"] (its id is
   "div"+field-id) so it can ONLY hit a click-to-edit editor — never a card or
   layout <div> that merely happens to wrap a form <table> (that would flex
   every cell of the whole form). Matches only the OPEN state: in the display
   state the wrapper's direct child is .onclick, not a <table>. */
body.modules #body div[id^="div"]:has(> table .legend-gray) > table,
body.modules #body div[id^="div"]:has(> table .legend-red) > table,
body.modules #body div[id^="div"]:has(> table .legend-gray) > table > tbody,
body.modules #body div[id^="div"]:has(> table .legend-red) > table > tbody {
	display: block;
}

body.modules #body div[id^="div"]:has(> table .legend-gray) > table > tbody > tr,
body.modules #body div[id^="div"]:has(> table .legend-red) > table > tbody > tr {
	display: flex;
	flex-wrap: wrap;
	gap: 14px;
}

body.modules #body div[id^="div"]:has(> table .legend-gray) > table > tbody > tr > td,
body.modules #body div[id^="div"]:has(> table .legend-red) > table > tbody > tr > td {
	display: flex;
	flex-direction: column-reverse;
	align-items: flex-start;
}

body.modules #body div[id^="div"]:has(> table .legend-gray) br,
body.modules #body div[id^="div"]:has(> table .legend-red) br {
	display: none;
}

/* MarkDown editor (e.g. Custom tab "Comments"/"Registration Notes", the
   calendar event popup's "Notes"): TextAreaInput() emits [.md-preview =
   Write/Preview tabs][textarea][caption]. twine-app.js wraps the cell in a
   .field-stack that the caption rule above reverse-stacks, which lands the
   order caption / textarea / tabs. Override that one stack to a normal column
   and order it caption -> tabs -> field, so the tabs sit between the heading
   and the field. */
body.modules #body .field-stack:has(> div.md-preview) {
	display: flex;
	flex-direction: column; /* override the caption rule's column-reverse */
}
body.modules #body .field-stack:has(> div.md-preview) > label { order: 1; }
body.modules #body .field-stack:has(> div.md-preview) > div.md-preview {
	order: 2;
	/* Pull the tab strip down 1px onto the field's top border and sit above it,
	   so the active tab (no bottom border) covers the line beneath it and opens
	   into the field — the classic connected-tab look. */
	position: relative;
	z-index: 1;
	margin-bottom: -1px;
}
body.modules #body .field-stack:has(> div.md-preview) > textarea { order: 3; }

/* Boxed Write/Preview tabs: bordered, rounded top corners (all of them,
   including "Write"'s), full border (including bottom) by default so the
   INACTIVE tab keeps a visible line separating it from the field below. The
   ACTIVE tab's own bottom border is colored to match its background, blending
   into it — this pairs with the two field-merge rules below (textarea /
   rendered panel) to erase the line specifically under whichever tab is
   active. */
body.modules #body .md-preview > .tab {
	display: inline-block;
	box-sizing: border-box;
	border: 1px solid var(--field-line);
	border-radius: 6px 6px 0 0;
	background: var(--card);
	padding: 5px 12px;
	margin: 0 2px 0 0;
	font-size: 12px;
	font-weight: 600;
	line-height: 1.6;
	color: var(--ink-faint);
	cursor: pointer;
}
body.modules #body .md-preview > .tab.disabled { /* active tab */
	color: var(--pri);
	font-weight: 700;
	background: var(--card);
	border-bottom-color: var(--card);
}

/* Write field (textarea): a real SIBLING of .md-preview. The existing
   field-stack rule above already pulls .md-preview -1px onto this textarea
   with z-index:1, so the active tab's blended bottom border (opaque, matching
   background) paints over and erases the textarea's top border locally; the
   inactive tab's real border-bottom shows normally beside/through it. */
body.modules #body .md-preview + textarea {
	border-top-left-radius: 0 !important;
	border-top-right-radius: 8px !important;
}

/* Preview field (the rendered .markdown-to-html panel): a CHILD of
   .md-preview, not a sibling — so the field-stack rule's -1px/z-index shift on
   the OUTER .md-preview box (aimed at the sibling textarea) never reaches it.
   Give the panel its own matching overlap: pull it up 1px onto the tab row
   (same stacking context as the tabs, so DOM order alone would let the panel's
   line paint over both tabs) and lift only the active tab above it with
   z-index, so — same as the textarea case — the active tab's opaque background
   erases the line locally while the inactive tab's own border stands in front
   of (and matches) the panel's line elsewhere. */
body.modules #body .md-preview > .tab.disabled {
	position: relative;
	z-index: 1;
}
body.modules #body .md-preview > div.markdown-to-html {
	position: relative;
	margin-top: -1px;
	border-top: 1px solid var(--field-line) !important;
	border-top-left-radius: 0 !important;
	border-top-right-radius: 8px !important;
}

/* =====================================================
   INFO CARDS (Student Info)
   The student info block (general + custom fields) and the enrollment block
   are wrapped in .twine-card and float as white rounded cards on the page
   background. The student card sits inside the tab body (td.popTable); the
   enrollment card renders just after the tab card, straight in #body.
   ===================================================== */
body.modules #body .twine-card {
	background: var(--card);
	border: 1px solid #e6ebf1;
	border-radius: 16px;
	padding: 24px 30px;
	margin-bottom: 20px;
	box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
}

body.modules #body .twine-card:last-child {
	margin-bottom: 0;
}

/* Let the page background show through the tab body so the cards float on it
   (tabs without cards keep the plain white sheet): the Student Info card
   (.twine-card) and the Addresses & Contacts card layout (tr.address). */
body.modules .postbox:has(.h3multi) > tbody > tr > td.popTable:has(.twine-card),
body.modules .postbox:has(.h3multi) > tbody > tr > td.popTable:has(tr.address) {
	background: transparent;
}

/* Continuous field flow inside a card — drop the section separators. */
body.modules #body .twine-card hr {
	display: none;
}

/* Enrollment card header: title + record-count pill, replacing ListOutput's
   default "N … were found." nav row. */
body.modules #body .twine-card--enrollment .list-nav {
	display: none;
}

body.modules #body .twine-card-head {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-bottom: 16px;
}

body.modules #body .twine-card-title {
	font-size: 17px;
	font-weight: 800;
	letter-spacing: -.01em;
	color: var(--ink);
}

body.modules #body .twine-pill {
	padding: 3px 11px;
	border-radius: 999px;
	background: var(--pri-soft);
	color: var(--pri-deep);
	font-size: 12px;
	font-weight: 700;
	white-space: nowrap;
}

/* Enrollment table sits flush inside the card (no double frame / offsets). */
/* A list inside a card melts into it (the Student Info Enrollment look):
   the card provides the frame, so the inner .widefat drops its own border,
   radius and header fill. Applies to every .twine-card — incl. the wrapped
   Users tab bodies (Preferences Widgets / Student Fields / User Fields lists)
   so they read like the student page instead of a card-in-a-card. */
body.modules #body .twine-card .widefat {
	border: 0;
	border-radius: 0;
}

body.modules #body .twine-card .widefat th,
body.modules #body .twine-card .widefat tfoot tr th {
	background: transparent;
}

body.modules #body .twine-card > div[style*="overflow"] {
	margin: 0;
}

/* =====================================================
   CHOSEN searchable select (ChosenSelectInput, e.g. "Add Existing
   Address/Contact"). Chosen paints its magnifier / clear / arrow glyphs from
   ONE sprite positioned by background-position; the generic #body input rule
   above (higher specificity via #body) resets that position + box, so the
   search field showed a stack of stray sprite glyphs (arrows, double-X). Give
   it a clean look: single magnifier at the trailing edge, no sprite.
   ===================================================== */
body.modules #body .chosen-search input[type=text],
body.modules #body .chosen-container-single .chosen-search input[type=text] {
	box-sizing: border-box;
	height: auto;
	margin: 0;
	padding: 7px 32px 7px 11px;
	border: 1px solid var(--field-line);
	border-radius: 8px;
	direction: ltr;
	font-size: 13px;
	background-color: var(--card) !important;
	background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%2394a3b8%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2711%27%20cy%3D%2711%27%20r%3D%278%27%2F%3E%3Cpath%20d%3D%27m21%2021-4.3-4.3%27%2F%3E%3C%2Fsvg%3E") !important;
	background-repeat: no-repeat !important;
	background-position: right 10px center !important;
	background-size: 15px 15px !important;
}

/* =====================================================
   ADDRESSES & CONTACTS (design/new.html)
   The page is a 3-column layout table anchored by <tr class="address">:
   col1 = address list, col2 = contacts + address detail (stacked), col3 =
   selected-contact detail (empty by default). Re-flow it into the mockup's
   cards: address-list | (contacts | address) — all via CSS on the existing
   markup, so every link / form / master-detail action keeps working.
   ===================================================== */
body.modules #body table:has(> tbody > tr.address) { display: block; }
body.modules #body table:has(> tbody > tr.address) > tbody { display: block; }
body.modules #body tr.address {
	display: grid;
	grid-template-columns: 340px minmax(0, 1fr);
	gap: 18px;
	align-items: start;
}
body.modules #body tr.address > td { display: block; min-width: 0; padding: 0; }
body.modules #body tr.address > td:empty { display: none; }

/* Right column: contacts | address split (contacts spans both rows). */
body.modules #body tr.address > td:nth-child(2) {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 18px;
	align-items: start;
}
body.modules #body tr.address > td:nth-child(2) > br { display: none; }
body.modules #body tr.address > td:nth-child(2) > table:nth-of-type(1) { grid-column: 1; grid-row: 1 / span 2; }
body.modules #body tr.address > td:nth-child(2) > table:nth-of-type(2) { grid-column: 2; grid-row: 1; margin: 0; }
body.modules #body tr.address > td:nth-child(2) > table:nth-of-type(3) { grid-column: 2; grid-row: 2; margin: 0; box-shadow: none; }

/* Each inner widefat -> a clean white card. */
body.modules #body tr.address .widefat {
	display: table;
	width: 100%;
	background: var(--card);
	border: 1px solid #e6ebf1;
	border-radius: 16px;
	overflow: hidden;
	box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
	border-collapse: separate;
	border-spacing: 0;
}

body.modules #body tr.address .widefat th {
	background: var(--card) !important;
	border-bottom: 1px solid #eef2f6;
	padding: 13px 18px;
	font-size: 13.5px !important;
	font-weight: 800;
	letter-spacing: 0;
	text-transform: none;
	color: var(--ink);
	text-align: left;
}

body.modules #body tr.address .widefat td {
	border: 0;
	border-bottom: 1px solid #f3f5f8;
	padding: 11px 16px;
	vertical-align: middle;
}
body.modules #body tr.address .widefat tr:last-child td { border-bottom: 0; }

/* Selected row -> pri-soft highlight. */
body.modules #body tr.address .widefat tr.highlight { background: var(--pri-soft); }
body.modules #body tr.address .widefat tr.highlight-hover:hover { background: var(--hover); }

body.modules #body tr.address .widefat a:not(.arrow) {
	color: var(--ink);
	text-decoration: none;
	font-weight: 700;
	font-size: 13px;
}
body.modules #body tr.address .widefat td a:not(.arrow):hover { color: var(--pri); }

/* Add-... action rows -> teal. */
body.modules #body tr.address .widefat a[href*="address_id=new"],
body.modules #body tr.address .widefat a[href*="address_id=old"],
body.modules #body tr.address .widefat a[href*="person_id=new"],
body.modules #body tr.address .widefat a[href*="person_id=old"] {
	color: var(--pri);
	font-weight: 600;
}

body.modules #body tr.address .arrow.right { color: #cbd5e1; }

/* Address-detail field rows get separators like the mockup. */
body.modules #body tr.address > td:nth-child(2) > table:nth-of-type(2) td {
	border-bottom: 1px solid #eef2f6;
}

/* Contact avatar + name column (avatar span added in Address.inc.php). */
body.modules #body tr.address .tw-avatar {
	width: 36px; height: 36px; border-radius: 10px;
	background: var(--bg, #e2e8f0); color: var(--c, #475569);
	display: inline-flex; align-items: center; justify-content: center;
	font-weight: 700; font-size: 13px; flex: none;
}
body.modules #body tr.address td:has(> .tw-avatar) { display: flex; align-items: center; gap: 11px; }
body.modules #body tr.address .tw-namecol { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
body.modules #body tr.address .tw-namecol a { color: var(--pri); font-weight: 700; font-size: 13.5px; }
body.modules #body tr.address .tw-sub { font-size: 11.5px; font-weight: 600; color: var(--ink-faint); }
body.modules #body tr.address .tw-imgs { margin-left: auto; }

/* Residence / mailing -> green-check rows. */
body.modules #body tr.address > td:nth-child(2) > table:nth-of-type(3) td:nth-child(3) {
	color: #16a34a; font-weight: 700; font-size: 12.5px;
}
body.modules #body tr.address > td:nth-child(2) > table:nth-of-type(3) img { display: none; }

/* Swap the list's +/- PNG buttons for clean glyphs (real app renders PNGs). */
body.modules #body tr.address img[src*="btn/add.png"] {
	content: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272.5%27%20stroke-linecap%3D%27round%27%3E%3Cpath%20d%3D%27M12%205v14M5%2012h14%27%2F%3E%3C%2Fsvg%3E");
	width: 15px !important; height: 15px !important; vertical-align: middle;
}
body.modules #body tr.address img[src*="btn/remove.png"] {
	content: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23dc2626%27%20stroke-width%3D%273%27%20stroke-linecap%3D%27round%27%3E%3Cpath%20d%3D%27M5%2012h14%27%2F%3E%3C%2Fsvg%3E");
	width: 14px !important; height: 14px !important; vertical-align: middle;
}
body.modules #body tr.address img[src*="btn/compass_rose.png"] { display: none; }


/* --- Selected-contact state -----------------------------------------------
   When a contact is picked from "Contacts at this Address", td3 (the contact
   detail: Contact Information + Additional Information) becomes non-empty. Then
   re-flow the row to three columns — addresses | contacts | detail — promote
   the middle cell's tables into that grid (display:contents), drop the Address
   and Primary/Mailing cards, and drop the contact detail into the freed column
   so it replaces Address. Default (no contact) keeps the base two-column flow. */
body.modules #body tr.address:has(> td:nth-child(3):not(:empty)) {
	grid-template-columns: 300px minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
}
body.modules #body tr.address:has(> td:nth-child(3):not(:empty)) > td:nth-child(2) {
	display: contents;
}
body.modules #body tr.address:has(> td:nth-child(3):not(:empty)) > td:nth-child(2) > table:nth-of-type(1) {
	grid-column: 2;
	grid-row: 1;
}
body.modules #body tr.address:has(> td:nth-child(3):not(:empty)) > td:nth-child(2) > table:nth-of-type(2),
body.modules #body tr.address:has(> td:nth-child(3):not(:empty)) > td:nth-child(2) > table:nth-of-type(3) {
	display: none;
}
/* Contact Information (td3) and the Additional Information category fieldsets
   (td4) sit side by side in the two freed columns. */
body.modules #body tr.address:has(> td:nth-child(3):not(:empty)) > td:nth-child(3) {
	grid-column: 3;
	grid-row: 1;
}
body.modules #body tr.address:has(> td:nth-child(3):not(:empty)) > td:nth-child(4) {
	grid-column: 4;
	grid-row: 1;
	align-self: start;
}

/* Contact-detail fieldsets (e.g. "Additional Information") render as a bare
   <fieldset><legend>; give them the same white-card look as the Contact
   Information table beside them. */
body.modules #body tr.address fieldset {
	background: var(--card);
	border: 1px solid #e6ebf1;
	border-radius: 16px;
	box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
	margin: 0;
	padding: 16px 18px 18px;
}
/* A <legend> is anchored to the fieldset's top border by default (it "floats"
   over the frame). Float it instead so it drops into normal flow as a plain
   full-width card title, with the content resuming below it. */
body.modules #body tr.address fieldset > legend {
	float: left;
	width: 100%;
	box-sizing: border-box;
	margin: 0 0 12px;
	padding: 0 0 10px;
	border-bottom: 1px solid #eef2f6;
	font-size: 13.5px;
	font-weight: 800;
	color: var(--ink);
}
body.modules #body tr.address fieldset > legend + * {
	clear: both;
}

/* =====================================================
   BOTTOM BAR (Menu / Print / Help / Logout)
   ===================================================== */
body.modules #footer {
	background: var(--card);
	background-image: none;
	border-top: 1px solid var(--line);
	box-shadow: 0 -2px 12px -6px rgba(15, 23, 42, .12);
}

body.modules .BottomButton {
	color: var(--ink-mid);
	font-weight: 700;
	font-size: 13px;
	margin: 0 14px; /* spread the bottom-bar items apart */
}

body.modules .BottomButton img {
	height: 22px;
	vertical-align: middle;
}

/* Inline icon buttons in the bottom bar (e.g. Logout). */
body.modules .BottomButton svg {
	width: 20px;
	height: 20px;
	vertical-align: middle;
	margin-right: 2px;
}

/* Menu button now carries an inline SVG hamburger like the other footer items —
   drop the base theme's "≡" glyph (#BottomButtonMenu:before) so it doesn't double up. */
body.modules #BottomButtonMenu::before {
	content: none;
}

/* Zammad support widget: a normal footer BottomButton now (moved here from a
   floating teal button). Reset the native <button> chrome so it matches the
   other footer items; .BottomButton supplies the colour/size/spacing. */
body.modules #zammad-feedback-form.BottomButton {
	margin: 0 14px;
	padding: 0;
	border: 0;
	background: none;
	box-shadow: none;
	outline: none;
	font-family: inherit;
	line-height: 32px;
	vertical-align: top;
	cursor: pointer;
}

/* =====================================================
   HELP MODAL
   The footer Help button loads inline help into #footerhelp; twine-app.js
   presents it as a centered modal instead of growing the footer.
   ===================================================== */
#twine-help-backdrop {
	position: fixed;
	inset: 0;
	z-index: 100000;
	background: rgba(15, 23, 42, .45);
}

body.modules #footerhelp.twine-help-modal {
	display: block;
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: min(760px, calc(100vw - 40px));
	height: auto;
	margin: 0;
	padding: 0;
	overflow: visible;
	background: var(--card);
	border-radius: 16px;
	box-shadow: 0 24px 64px -16px rgba(15, 23, 42, .45);
	z-index: 100001;
}

body.modules #footerhelp.twine-help-modal .twine-help-body {
	max-height: min(80vh, 720px);
	overflow-y: auto;
	padding: 30px 34px 34px;
	line-height: 1.5;
}

/* Red close button, top-right corner. */
body.modules #footerhelp.twine-help-modal .twine-help-close {
	position: absolute;
	top: 12px;
	right: 12px;
	z-index: 1;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	padding: 0;
	border: 0;
	border-radius: 9px;
	background: none;
	color: #ef4444; /* red */
	cursor: pointer;
	transition: background .12s, color .12s;
}

body.modules #footerhelp.twine-help-modal .twine-help-close:hover {
	background: #fee2e2;
	color: #dc2626;
}

body.modules #footerhelp.twine-help-modal .twine-help-close svg {
	width: 19px;
	height: 19px;
}

/* =====================================================
   MODULE ICONS (design/new.html) — sidebar + page header
   Monochrome Lucide-style glyphs via content:url() data URIs,
   keyed by module class (sidebar) and icon src (header).
   ===================================================== */
/* --- sidebar module icons (from design/new.html) --- */
body.modules .menu-module.school-setup .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%2322a06b%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M3%209%2012%204l9%205-9%205-9-5Z%27%2F%3E%3Cpath%20d%3D%27M3%209v6l9%205%209-5V9%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.students .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23b45309%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%277%27%20width%3D%2720%27%20height%3D%2714%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M16%207V5a2%202%200%200%200-2-2h-4a2%202%200%200%200-2%202v2%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.users .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23475569%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%278%27%20r%3D%274%27%2F%3E%3Cpath%20d%3D%27M4%2021c0-4%204-6%208-6s8%202%208%206%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.scheduling .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%232563eb%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%273%27%20y%3D%274%27%20width%3D%2718%27%20height%3D%2717%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M16%202v4M8%202v4M3%2010h18%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.grades .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23dc2626%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2019.5A2.5%202.5%200%200%201%206.5%2017H20%27%2F%3E%3Cpath%20d%3D%27M6.5%202H20v20H6.5A2.5%202.5%200%200%201%204%2019.5v-15A2.5%202.5%200%200%201%206.5%202Z%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.attendance .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230891b2%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%279%27%2F%3E%3Cpath%20d%3D%27M12%207v5l3%202%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.eligibility .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230d9488%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203l7%203v6c0%204-3%206.5-7%208-4-1.5-7-4-7-8V6z%27%2F%3E%3Cpath%20d%3D%27m8.5%2012%202.5%202.5%204.5-5%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.discipline .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%237c3aed%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27m14.5%204%205.5%205.5L9%2020.5%203.5%2015%2014.5%204Z%27%2F%3E%3Cpath%20d%3D%27m11%207%206%206%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.accounting .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%2316a34a%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%276%27%20width%3D%2720%27%20height%3D%2712%27%20rx%3D%272%27%2F%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%272.5%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.student-billing .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23b45309%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%277%27%20width%3D%2720%27%20height%3D%2714%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M16%207V5a2%202%200%200%200-2-2h-4a2%202%200%200%200-2%202v2M2%2013h20%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.food-service .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23ea580c%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M5%2011h14l-1.2%207a2%202%200%200%201-2%201.6H8.2a2%202%200%200%201-2-1.6z%27%2F%3E%3Cpath%20d%3D%27M7%2011a5%205%200%200%201%2010%200%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.resources .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%2364748b%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M3%207a2%202%200%200%201%202-2h4l2%202h8a2%202%200%200%201%202%202v8a2%202%200%200%201-2%202H5a2%202%200%200%201-2-2z%27%2F%3E%3C%2Fsvg%3E")}
body.modules .menu-module.custom .menu-top img{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%236366f1%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2021v-7M4%2010V4M12%2021v-9M12%206V4M20%2021v-5M20%2010V4%27%2F%3E%3Cpath%20d%3D%27M1%2014h6M9%206h6M17%2012h6%27%2F%3E%3C%2Fsvg%3E")}

/* --- header module icon (same glyphs) --- */
body.modules .header1 .headerIcon[src*="School_Setup/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M3%209%2012%204l9%205-9%205-9-5Z%27%2F%3E%3Cpath%20d%3D%27M3%209v6l9%205%209-5V9%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Students/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%277%27%20width%3D%2720%27%20height%3D%2714%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M16%207V5a2%202%200%200%200-2-2h-4a2%202%200%200%200-2%202v2%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Users/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%278%27%20r%3D%274%27%2F%3E%3Cpath%20d%3D%27M4%2021c0-4%204-6%208-6s8%202%208%206%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Scheduling/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%273%27%20y%3D%274%27%20width%3D%2718%27%20height%3D%2717%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M16%202v4M8%202v4M3%2010h18%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Grades/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2019.5A2.5%202.5%200%200%201%206.5%2017H20%27%2F%3E%3Cpath%20d%3D%27M6.5%202H20v20H6.5A2.5%202.5%200%200%201%204%2019.5v-15A2.5%202.5%200%200%201%206.5%202Z%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Attendance/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%279%27%2F%3E%3Cpath%20d%3D%27M12%207v5l3%202%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Eligibility/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M12%203l7%203v6c0%204-3%206.5-7%208-4-1.5-7-4-7-8V6z%27%2F%3E%3Cpath%20d%3D%27m8.5%2012%202.5%202.5%204.5-5%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Discipline/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27m14.5%204%205.5%205.5L9%2020.5%203.5%2015%2014.5%204Z%27%2F%3E%3Cpath%20d%3D%27m11%207%206%206%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Accounting/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%276%27%20width%3D%2720%27%20height%3D%2712%27%20rx%3D%272%27%2F%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%272.5%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Student_Billing/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%277%27%20width%3D%2720%27%20height%3D%2714%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M16%207V5a2%202%200%200%200-2-2h-4a2%202%200%200%200-2%202v2M2%2013h20%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Food_Service/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M5%2011h14l-1.2%207a2%202%200%200%201-2%201.6H8.2a2%202%200%200%201-2-1.6z%27%2F%3E%3Cpath%20d%3D%27M7%2011a5%205%200%200%201%2010%200%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Resources/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M3%207a2%202%200%200%201%202-2h4l2%202h8a2%202%200%200%201%202%202v8a2%202%200%200%201-2%202H5a2%202%200%200%201-2-2z%27%2F%3E%3C%2Fsvg%3E")}
body.modules .header1 .headerIcon[src*="Custom/icon.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%230e7490%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M4%2021v-7M4%2010V4M12%2021v-9M12%206V4M20%2021v-5M20%2010V4%27%2F%3E%3Cpath%20d%3D%27M1%2014h6M9%206h6M17%2012h6%27%2F%3E%3C%2Fsvg%3E")}

/* =====================================================
   DIRECT btn/*.png IMAGES -> inline SVG (design/new.html)
   These are hard-coded <img> (not via button()); swap the
   rendered glyph with content:url(). Colour baked slate
   (currentColor is not inherited by an SVG loaded as url()).
   ===================================================== */
body.modules img[src*="btn/locked.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23475569%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%273%27%20y%3D%2711%27%20width%3D%2718%27%20height%3D%2711%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M7%2011V7a5%205%200%200%201%2010%200v4%27%2F%3E%3C%2Fsvg%3E");width:17px !important;height:17px !important;vertical-align:middle}
body.modules img[src*="btn/unlocked.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23475569%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%273%27%20y%3D%2711%27%20width%3D%2718%27%20height%3D%2711%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M7%2011V7a5%205%200%200%201%209.9-1%27%2F%3E%3C%2Fsvg%3E");width:17px !important;height:17px !important;vertical-align:middle}
body.modules img[src*="btn/download.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23475569%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M21%2015v4a2%202%200%200%201-2%202H5a2%202%200%200%201-2-2v-4%27%2F%3E%3Cpath%20d%3D%27m7%2010%205%205%205-5%27%2F%3E%3Cpath%20d%3D%27M12%2015V3%27%2F%3E%3C%2Fsvg%3E");width:17px !important;height:17px !important;vertical-align:middle}
body.modules img[src*="btn/visualize.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23475569%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cpath%20d%3D%27M2%2012s3-7%2010-7%2010%207%2010%207-3%207-10%207-10-7-10-7z%27%2F%3E%3Ccircle%20cx%3D%2712%27%20cy%3D%2712%27%20r%3D%273%27%2F%3E%3C%2Fsvg%3E");width:17px !important;height:17px !important;vertical-align:middle}
body.modules img[src*="btn/md_button.png"]{content:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2024%2024%27%20fill%3D%27none%27%20stroke%3D%27%23475569%27%20stroke-width%3D%272%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Crect%20x%3D%272%27%20y%3D%275%27%20width%3D%2720%27%20height%3D%2714%27%20rx%3D%272%27%2F%3E%3Cpath%20d%3D%27M6%2015V9l3%203%203-3v6%27%2F%3E%3Cpath%20d%3D%27M16%209v4M14%2013l2%202%202-2%27%2F%3E%3C%2Fsvg%3E");width:17px !important;height:17px !important;vertical-align:middle}
