/* =============================================================================
 * co-v2.css - the shared look for the v2 coordinator pages.
 *
 * Used by view-students-v2.php, edit-student-v2.php and student-search-v2.php.
 * Everything is scoped under .cov2 so it cannot reach the 2019 bootstrap/style.css
 * that the legacy header and sidebar are built on, and those cannot reach in here.
 *
 * RELATIONSHIP TO bulk-students-v2.css. That file is the bulk grid's own stylesheet and
 * is deliberately left alone - it works, it has been through five rounds of screenshots
 * on the owner's phone, and re-plumbing it to share this one would put all of that at
 * risk for no user-visible gain. The two agree on the palette on purpose. If the bulk
 * page is ever revisited, moving it onto this file is the tidy-up.
 *
 * RULES THIS FILE FOLLOWS, all of them learned the hard way on the bulk page:
 *
 *  - Tokens live on :root, NOT on .cov2. Fixed-position overlays (the confirm dialog)
 *    are outside the .cov2 subtree in some browsers' containing-block terms, and a
 *    token declared on .cov2 resolves to nothing there - which renders a dialog with
 *    no background at all.
 *  - NEVER the `background` shorthand on a rule that can land on a <select>. The
 *    shorthand resets background-repeat to `repeat`, and a 12x8 chevron tiled across a
 *    340px control is a blue zigzag. background-color only.
 *  - Grid tracks are minmax(0, 1fr). A plain 1fr will not shrink below an <input>'s
 *    min-content width and the page scrolls sideways on a phone.
 *  - A generic .is-hidden exists. Per-component hiding rules mean any NEW element
 *    carrying the class is simply not hidden.
 *  - No `inset:` shorthand - long-hand top/right/bottom/left. inset is Chrome 87, and
 *    coordinators are on whatever Android shipped with the phone.
 *  - Base rules come BEFORE the media queries. A base rule written after a query
 *    silently wins over it at the same specificity.
 * ============================================================================= */

:root {
	--co-bg:          #f4f6fb;
	--co-card:        #ffffff;
	--co-ink:         #1f2733;
	--co-ink-soft:    #5b6b7f;
	--co-ink-faint:   #8b98a9;
	--co-line:        #e6eaf2;
	--co-line-firm:   #d3dae6;

	--co-accent:      #4361ee;
	--co-accent-dark: #2f4bd6;
	--co-accent-soft: #eef2ff;

	--co-ok:          #0f9d58;
	--co-ok-soft:     #e8f7f0;
	--co-warn:        #a8690b;
	--co-warn-soft:   #fdf3e2;
	--co-bad:         #d93b3b;
	--co-bad-soft:    #fdecec;

	--co-radius:      12px;
	--co-radius-sm:   8px;
	--co-shadow:      0 1px 2px rgba(16,24,40,.05), 0 1px 3px rgba(16,24,40,.06);

	--co-chev:        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%235b6b7f' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.75 6 6.25 11 1.75'/%3E%3C/svg%3E");
	--co-chev-accent: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%234361ee' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.75 6 6.25 11 1.75'/%3E%3C/svg%3E");
}

.cov2 {
	box-sizing: border-box;
	color: var(--co-ink);
	font-size: 15px;
	line-height: 1.5;
}
.cov2 *,
.cov2 *::before,
.cov2 *::after { box-sizing: inherit; }

/* The generic one. Without it, any new element given this class is simply not hidden -
   which on the bulk page showed both steps of a dialogue at once. */
.cov2 .is-hidden { display: none !important; }

/* visually hidden, still read aloud */
.cov2 .co-sr {
	position: absolute;
	width: 1px; height: 1px;
	margin: -1px; padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

/* ------------------------------------------------------------------- head --- */

.co-head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 12px;
	margin-bottom: 14px;
}
.co-head-title { flex: 1 1 260px; min-width: 0; }
.co-head h1 {
	margin: 0;
	font-size: 1.32rem;
	font-weight: 680;
	letter-spacing: -.01em;
}
.co-sub {
	margin-top: 3px;
	color: var(--co-ink-soft);
	font-size: .88rem;
}
.co-head-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

/* --------------------------------------------------------------- notices --- */

.co-notice {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin-bottom: 14px;
	padding: 12px 42px 12px 14px;
	border: 1px solid var(--co-line);
	border-left-width: 4px;
	border-radius: var(--co-radius-sm);
	background: var(--co-card);
	font-size: .9rem;
}
.co-notice-body { flex: 1 1 240px; min-width: 0; }
.co-notice-body b { display: block; font-weight: 650; }
.co-notice-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.co-notice.is-ok   { border-left-color: var(--co-ok);   background: var(--co-ok-soft); }
.co-notice.is-warn { border-left-color: var(--co-warn); background: var(--co-warn-soft); }
.co-notice.is-bad  { border-left-color: var(--co-bad);  background: var(--co-bad-soft); }
.co-notice.is-info { border-left-color: var(--co-accent); background: var(--co-accent-soft); }
.co-notice-x {
	position: absolute;
	top: 6px; right: 8px;
	width: 30px; height: 30px;
	border: 0;
	background: transparent;
	color: var(--co-ink-faint);
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
}
.co-notice-x:hover { color: var(--co-ink); }

/* ---------------------------------------------------------------- panels --- */

.co-panel {
	margin-bottom: 16px;
	border: 1px solid var(--co-line);
	border-radius: var(--co-radius);
	background: var(--co-card);
	box-shadow: var(--co-shadow);
}
.co-panel-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	padding: 13px 16px;
	border-bottom: 1px solid var(--co-line);
}
.co-panel-head h2 {
	margin: 0;
	flex: 1 1 auto;
	font-size: .95rem;
	font-weight: 650;
}
.co-panel-head .co-hint {
	color: var(--co-ink-faint);
	font-size: .82rem;
}
.co-panel-body { padding: 16px; }
.co-panel-body.is-flush { padding: 0; }

/* ------------------------------------------------------------------ lock --- */

/*
 * A value the page states but will never let you change - the student's centre on
 * edit-student-v2.php.
 *
 * It exists because the alternative is worse: a `disabled` .co-in sitting in a form
 * slot looks like a field that has failed rather than one that is deliberately fixed,
 * and it spends a whole grid column saying so. This reads as context, and the reason
 * it cannot change sits beside it instead of underneath as a footnote.
 */
.co-lock {
	display: flex;
	align-items: center;
	gap: 11px;
	margin-bottom: 14px;
	padding: 11px 13px;
	border: 1px solid var(--co-line);
	border-radius: var(--co-radius-sm);
	background-color: var(--co-bg);
	color: var(--co-ink-faint);
}
.co-lock > svg { flex: 0 0 auto; }
.co-lock-body { flex: 1 1 auto; min-width: 0; }
.co-lock-label {
	display: block;
	color: var(--co-ink-soft);
	font-size: .74rem;
	font-weight: 650;
	text-transform: uppercase;
	letter-spacing: .06em;
}
.co-lock-value {
	display: block;
	color: var(--co-ink);
	font-weight: 500;
}
.co-lock-why {
	flex: 0 1 auto;
	max-width: 280px;
	font-size: .78rem;
	text-align: right;
}
/* On a phone the reason belongs under the value, not squeezed beside it. */
@media only screen and (max-width: 700px) {
	.co-lock { align-items: flex-start; flex-wrap: wrap; }
	.co-lock-why { flex: 1 1 100%; max-width: none; text-align: left; }
}

/* ---------------------------------------------------------------- fields --- */

.co-fields {
	display: grid;
	/* minmax(0,...) - a bare 1fr will not shrink below an input's min-content width */
	grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
	gap: 14px;
}
.co-fields.is-wide {
	grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}
/*
 * Exactly four across on a wide row, and it holds that grouping down to a tablet.
 *
 * Two things are going on. Raising the track floor to a quarter of the row (minus its
 * three gaps) means auto-fit can never fit a FIFTH column, so four fields stay four
 * rather than becoming five-and-a-bit on a large monitor.
 *
 * The 150px is the other half, and it is lower than .co-fields' own 210px ON PURPOSE.
 * 210px is sized for long values - a school name with its id - and at a tablet width it
 * let a four-field row collapse to three, stranding the fourth field alone on a second
 * line. This modifier is for rows of SHORT values, name parts being the case it was
 * written for, where 150px is comfortable: measured, "Bapusaheb" needs about 95px
 * including the padding. Four across now survives to roughly 640px of row.
 *
 * So do NOT use this for a four-field row of long values - it would squeeze them.
 * Below 640px it steps down to three, two and finally one column as usual.
 */
.co-fields.is-4up {
	grid-template-columns:
		repeat(auto-fit, minmax(max(150px, calc((100% - 3 * 14px) / 4)), 1fr));
}
/*
 * Four fields halve to two, then to one - they never sit at THREE.
 *
 * auto-fit alone cannot express that: it steps down one column at a time, so between
 * roughly 550 and 700px it fits exactly three tracks and strands the fourth field alone
 * on a second line. Three-of-four is the one arrangement that always looks like a
 * mistake, so the two narrow steps are stated outright instead of being left to the
 * track maths.
 *
 * These widths are VIEWPORT, and that is sound here only because both are below the
 * 992px point where the sidebar leaves the flow - so viewport minus the 60px of page
 * padding IS the row width. Do not copy these numbers into a rule that can apply while
 * the sidebar is showing; there the row is 230px narrower than the viewport.
 */
@media only screen and (max-width: 710px) {
	.co-fields.is-4up { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media only screen and (max-width: 400px) {
	.co-fields.is-4up { grid-template-columns: minmax(0, 1fr); }
}
/*
 * Field rows that must stay grouped.
 *
 * A single .co-fields grid packs by available width, so where the line breaks is an
 * accident of the viewport. When the grouping itself is the design - names on one row,
 * contact details on the next - use one .co-fields per row inside this, and each wraps
 * independently. Same 14px rhythm as the grid gap, so the rows are evenly spaced.
 */
.co-fieldrows {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.co-field { min-width: 0; }
.co-field.is-span2 { grid-column: span 2; }

.co-label {
	display: block;
	margin-bottom: 5px;
	color: var(--co-ink-soft);
	font-size: .74rem;
	font-weight: 650;
	text-transform: uppercase;
	letter-spacing: .06em;
}
.co-req { margin-left: 2px; color: var(--co-bad); }
.co-opt {
	margin-left: 4px;
	color: var(--co-ink-faint);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
}
.co-fieldnote {
	margin-top: 4px;
	color: var(--co-ink-faint);
	font-size: .78rem;
}
.co-fielderr {
	display: block;
	margin-top: 4px;
	color: var(--co-bad);
	font-size: .78rem;
	font-weight: 600;
}
.co-fielderr:empty { display: none; }

.co-in,
.co-sel {
	display: block;
	width: 100%;
	min-height: 44px;
	padding: 9px 11px;
	border: 1px solid var(--co-line-firm);
	border-radius: var(--co-radius-sm);
	background-color: var(--co-card);
	color: var(--co-ink);
	font: inherit;
	/* 16px stops iOS Safari zooming the whole page in the moment a field is focused */
	font-size: 16px;
	-webkit-appearance: none;
	appearance: none;
	transition: border-color .13s ease, background-color .13s ease, box-shadow .13s ease;
}
.co-sel {
	padding-right: 36px;
	/* background-COLOR above, image here - see the note at the top of this file */
	background-image: var(--co-chev);
	background-repeat: no-repeat;
	background-position: right 13px center;
	cursor: pointer;
}
.co-in:hover:not(:disabled),
.co-sel:hover:not(:disabled) {
	border-color: #aab8c9;
	background-color: #fbfcfe;
}
.co-in:focus,
.co-sel:focus {
	outline: none;
	border-color: var(--co-accent);
	box-shadow: 0 0 0 3px rgba(67,97,238,.18);
}
.co-sel:focus {
	background-image: var(--co-chev-accent);
	background-repeat: no-repeat;
	background-position: right 13px center;
}
.co-sel:disabled { background-image: none; padding-right: 12px; }
.co-in:disabled,
.co-sel:disabled {
	background-color: #f2f5f9;
	color: var(--co-ink-faint);
	cursor: not-allowed;
}
.co-in.is-bad,
.co-sel.is-bad { border-color: var(--co-bad); background-color: #fff; }
.co-in::placeholder { color: var(--co-ink-faint); }

textarea.co-in { min-height: 78px; resize: vertical; line-height: 1.45; }

/* --------------------------------------------------------------- buttons --- */

.co-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	min-height: 42px;
	padding: 9px 15px;
	border: 1px solid var(--co-line-firm);
	border-radius: var(--co-radius-sm);
	background-color: var(--co-card);
	color: var(--co-ink);
	font: inherit;
	font-size: .9rem;
	font-weight: 600;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}
.co-btn:hover:not(:disabled) { background-color: #f1f5fa; border-color: #aab8c9; color: var(--co-ink); text-decoration: none; }
.co-btn:focus-visible { outline: 3px solid rgba(67,97,238,.4); outline-offset: 1px; }
.co-btn:disabled { opacity: .55; cursor: not-allowed; }

.co-btn-primary {
	border-color: var(--co-accent);
	background-color: var(--co-accent);
	color: #fff;
}
.co-btn-primary:hover:not(:disabled) {
	border-color: var(--co-accent-dark);
	background-color: var(--co-accent-dark);
	color: #fff;
}
.co-btn-danger {
	border-color: #f0bcbc;
	background-color: #fff;
	color: var(--co-bad);
}
.co-btn-danger:hover:not(:disabled) { background-color: var(--co-bad-soft); border-color: var(--co-bad); color: var(--co-bad); }
.co-btn-lg { min-height: 48px; padding: 11px 22px; font-size: .95rem; }
.co-btn-sm { min-height: 34px; padding: 5px 11px; font-size: .82rem; }

.co-btn-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px; height: 36px;
	padding: 0;
	border: 1px solid transparent;
	border-radius: var(--co-radius-sm);
	background-color: transparent;
	color: var(--co-ink-soft);
	cursor: pointer;
}
.co-btn-icon:hover { background-color: #eef2f8; color: var(--co-ink); }

/* ------------------------------------------------------ searchable picker --- */
/* Behaviour, and why the native <select> stays underneath, is documented in
   assets/js/co-ui-v2.js. */

.co-combo { position: relative; }
/* an open picker has to clear anything sticky above it */
.co-combo.is-open { z-index: 40; }
.co-combo-native { display: none !important; }

.co-combo-btn {
	display: flex;
	align-items: center;
	width: 100%;
	text-align: left;
}
.co-combo-val {
	display: block;
	width: 100%;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}
.co-combo-btn.is-placeholder .co-combo-val { color: var(--co-ink-faint); }
.co-combo.is-open .co-combo-btn {
	border-color: var(--co-accent);
	box-shadow: 0 0 0 3px rgba(67,97,238,.18);
	background-image: var(--co-chev-accent);
	background-repeat: no-repeat;
	background-position: right 13px center;
}

.co-combo-pop {
	position: absolute;
	top: 100%; left: 0; right: 0;
	margin-top: 4px;
	border: 1px solid var(--co-line-firm);
	border-radius: 10px;
	background: var(--co-card);
	box-shadow: 0 14px 34px rgba(15,23,42,.18);
	overflow: hidden;
}
.co-combo-pop.is-hidden { display: none; }
.co-combo-search {
	padding: 8px;
	border-bottom: 1px solid var(--co-line);
	background: #f8fafc;
}
.co-combo-search.is-hidden { display: none; }
.co-combo-q {
	width: 100%;
	min-height: 40px;
	padding: 8px 11px;
	border: 1px solid var(--co-line-firm);
	border-radius: var(--co-radius-sm);
	background-color: var(--co-card);
	color: var(--co-ink);
	font: inherit;
	font-size: 16px;
}
.co-combo-q:focus {
	outline: none;
	border-color: var(--co-accent);
	box-shadow: 0 0 0 3px rgba(67,97,238,.18);
}
.co-combo-list {
	/*
	 * POSITIONED ON PURPOSE, and load-bearing. The keyboard handler scrolls the active
	 * row into view with item.offsetTop, which is measured against the nearest
	 * POSITIONED ancestor. Static, that ancestor is .co-combo-pop, so every offset comes
	 * back with the search box height added and the list scrolls past the row it is
	 * trying to show.
	 */
	position: relative;
	max-height: 264px;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}
.co-combo-item {
	padding: 11px 13px;
	border-bottom: 1px solid #f1f5f9;
	font-size: .9rem;
	line-height: 1.35;
	cursor: pointer;
}
.co-combo-item:last-child { border-bottom: 0; }
.co-combo-item:hover,
.co-combo-item.is-active {
	background-color: var(--co-accent-soft);
	color: var(--co-accent-dark);
}
.co-combo-none { padding: 16px 13px; color: var(--co-ink-faint); font-size: .85rem; }
.co-combo-none.is-hidden { display: none; }

/* ----------------------------------------------------------------- table --- */

.co-tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.co-table {
	width: 100%;
	border-collapse: separate;
	border-spacing: 0;
	font-size: .9rem;
}
.co-table th {
	padding: 10px 12px;
	border-bottom: 1px solid var(--co-line);
	background: #f8fafc;
	text-align: left;
	font-size: .68rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .05em;
	color: var(--co-ink-soft);
	white-space: nowrap;
}
.co-table td {
	padding: 11px 12px;
	border-bottom: 1px solid #f1f5f9;
	vertical-align: middle;
}
.co-table tbody tr:last-child td { border-bottom: 0; }
.co-table tbody tr:hover td { background: #fafbfe; }
.co-table .co-num {
	color: var(--co-ink-faint);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}
.co-table .co-name { font-weight: 600; }
.co-table .co-actions { text-align: right; white-space: nowrap; }
.co-table .co-actions .co-btn { margin-left: 4px; }

/* ------------------------------------------------------- row actions menu ---
 *
 * One button per row instead of two to four. The lists had grown past what the
 * width allows: schools carried Edit + Reset + Delete and still overflowed and
 * scrolled sideways at 1900px, with the Actions column itself cut off - so the
 * controls a row exists to offer were the part you could not reach.
 *
 * THE POPUP IS position: fixed, AND THAT IS NOT A STYLE CHOICE. It lives inside
 * .co-tablewrap, which is `overflow-x: auto` - a scroll container clips any
 * absolutely-positioned descendant, so an absolute menu would be cut off at the
 * table's edge, which is exactly the problem this component is here to solve. A
 * fixed element's containing block is the viewport, so it escapes that clip.
 * co-ui-v2.js sets top/left from the button's rect on open, and closes the menu
 * on scroll rather than trying to follow it - a menu is a momentary thing and
 * chasing the scroll costs a listener on every frame.
 *
 * z-index sits above the sticky save bar (20) and the combo popup (40), per the
 * elevation note in .agents/rules/ui_component_invariants.md, and the background
 * is explicitly opaque so nothing bleeds through from the row beneath.
 */
.co-rowmenu { position: relative; display: inline-block; }
.co-rowmenu-pop {
	position: fixed;
	z-index: 120;
	min-width: 190px;
	padding: 6px;
	border: 1px solid var(--co-line-firm);
	border-radius: var(--co-radius-sm);
	background: var(--co-card);
	box-shadow: 0 14px 34px rgba(15, 23, 42, .18);
	text-align: left;
	white-space: normal;
}
.co-rowmenu-pop.is-hidden { display: none; }
.co-rowmenu-item {
	display: block;
	width: 100%;
	padding: 9px 11px;
	border: 0;
	border-radius: 6px;
	background: none;
	font: inherit;
	font-size: .9rem;
	color: var(--co-ink);
	text-align: left;
	text-decoration: none;
	cursor: pointer;
}
.co-rowmenu-item i { width: 15px; margin-right: 8px; color: var(--co-ink-faint); }
.co-rowmenu-item:hover,
.co-rowmenu-item:focus { background: var(--co-accent-soft); color: var(--co-accent-dark); outline: none; }
.co-rowmenu-item:hover i,
.co-rowmenu-item:focus i { color: var(--co-accent-dark); }
.co-rowmenu-item.is-danger { color: var(--co-bad); }
.co-rowmenu-item.is-danger i { color: var(--co-bad); }
.co-rowmenu-item.is-danger:hover,
.co-rowmenu-item.is-danger:focus { background: var(--co-bad-soft); color: var(--co-bad); }
/* A blocked action stays VISIBLE and says why on hover, rather than vanishing -
   "why can I not delete this?" is the question the row has to answer. */
.co-rowmenu-item[disabled] { color: var(--co-ink-faint); cursor: not-allowed; }
.co-rowmenu-item[disabled]:hover { background: none; color: var(--co-ink-faint); }
/*
 * WHY A DISABLED ITEM GETS A VISIBLE NOTE AND NOT A title=.
 *
 * The centre list greys out Delete while anything still points at the centre, and the
 * reason used to live only in a title attribute on the disabled <button>. Browsers do
 * not reliably show a tooltip on a disabled control at all, and inside a popover menu
 * nobody thinks to hover one - so the honest refusal read as a broken button. It was
 * reported as exactly that: "delete button is not active even when there are 0 student
 * and 0 school" - because the blocker was the teacher count, which has no column.
 *
 * The note sits under the item it explains, indented to the item's text so it reads as
 * that item's reason rather than as another choice.
 */
.co-rowmenu-note {
	padding: 2px 12px 8px 35px;
	max-width: 250px;
	color: var(--co-ink-faint);
	font-size: .74rem;
	line-height: 1.35;
	white-space: normal;
}
.co-rowmenu-sep { height: 1px; margin: 5px 4px; background: var(--co-line); }

/* the student id, which people read out and type into other systems */
.co-id {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: .86rem;
	font-weight: 600;
}

.co-badge {
	display: inline-block;
	padding: 2px 8px;
	border-radius: 999px;
	background: #eef2f8;
	color: var(--co-ink-soft);
	font-size: .74rem;
	font-weight: 650;
	white-space: nowrap;
}
.co-badge.is-accent { background: var(--co-accent-soft); color: var(--co-accent-dark); }

/* the masked password cell */
.co-pw {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: .86rem;
}
.co-pw-value { letter-spacing: .06em; }
.co-pw-btn {
	border: 0;
	background: transparent;
	color: var(--co-ink-faint);
	cursor: pointer;
	padding: 4px;
	line-height: 1;
}
.co-pw-btn:hover { color: var(--co-accent); }

/* The filter panel's fold-away control. Hidden here and shown only inside the
   small-screen media query at the end of this file - on a desktop the panel is always
   open, so a button that collapses it is a button with nothing to do. */
.co-filter-toggle { display: none; }
.co-filter-summary {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	color: var(--co-ink-faint);
	font-size: .82rem;
}

/* ----------------------------------------------------------- empty state --- */

.co-empty {
	padding: 38px 20px;
	text-align: center;
	color: var(--co-ink-soft);
}
.co-empty-icon { font-size: 1.9rem; color: var(--co-line-firm); margin-bottom: 8px; }
.co-empty b { display: block; margin-bottom: 4px; color: var(--co-ink); font-size: 1rem; }
.co-empty p { margin: 0 auto; max-width: 420px; font-size: .88rem; }

/* ----------------------------------------------------------------- pager --- */

.co-pager {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	padding: 12px 16px;
	border-top: 1px solid var(--co-line);
	background: #fbfcfe;
	font-size: .86rem;
	color: var(--co-ink-soft);
}
.co-pager-count { flex: 1 1 auto; }
.co-pager-count b { color: var(--co-ink); font-variant-numeric: tabular-nums; }
.co-pager-nav { display: flex; gap: 6px; }

/* ----------------------------------------------------------------- stats --- */

.co-stats { display: flex; flex-wrap: wrap; gap: 8px; }
.co-stat {
	display: inline-flex;
	align-items: baseline;
	gap: 5px;
	padding: 5px 11px;
	border-radius: 999px;
	background: #eef2f8;
	color: var(--co-ink-soft);
	font-size: .82rem;
}
.co-stat b { color: var(--co-ink); font-size: .95rem; font-variant-numeric: tabular-nums; }

/*
 * The stats strip carries no margin of its own anywhere else, because until now
 * nothing used it. Given one here so it does not butt against the panel below it.
 */
.cov2 .co-stats { margin: 0 0 16px; }

/*
 * Two small helpers shared by the centre, school and teacher lists.
 *
 * .co-cell-clamp is for the free-text columns those tables carry: a name, a centre or
 * school name, a head master, a postal address. Every one of them accepts up to 150
 * characters and some are typed that long.
 *
 * WITHOUT IT THE DAMAGE IS NOT LOCAL TO THE LONG ROW. Measured at 1280px with a
 * 146-character centre name: nothing overflowed and no scrollbar appeared - instead
 * three columns wrapped the value into a stack of one-word lines and every row in
 * the table became 239px tall, including the rows whose own values were short,
 * because a centre name repeats down the whole page. Six schools filled the screen.
 *
 * So it is applied to all of them, on all three lists. The full text stays in the
 * cell's title attribute, and the clamp is lifted on small screens, where each cell
 * is already its own line in a card and has the room.
 *
 * TWO LINES, NOT ONE, AND THAT CHANGE MATTERS MORE THAN IT LOOKS. This was
 * `white-space: nowrap` with an ellipsis, so a value was cut at 260px on a single
 * line - and these names truncate from the RIGHT, which is precisely where the part
 * that tells them apart lives. A whole page of centres reading "Zilha Parishad
 * Primary School Wa..." is not a shortened label, it is the same label repeated: the
 * column stops carrying any information at all. Measured against the real data, one
 * line was not enough for even an ordinary centre name.
 *
 * Wrapping to two lines buys that back WITHOUT asking for a pixel more width, which
 * these tables have none of - the schools list already overflows and scrolls
 * sideways at 1900px. The bound is what keeps the original problem fixed: measured at
 * 1500px with the 147-character name on all six rows, one line gives 43px rows and a
 * 293px table, two lines gives 63px and 413px, and the unbounded wrap this clamp was
 * written to prevent gave 239px rows. So it costs one line in the worst case and
 * nothing at all in the normal one, where a name that fits stays on a single line.
 *
 * The clamp has to live on an inner element rather than the cell: -webkit-line-clamp
 * needs `display: -webkit-box`, and a <td> given that display stops being a table
 * cell and takes the column layout down with it. Hence .co-clamp2 and the wrapping
 * span in the markup. Anything outside that span - the "via center" badge - is left
 * unclamped on purpose, so a long name can never push the badge out of view.
 *
 * .co-muted is for a value that is real but empty - a centre with no schools yet
 * reads "0", and it should not carry the same weight as a number worth clicking.
 */
.co-table .co-cell-clamp {
	max-width: 260px;
	white-space: normal;
}
.co-table .co-cell-clamp > .co-clamp2 {
	display: -webkit-inline-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
	overflow-wrap: anywhere;
	vertical-align: top;
	max-width: 260px;
}
.cov2 .co-muted { color: var(--co-ink-faint); }

/* ------------------------------------------------------------------ grid --- */

/*
 * The entry grid: a table whose cells are inputs, for typing a list of people off a
 * sheet of paper. Used by add-bulk-teachers-v2.php.
 *
 * WHY NOT REUSE .bsv2-* FROM bulk-students-v2.css. That file is a second, older copy
 * of this whole design system, built before co-v2.css existed. It is 46KB, it has been
 * through five rounds of testing on the owner's phone, and the standing decision is
 * that it keeps its copy and everything new uses this one. Pointing a new page at it
 * would couple the teacher grid to the student page's stylesheet for good.
 *
 * The grid stays a real <table> on a desktop, because entering a list means reading
 * DOWN a column and a stack of cards cannot be read that way. Below 860px it becomes
 * cards like every other .co-table, since a six-column grid on a 360px phone is
 * unusable however it is styled.
 */
.co-grid {
	width: 100%;
	border-collapse: collapse;
	font-size: .9rem;
}
.co-grid th {
	padding: 8px 10px;
	border-bottom: 1px solid var(--co-line-firm);
	background: var(--co-bg);
	color: var(--co-ink-soft);
	font-size: .78rem;
	font-weight: 650;
	text-align: left;
	white-space: nowrap;
}
.co-grid td {
	padding: 5px 6px;
	border-bottom: 1px solid var(--co-line);
	vertical-align: middle;
}
.co-grid tbody tr:last-child td { border-bottom: 0; }

/* The row number. Tabular figures so 9 and 10 do not shift the column. */
.co-grid .co-gn {
	width: 1%;
	padding-left: 12px;
	color: var(--co-ink-faint);
	font-size: .8rem;
	font-variant-numeric: tabular-nums;
	text-align: right;
}
.co-grid .co-gact { width: 1%; padding-right: 10px; text-align: right; }

/* Inputs inside the grid carry no border of their own - the cell is the border.
   Anything else and forty rows read as forty stacked boxes. */
.co-grid .co-gin,
.co-grid .co-gsel {
	width: 100%;
	min-width: 0;
	padding: 7px 8px;
	border: 1px solid transparent;
	border-radius: var(--co-radius-sm);
	background: transparent;
	color: var(--co-ink);
	font: inherit;
}
.co-grid .co-gin:hover,
.co-grid .co-gsel:hover { border-color: var(--co-line); }
.co-grid .co-gin:focus,
.co-grid .co-gsel:focus {
	border-color: var(--co-accent);
	background: var(--co-card);
	box-shadow: 0 0 0 3px var(--co-accent-soft);
	outline: none;
}
.co-grid .co-gsel {
	appearance: none;
	-webkit-appearance: none;
	padding-right: 26px;
	background-image: var(--co-chev);
	background-repeat: no-repeat;
	background-position: right 8px center;
}
/* A cell the server rejected. The row is tinted too, so the bad row is findable when
   scrolled past - a single red border on one input is not. */
.co-grid .co-gin.is-bad,
.co-grid .co-gsel.is-bad { border-color: var(--co-bad); background: var(--co-bad-soft); }
.co-grid tr.is-bad { background: var(--co-bad-soft); }

.co-gridfoot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	padding: 11px 13px;
	border-top: 1px solid var(--co-line);
	background: var(--co-bg);
}
.co-gridfoot .co-hint { color: var(--co-ink-faint); font-size: .8rem; }

/*
 * The save bar sticks to the bottom of the viewport, because the Save button belongs
 * where your hands are after typing forty rows - not below them, reachable only by
 * scrolling past everything you just entered.
 */
.co-savebar {
	position: sticky;
	bottom: 0;
	z-index: 20;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin-top: 16px;
	padding: 11px 14px;
	border: 1px solid var(--co-line);
	border-radius: var(--co-radius);
	background: var(--co-card);
	box-shadow: 0 -2px 10px rgba(16,24,40,.07);
}
.co-savebar-count { flex: 1 1 auto; color: var(--co-ink-soft); font-size: .86rem; }
.co-savebar-count b { color: var(--co-ink); font-variant-numeric: tabular-nums; }

.co-kbd {
	display: inline-block;
	padding: 1px 5px;
	border: 1px solid var(--co-line-firm);
	border-bottom-width: 2px;
	border-radius: 4px;
	background: var(--co-card);
	font-family: inherit;
	font-size: .78rem;
}

/* ---------------------------------------------------------- confirm veil --- */

.co-modal {
	position: fixed;
	/* long-hand, not inset:0 - see the note at the top of this file */
	top: 0; right: 0; bottom: 0; left: 0;
	z-index: 1100;              /* above the legacy header's 1039 */
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 16px;
	background: rgba(15,23,42,.55);
}
.co-modal.is-hidden { display: none; }
.co-modal-box {
	width: 100%;
	max-width: 460px;
	max-height: 90vh;
	display: flex;
	flex-direction: column;
	border-radius: 12px;
	background: var(--co-card);
	box-shadow: 0 20px 50px rgba(15,23,42,.3);
	overflow: hidden;
}
.co-modal-head {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 14px 16px;
	border-bottom: 1px solid var(--co-line);
}
.co-modal-head h2 { margin: 0; flex: 1 1 auto; font-size: 1rem; font-weight: 650; }
.co-modal-body { padding: 16px; overflow-y: auto; font-size: .92rem; }
.co-modal-foot {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	gap: 8px;
	padding: 13px 16px;
	border-top: 1px solid var(--co-line);
	background: var(--co-bg);
}

.co-veil {
	position: fixed;
	top: 0; right: 0; bottom: 0; left: 0;
	z-index: 1200;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 14px;
	background: rgba(255,255,255,.86);
	color: var(--co-ink);
	font-weight: 600;
}
.co-veil.is-hidden { display: none; }
.co-spin {
	width: 34px; height: 34px;
	border: 3px solid var(--co-line-firm);
	border-top-color: var(--co-accent);
	border-radius: 50%;
	animation: co-spin .7s linear infinite;
}
@keyframes co-spin { to { transform: rotate(360deg); } }

/* =============================================================================
 * SMALL SCREENS
 *
 * The table becomes a list of cards. A ten-column table inside a horizontally
 * scrolling box on a 360px phone is technically "responsive" and practically
 * unusable - you cannot see a name and its actions at the same time.
 *
 * Cells are addressed by data-col, never :nth-child, so adding a column later cannot
 * shuffle the layout.
 * ============================================================================= */

@media (max-width: 860px) {

	.co-head h1 { font-size: 1.15rem; }
	.co-head-actions { width: 100%; }
	.co-head-actions .co-btn { flex: 1 1 auto; }

	.co-panel-body { padding: 13px; }
	.co-fields { gap: 12px; }
	.co-field.is-span2 { grid-column: span 1; }

	.co-tablewrap { overflow-x: visible; }

	.co-table,
	.co-table tbody,
	.co-table tr,
	.co-table td { display: block; width: 100%; }
	.co-table thead { display: none; }

	.co-table tr {
		position: relative;
		margin: 0 0 10px;
		padding: 12px 13px;
		border: 1px solid var(--co-line);
		border-radius: var(--co-radius-sm);
		background: var(--co-card);
	}
	.co-table tbody tr:hover td { background: transparent; }

	.co-table td {
		padding: 2px 0;
		border: 0;
	}
	/*
	 * The label the <th> used to supply, put back per cell.
	 *
	 * padding-right, NOT a trailing space in the content string. `attr(data-label) " "`
	 * looks like it separates the two, and it does right up until the label is wider
	 * than the min-width - at which point the inline-block shrink-wraps, the browser
	 * trims the trailing whitespace at its edge, and the value is welded to the label:
	 * "SCHOOL CODE110556001", "HEAD MASTERiujh". Padding cannot be trimmed.
	 */
	.co-table td[data-label]::before {
		content: attr(data-label);
		display: inline-block;
		min-width: 84px;
		padding-right: 10px;
		color: var(--co-ink-faint);
		font-size: .72rem;
		font-weight: 650;
		text-transform: uppercase;
		letter-spacing: .04em;
	}

	/* the name is the heading of the card, so it loses its label and gains size */
	/*
	 * The entry grid becomes cards too. Its inputs get a visible border back: without
	 * the table cell around them a borderless input on a card is invisible, which on
	 * the bulk student grid showed up as an unlabelled column of nothing.
	 */
	.co-grid, .co-grid tbody, .co-grid tr, .co-grid td { display: block; width: 100%; }
	.co-grid thead { display: none; }
	.co-grid tr {
		margin: 0 12px 12px;
		padding: 8px 0 4px;
		border: 1px solid var(--co-line);
		border-radius: var(--co-radius-sm);
		background: var(--co-card);
	}
	.co-grid td { border-bottom: 0; padding: 4px 10px; }
	.co-grid td[data-label]::before {
		content: attr(data-label) " ";
		display: block;
		margin-bottom: 2px;
		color: var(--co-ink-faint);
		font-size: .72rem;
		font-weight: 650;
		text-transform: uppercase;
		letter-spacing: .05em;
	}
	/*
	 * THE REQUIRED MARKER, PUT BACK. The asterisk lived only in the <th>, and the
	 * header is display:none here - so on a phone, which is where the bulk grid is
	 * most used, nothing said which of the seven fields could not be left blank.
	 * The cell label carries it now. The inputs also carry aria-required, which the
	 * header asterisk never provided at any width.
	 */
	.co-grid td.is-req[data-label]::before { content: attr(data-label) " *"; }

	.co-grid .co-gn,
	.co-grid .co-gact { width: auto; text-align: left; padding-left: 10px; }
	.co-grid .co-gn::before,
	.co-grid .co-gact::before { content: none; }
	.co-grid .co-gin,
	.co-grid .co-gsel { border-color: var(--co-line); background: var(--co-card); }

	/* the address has a whole line to itself in a card, so let it wrap */
	.co-table .co-cell-clamp {
		max-width: none;
		white-space: normal;
	}
	/* ...and the two-line cap goes with it, for the same reason: in a card the value
	   is on its own row with the full width of the screen, so there is nothing to
	   protect the layout from. Undo the line clamp rather than leave a card quietly
	   hiding the end of an address. */
	.co-table .co-cell-clamp > .co-clamp2 {
		display: inline;
		-webkit-line-clamp: unset;
		line-clamp: unset;
		max-width: none;
		overflow: visible;
	}

	.co-table td[data-col="name"] {
		margin-bottom: 6px;
		padding-right: 40px;      /* clear of the row number in the corner */
		font-size: 1rem;
		font-weight: 650;
	}
	.co-table td[data-col="name"]::before { content: none; }

	.co-table td[data-col="n"] {
		position: absolute;
		/* left of the actions button, which now owns the corner */
		top: 16px; right: 56px;
		/*
		 * width:auto UNDOES the `.co-table td { width: 100% }` above, and it is not
		 * cosmetic. An absolutely positioned box that is still 100% wide is 100% of its
		 * containing block, so `right` pushed its LEFT edge off the card and the row
		 * number rendered outside the card entirely, over the page background.
		 */
		width: auto;
		padding: 0;
		font-size: .74rem;
	}
	.co-table td[data-col="n"]::before { content: none; }

	/*
	 * THE ACTIONS BUTTON SITS IN THE TOP-RIGHT CORNER, not in a row of its own at the
	 * foot of the card.
	 *
	 * It used to be a full-width block with a top border, which cost about 60px of the
	 * 740px a phone has - a whole field's worth per card, on a list where the point is
	 * to see as many records as possible without scrolling. In the corner it costs
	 * nothing: it sits in the space beside the first line, which was empty.
	 *
	 * It is also the easier place to reach. A thumb on a phone held one-handed covers
	 * the top-right corner comfortably; the bottom-left of a card halfway down a long
	 * scroll is the worst spot on the screen for it.
	 */
	.co-table td[data-col="actions"] {
		position: absolute;
		top: 8px; right: 10px;
		width: auto;          /* same trap as the row number above */
		margin: 0;
		padding: 0;
		border-top: 0;
		text-align: right;
	}
	.co-table td[data-col="actions"]::before { content: none; }
	.co-table td[data-col="actions"] .co-btn {
		margin: 0;
		min-height: 38px;
	}

	/*
	 * THE FIRST LINE KEEPS CLEAR OF THAT CORNER. Whichever cell leads the card - the id
	 * on three of the lists, the name on the teacher list - is the one that would run
	 * under the button.
	 */
	.co-table td[data-col="id"],
	.co-table td[data-col="code"],
	.co-table td[data-col="name"] { padding-right: 96px; }

	/*
	 * TWO SHORT FIELDS TO A ROW.
	 *
	 * A count, a standard, a medium, a district - none of them needs 360px, and giving
	 * each one a full line was what made these cards four screens long. The short ones
	 * are half-width and flex-wrap pairs them up: schools beside students, district
	 * beside taluka, std beside medium, contact beside password.
	 *
	 * FLEX RATHER THAN GRID, deliberately. Grid is Chrome 57; this panel still serves
	 * Android WebViews below Chrome 41, where an unknown `display` value is ignored and
	 * the rows keep the `display: block` set above - which is exactly today's layout.
	 * The pairing is the enhancement, and its absence is not a broken page.
	 */
	.co-table tbody tr { display: flex; flex-wrap: wrap; }
	.co-table tbody td { flex: 0 0 100%; }

	.co-table tbody td[data-col="schools"],
	.co-table tbody td[data-col="students"],
	.co-table tbody td[data-col="teachers"],
	.co-table tbody td[data-col="district"],
	.co-table tbody td[data-col="taluka"],
	.co-table tbody td[data-col="std"],
	.co-table tbody td[data-col="medium"],
	.co-table tbody td[data-col="contact"],
	.co-table tbody td[data-col="password"] {
		flex: 0 0 50%;
		max-width: 50%;
	}

	/* the absolute cells are out of the flex flow and must not claim a line */
	.co-table tbody td[data-col="n"],
	.co-table tbody td[data-col="actions"] { flex: 0 0 auto; }

	/*
	 * THE NAME LEADS THE CARD.
	 *
	 * The cells are in the table's column order, which on the centre list puts the two
	 * counts before the name - so a card opened with "SCHOOLS 4  STUDENTS 5" and only
	 * then said which centre that was. On a phone the name is the one thing being
	 * scanned for; everything else is detail you read once you have found the record.
	 *
	 * flex `order` rather than moving the cells, because these are real table columns
	 * and reordering the markup would reorder the DESKTOP table too - where the current
	 * order is right, and where the header row would then no longer match its cells.
	 */
	.co-table tbody td[data-col="id"],
	.co-table tbody td[data-col="code"]  { order: -2; }
	.co-table tbody td[data-col="name"]  { order: -1; }

	/*
	 * THE PICKER'S TICK BOX LEADS THE FIRST LINE, not a row of its own.
	 *
	 * As a full-width cell it landed in the MIDDLE of the card: a centred word SELECT
	 * with a checkbox under it, sitting between the school's name and its student
	 * count. That is the one part of a card where nothing else lives, it is the
	 * hardest place on a phone to hit accurately, and it cost a whole 44px line per
	 * school on a screen that has 740 of them.
	 *
	 * On the first line it is where a list's checkbox has always been: leading the
	 * record, left of its code, opposite the button in the far corner.
	 *
	 * THE LABEL GOES WITH IT. "SELECT" above a checkbox says nothing the checkbox does
	 * not, and the select-all box in the header row already names the column.
	 *
	 * A FIXED 30px SLOT so the codes line up down the card whatever is in it. A school
	 * with no students gets an em dash instead of a box - there is nothing to report
	 * on - and an auto-width slot would indent that card's code differently from its
	 * neighbours', which reads as a rendering fault rather than as a missing box.
	 */
	.co-table tbody td[data-col="tick"] {
		order: -3;
		flex: 0 0 30px;
		width: auto;
		max-width: none;
		align-self: center;      /* against the code line, not the top of it */
		margin: 0;
		padding: 0 8px 0 0;
	}
	.co-table tbody td[data-col="tick"]::before { content: none; }
	/*
	 * ...and the code SHARES that line rather than being pushed under it. Keyed off
	 * the tick's presence, so the four lists that have no tick column are untouched.
	 *
	 * flex-basis 0, NOT auto. With auto the cell asks for its content width, and a
	 * flex container breaks the line before it shrinks anything - so the code went to
	 * a line of its own and the tick sat alone above it, which is what the full-width
	 * cell did in the first place.
	 *
	 * AND A SMALLER RESERVE FOR THE CORNER BUTTON. 96px is what the other lists keep
	 * clear, measured for a cell that starts at the card edge; this one starts 30px in
	 * and then has to fit "SCHOOL CODE" plus nine digits, which at 360px is 163px of
	 * the 153px that was left - so the value wrapped under its own label. The button
	 * is 69px wide at right:10, so 76px clears it with room to spare and the line fits.
	 */
	.co-table tbody td[data-col="tick"] ~ td[data-col="code"] {
		flex: 1 1 0%;
		padding-right: 76px;
	}
	/* 18px is a mouse pointer's target. A thumb needs more, and the row has the room
	   now that the cell is not carrying a label. */
	.co-table tbody td[data-col="tick"] input[type="checkbox"] {
		width: 22px;
		height: 22px;
	}

	/*
	 * EVERY LABEL SITS ABOVE ITS VALUE. One rhythm down the whole card.
	 *
	 * Two earlier shapes were worse, and both were tried on this screen:
	 *
	 *   - label INLINE, value running after it. A long value wrapped back to the far
	 *     left under the label, so the centre name broke mid-phrase and finished hard
	 *     against the card edge. Nothing lined up with anything.
	 *   - label in a FIXED 94px column. That is enough for CENTER and not for
	 *     "SCHOOL CODE" or "HEAD MASTER", which wrapped to two lines of label; and a
	 *     94px column inside a 150px paired cell left the value overlapping its
	 *     neighbour - CONTACT's number was drawn straight through the word PASSWORD.
	 *
	 * Stacking has none of those failure modes at any width, for any label, in any
	 * language - which matters here, because these labels are one Marathi translation
	 * away from being half again as long. It costs one line per full-width field and
	 * buys a card with a single straight edge down the left.
	 */
	.co-table tbody td[data-label] { display: block; }
	.co-table tbody td[data-label]::before {
		display: block;
		min-width: 0;
		padding-right: 0;
		margin-bottom: 1px;
		line-height: 1.25;
	}

	/*
	 * THE ID LINE IS THE ONE EXCEPTION, and it earns it. "CENTER ID" and a four-digit
	 * number are short enough to sit together with room to spare beside the actions
	 * button, and stacked they spent a whole line on "1101". It is also the card's
	 * header rather than one of its fields, so reading as one line is what it should do.
	 * white-space: nowrap on the label because this is the only place a label shares a
	 * line with anything - everywhere else it has the width to itself.
	 *
	 * It has to come AFTER the general rule above: same specificity, so source order is
	 * what decides, and placed before it the general `display: block` simply won.
	 */
	.co-table tbody td[data-col="id"]::before,
	.co-table tbody td[data-col="code"]::before {
		display: inline-block;
		padding-right: 8px;
		margin-bottom: 0;
		white-space: nowrap;
	}


	/*
	 * THE TEACHER CARD, grouped like the student one.
	 *
	 * Its column order is name, school, center, contact, std, medium, students - which
	 * once the short cells pair up reads "CONTACT | STD" then "MEDIUM | STUDENTS",
	 * splitting the two halves of the same fact across two rows. Ordered here it reads
	 * name, then std beside medium, then the school and centre, then the contact beside
	 * the student count - the shape view-students-v2.php already has.
	 *
	 * Scoped to this one table by class, not applied globally: on the student list the
	 * same rule would pull `password` up above the school, because it has no `students`
	 * cell to pair with and would land in the wrong group.
	 */
	.co-table-tch tbody td[data-col="std"],
	.co-table-tch tbody td[data-col="medium"]   { order: 0; }
	.co-table-tch tbody td[data-col="school"],
	.co-table-tch tbody td[data-col="center"]   { order: 1; }
	.co-table-tch tbody td[data-col="contact"],
	.co-table-tch tbody td[data-col="students"] { order: 2; }

	/*
	 * THE FILTER PANEL FOLDS AWAY.
	 *
	 * Six stacked fields is 538px on a 375px screen - the whole first screen is filters
	 * and the first student sits below the fold, every single time the page is opened.
	 * On a phone it collapses to its head, which names what is currently filtering, and
	 * one tap opens it. On desktop there is room for all of it, so the toggle is not
	 * even rendered.
	 */
	.co-filter-toggle { display: inline-flex; }

	.co-pager { padding: 12px 13px; }
	.co-pager-count { width: 100%; }
	.co-pager-nav { width: 100%; }
	.co-pager-nav .co-btn { flex: 1 1 auto; }

	.co-combo-list { max-height: 46vh; }
	.co-combo-item { padding: 13px; font-size: .95rem; }
}

@media (max-width: 420px) {
	.co-panel-body { padding: 11px; }
	.co-table td[data-label]::before { min-width: 72px; }
}

/* Users who ask the OS for less motion get none of the spinner. */
@media (prefers-reduced-motion: reduce) {
	.co-spin { animation-duration: 3s; }
	.co-btn { transition: none; }
}

@media print {
	.co-head-actions, .co-pager-nav, .co-notice-x,
	.co-modal, .co-veil, .co-actions { display: none !important; }
	.co-panel { border: 0; box-shadow: none; }
	.co-tablewrap { overflow: visible; }
}
