@charset "UTF-8";
/* ==========================================================================
   SKYLED — Operations Console  ·  v3
   Candidate replacement for wtos/wtos-theme/css/style.css
   --------------------------------------------------------------------------
   Targets the LEGACY class vocabulary (.container/.leftside/.middle,
   .listTable, .borderTitle, .formClass, .textbox, .fWidth, .listHeader,
   .headertext, .submit, .searchButton, .cLegend…) so ~216 pages restyle
   without being edited.  [COMPAT] = overrides legacy inline attrs / layout.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS — light
   -------------------------------------------------------------------------- */
:root {
	/* Cobalt — chosen to sit with IBM Plex. Replaces legacy #00509F. */
	--blue-50:  #eff4ff;
	--blue-100: #dbe6ff;
	--blue-200: #bdd2ff;
	--blue-300: #90b3ff;
	--blue-400: #5d8bff;
	--blue-500: #3670f7;
	--blue-600: #0f62fe;   /* primary */
	--blue-700: #0b4ed1;
	--blue-800: #103fa1;
	--blue-900: #12377e;

	/* Sidebar — near-black with a blue undertone */
	--ink-950: #060a14;
	--ink-900: #0b1120;
	--ink-850: #10182b;
	--ink-800: #151f36;
	--ink-700: #1d2942;
	--ink-600: #2a3855;

	--n-0:   #ffffff;
	--n-25:  #fbfcfe;
	--n-50:  #f5f7fa;
	--n-100: #eef1f6;
	--n-150: #e3e8ef;
	--n-200: #d5dce6;
	--n-300: #b3bece;
	--n-400: #8492a6;
	--n-500: #61708a;
	--n-600: #475467;
	--n-700: #333f52;
	--n-800: #1f2937;
	--n-900: #0f172a;

	--ok:        #067a4b;
	--ok-bg:     #e2f6ed;
	--ok-br:     #a3ddc3;
	--warn:      #94550a;
	--warn-bg:   #fdf2de;
	--warn-br:   #efcf9c;
	--danger:    #c02620;
	--danger-bg: #fdecea;
	--danger-br: #f5c4c0;
	--info:      var(--blue-600);
	--info-bg:   var(--blue-50);
	--info-br:   var(--blue-200);
	--idle:      #5b6a80;
	--idle-bg:   #eef1f5;
	--idle-br:   #d5dce6;

	--surface:      var(--n-0);
	--surface-sub:  var(--n-25);
	--page:         var(--n-50);
	--border:       var(--n-150);
	--border-strong:var(--n-200);
	--text:         var(--n-800);
	--text-soft:    var(--n-500);
	--text-strong:  var(--n-900);

	--font-ui:   "IBM Plex Sans", "Segoe UI", Tahoma, sans-serif;
	--font-mono: "IBM Plex Mono", "Consolas", monospace;

	--fs-xs:  11px;  --fs-sm: 12px;  --fs-md: 13px;
	--fs-lg:  15px;  --fs-xl: 20px;  --fs-2xl: 28px;

	--s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
	--s-5: 20px; --s-6: 24px; --s-8: 32px; --s-10: 40px;

	--r-sm: 6px; --r: 9px; --r-lg: 13px;

	--sh-xs: 0 1px 2px rgba(15, 23, 42, .05);
	--sh-sm: 0 1px 3px rgba(15, 23, 42, .07), 0 1px 2px rgba(15, 23, 42, .04);
	--sh-md: 0 6px 16px rgba(15, 23, 42, .09), 0 2px 4px rgba(15, 23, 42, .05);
	--sh-lg: 0 20px 48px rgba(15, 23, 42, .18), 0 6px 14px rgba(15, 23, 42, .09);
	--sh-glow: 0 2px 10px rgba(15, 98, 254, .28);

	--sidebar-w: 250px;
	--topbar-h:  56px;
	--bottomnav-h: 58px;

	--ring: 0 0 0 3px rgba(15, 98, 254, .22);

	--t-fast: .12s cubic-bezier(.4, 0, .2, 1);
	--t:      .18s cubic-bezier(.4, 0, .2, 1);
	--t-slow: .32s cubic-bezier(.22, 1, .36, 1);
}

/* --------------------------------------------------------------------------
   1b. TOKENS — dark
   -------------------------------------------------------------------------- */
:root[data-theme="dark"] {
	--n-0:   #0f1522;
	--n-25:  #131a29;
	--n-50:  #0b1120;
	--n-100: #1a2333;
	--n-150: #232e42;
	--n-200: #2c3850;
	--n-300: #3d4b66;
	--n-400: #6b7a94;
	--n-500: #8f9db4;
	--n-600: #aab6c9;
	--n-700: #c6cfdd;
	--n-800: #e2e8f0;
	--n-900: #f4f7fb;

	--ok-bg:     #0d2b20;  --ok-br:     #1c5540;  --ok:     #46c48c;
	--warn-bg:   #2c2010;  --warn-br:   #5a441c;  --warn:   #e0a350;
	--danger-bg: #2e1414;  --danger-br: #5e2723;  --danger: #f0776f;
	--idle-bg:   #1a2333;  --idle-br:   #2c3850;  --idle:   #9aa8bf;
	--info-bg:   #10203f;  --info-br:   #1d3f78;

	--blue-50:  #10203f;
	--blue-100: #16294f;

	--surface:      #111827;
	--surface-sub:  #151d2e;
	--page:         #0b1120;
	--border:       #232e42;
	--border-strong:#2c3850;

	--sh-xs: 0 1px 2px rgba(0, 0, 0, .4);
	--sh-sm: 0 1px 3px rgba(0, 0, 0, .45), 0 1px 2px rgba(0, 0, 0, .3);
	--sh-md: 0 6px 16px rgba(0, 0, 0, .5), 0 2px 4px rgba(0, 0, 0, .35);
	--sh-lg: 0 20px 48px rgba(0, 0, 0, .6), 0 6px 14px rgba(0, 0, 0, .4);
}

/* --------------------------------------------------------------------------
   2. RESET
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
	margin: 0;
	background: var(--page);
	color: var(--text);
	font-family: var(--font-ui);
	font-size: var(--fs-md);
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	transition: background var(--t), color var(--t);
}

a { color: var(--blue-600); text-decoration: none; transition: color var(--t-fast); }
a:hover { color: var(--blue-500); }
img { max-width: 100%; border: 0; }

.ico { flex: 0 0 16px; width: 16px; height: 16px; }

:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--r-sm); }

.listTable td, .listTable th, .textbox, .amount, .mono,
input[type="text"], input[type="password"] {
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum" 1;
}

::selection { background: var(--blue-200); color: var(--blue-900); }

/* --------------------------------------------------------------------------
   3. MOTION PRIMITIVES
   -------------------------------------------------------------------------- */
@keyframes rise      { from { opacity: 0; transform: translateY(8px);  } to { opacity: 1; transform: none; } }
@keyframes fade      { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideDown { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }
@keyframes slideUp   { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes pop       { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
/* .sk-check's checkmark is a rotated border-corner, not a plain box -- reusing
   @keyframes pop's "to { transform: none }" end state (needed everywhere
   else pop is used) would wipe out that rotate(45deg) once the animation
   finishes, leaving an unrotated L-shape that reads as a stray glyph
   instead of a tick. */
@keyframes popCheck  { from { opacity: 0; transform: scale(.5) rotate(45deg); } to { opacity: 1; transform: rotate(45deg); } }
@keyframes growX     { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes shimmer   { from { background-position: -420px 0; } to { background-position: 420px 0; } }
@keyframes pulseDot  { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes barSlide  { from { left: -35%; } to { left: 100%; } }

/* Staggered page-load reveal — applied by app.js */
.sk-rise { animation: rise .42s cubic-bezier(.22,1,.36,1) both; }

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
		scroll-behavior: auto !important;
	}
}

/* Theme switching: suppress transitions for one frame, otherwise elements
   stay stuck on their old colour when the custom properties change. */
:root.sk-theming *,
:root.sk-theming *::before,
:root.sk-theming *::after {
	transition: none !important;
}

/* Top navigation progress bar */
.sk-progress {
	position: fixed; top: 0; left: 0; right: 0; height: 2px;
	background: transparent; z-index: 90; overflow: hidden; display: none;
}
.sk-progress.is-on { display: block; }
.sk-progress::after {
	content: ""; position: absolute; top: 0; bottom: 0; width: 35%;
	background: linear-gradient(90deg, transparent, var(--blue-500), var(--blue-300));
	animation: barSlide .9s ease-in-out infinite;
}

/* --------------------------------------------------------------------------
   4. [COMPAT] LEGACY LAYOUT → APP SHELL
   -------------------------------------------------------------------------- */
/* [COMPAT] 7 live pages (mif, invoiceReport, orders, purchase, service,
   serviceReport, vendor) carry an inline style="width:1300px" on this
   table. An inline style beats a class rule, so on those pages the page
   frame was 1300px inside a 1257px viewport and the WHOLE DOCUMENT
   scrolled sideways -- which cut the list table's own header off at the
   right edge. !important is the right tool here: the fixed pixel width is
   a leftover from a fixed-width layout the app no longer has. */
table.container,
table.container > tbody,
table.container > tbody > tr { display: block; width: 100% !important; border-collapse: collapse; }

/* [COMPAT] .container .leftside in the legacy style.css is (0,2,0)
   specificity -- td.leftside alone is (0,1,1) and loses on width. Qualify
   with .container to reach (0,2,1) so this wins regardless of load order,
   and !important the structural properties so a per-page inline
   style="..." attribute (1,344 of them exist across wtos/) cannot break
   the shell layout either. */
.container td.leftside, td.leftside {
	display: flex !important; flex-direction: column;
	position: fixed !important; top: 0 !important; left: 0 !important; bottom: 0 !important;
	width: var(--sidebar-w) !important;
	margin: 0 !important; padding: 0 !important;
	background: linear-gradient(175deg, var(--ink-850) 0%, var(--ink-950) 100%);
	border-right: 1px solid rgba(255,255,255,.05);
	z-index: 60;
	overflow: hidden;
}
/* subtle top glow so the sidebar has depth */
td.leftside::before {
	content: ""; position: absolute; top: -140px; left: -60px;
	width: 300px; height: 300px; border-radius: 50%;
	background: radial-gradient(circle, rgba(15,98,254,.30), transparent 70%);
	pointer-events: none;
}

/* [COMPAT] same specificity problem as .leftside above, plus per-page
   inline style="padding-left:5px; background-color:#FFFFFF" (seen on
   callReport.php and others) would otherwise win over any non-!important
   rule here. */
.container td.middle, td.middle {
	display: block !important; width: auto;
	margin: 0 !important; margin-left: var(--sidebar-w) !important;
	padding: calc(var(--topbar-h) + var(--s-6)) var(--s-6) var(--s-10) !important;
	min-height: 100vh;
	background: var(--page) !important;
}

/* --------------------------------------------------------------------------
   5. TOPBAR
   -------------------------------------------------------------------------- */
.sk-topbar {
	position: fixed; top: 0; left: var(--sidebar-w); right: 0;
	height: var(--topbar-h);
	display: flex; align-items: center; gap: var(--s-2);
	padding: 0 var(--s-6);
	background: color-mix(in srgb, var(--surface) 82%, transparent);
	backdrop-filter: saturate(180%) blur(14px);
	-webkit-backdrop-filter: saturate(180%) blur(14px);
	border-bottom: 1px solid var(--border);
	z-index: 50;
	transition: left var(--t), background var(--t), border-color var(--t);
}
.sk-topbar-spacer { flex: 1; }

/* centered in the topbar regardless of how wide the nav-toggle on its left
   or the date/refresh/account cluster on its right end up being -- those
   stay in the normal flex flow, this is pulled out of it so their widths
   can never throw its centering off */
.sk-topsearch { position: absolute; left: 50%; transform: translateX(-50%); width: 340px; max-width: 38vw; }
.sk-topsearch input {
	width: 100%; height: 34px;
	padding: 0 56px 0 34px;
	border: 1px solid var(--border-strong);
	border-radius: var(--r);
	background: var(--page);
	color: var(--text);
	font-family: var(--font-ui); font-size: var(--fs-sm);
	cursor: pointer;
	transition: background var(--t), border-color var(--t), box-shadow var(--t), width var(--t);
}
/* [FIX] the global ".textbox, input[type=text], select, ... { height:36px;
   padding: 0 var(--s-3) }" reset (line ~569) carries the same specificity
   as the plain rule above AND comes later in the file, so its !important
   was winning the tie and collapsing this input's padding to 12px both
   sides -- the search icon (positioned at left:10px) ended up sitting
   UNDER the typed-in text instead of clear of it, and long queries ran
   under the "Ctrl K" badge on the right. One extra class beats it outright
   regardless of source order. */
.sk-topbar .sk-topsearch input { height: 34px !important; padding: 0 56px 0 34px !important; }
.sk-topsearch input::placeholder { color: var(--n-400); }
.sk-topsearch input:hover { background: var(--surface); border-color: var(--n-300); }
.sk-topsearch input:focus {
	outline: none; background: var(--surface);
	border-color: var(--blue-400); box-shadow: var(--ring);
}
.sk-topsearch .ico {
	position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
	width: 15px; height: 15px; color: var(--n-400); pointer-events: none;
	transition: color var(--t);
}
.sk-topsearch input:focus ~ .ico { color: var(--blue-600); }
.sk-kbd {
	position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
	padding: 2px 6px;
	border: 1px solid var(--border-strong); border-bottom-width: 2px;
	border-radius: 5px;
	background: var(--surface);
	color: var(--n-400);
	font-family: var(--font-mono); font-size: 10px;
	pointer-events: none;
}

.sk-iconbtn {
	position: relative;
	display: grid; place-items: center;
	width: 34px; height: 34px;
	border: 1px solid transparent; border-radius: var(--r);
	background: transparent; color: var(--n-500);
	cursor: pointer;
	transition: background var(--t), color var(--t), transform var(--t-fast);
}
.sk-iconbtn:hover { background: var(--n-100); color: var(--text-strong); }
.sk-iconbtn:active { transform: scale(.94); }
/* in the topbar specifically (not the drawer header, where a ghost icon on
   a tinted background already reads fine) a fully transparent resting state
   looked like a stray icon rather than a button next to the bordered date
   text beside it -- a faint resting border+fill gives it the same button
   affordance the rest of the topbar chrome has. */
.sk-topbar .sk-iconbtn {
	border-color: var(--border);
	background: var(--surface-sub);
}
.sk-topbar .sk-iconbtn:hover { background: var(--n-100); border-color: var(--n-300); }

/* [FIX] this used to share the .sk-today class with the dashboard's
   "Today's Ops" card (a bordered, shadowed panel) -- applied to this plain
   date <span> instead it added a border and rounded corners with zero
   padding, so the text sat flush against its own border. Own class now,
   styled as what it actually is: quiet metadata text, not a card. */
.sk-topdate {
	color: var(--text-soft); font-size: var(--fs-sm); font-weight: 500;
	white-space: nowrap;
}
.sk-dot {
	position: absolute; top: 7px; right: 8px;
	width: 6px; height: 6px;
	border: 1.5px solid var(--surface); border-radius: 50%;
	background: var(--danger);
	animation: pulseDot 2.4s ease-in-out infinite;
}

.sk-user {
	display: flex; align-items: center; gap: var(--s-2);
	height: 34px; padding: 0 var(--s-2) 0 var(--s-1);
	border: 1px solid transparent; border-radius: var(--r);
	color: var(--n-700); font-size: var(--fs-sm);
	cursor: pointer;
	transition: background var(--t);
}
.sk-user:hover { background: var(--n-100); color: var(--text-strong); }
.sk-avatar {
	display: grid; place-items: center;
	width: 26px; height: 26px; border-radius: 8px;
	background: linear-gradient(140deg, var(--blue-400), var(--blue-700));
	color: #fff; font-size: 10px; font-weight: 600;
	box-shadow: var(--sh-glow);
}
.sk-user-meta { line-height: 1.2; font-weight: 500; }
.sk-user-meta small { display: block; color: var(--n-400); font-size: 10px; font-weight: 400; }

/* --------------------------------------------------------------------------
   6. SIDEBAR
   -------------------------------------------------------------------------- */
.sk-side-head {
	position: relative;
	display: flex; align-items: center; gap: var(--s-3);
	height: var(--topbar-h); padding: 0 var(--s-4);
	border-bottom: 1px solid rgba(255,255,255,.06);
	flex: 0 0 auto;
}
.sk-brand { display: flex; align-items: center; gap: var(--s-3); color: #fff; }
.sk-brand:hover { color: #fff; }
.sk-brand-mark {
	display: grid; place-items: center;
	width: 30px; height: 30px; border-radius: 9px;
	background: linear-gradient(140deg, var(--blue-400), var(--blue-700));
	color: #fff; font-size: var(--fs-sm); font-weight: 700;
	box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 3px 12px rgba(15,98,254,.45);
	transition: transform var(--t-slow), box-shadow var(--t);
}
.sk-brand:hover .sk-brand-mark { transform: rotate(-6deg) scale(1.06); }
.sk-brand-name { font-size: var(--fs-lg); font-weight: 600; letter-spacing: -.015em; line-height: 1.1; }
.sk-brand-sub {
	display: block; color: #6a7f9d; font-size: 10px; font-weight: 500;
	letter-spacing: .11em; text-transform: uppercase;
}

.sk-nav {
	position: relative;
	flex: 1 1 auto;
	padding: var(--s-3) var(--s-2) var(--s-8);
	overflow-y: auto; overscroll-behavior: contain;
	scrollbar-width: thin; scrollbar-color: var(--ink-600) transparent;
}
.sk-nav::-webkit-scrollbar { width: 7px; }
.sk-nav::-webkit-scrollbar-thumb { background: var(--ink-600); border-radius: 4px; }
.sk-nav::-webkit-scrollbar-thumb:hover { background: #3a4c70; }

.sk-nav-group { margin-bottom: 2px; }

.sk-nav-title {
	display: flex; align-items: center; gap: var(--s-3);
	width: 100%; margin: var(--s-2) 0 var(--s-1);
	padding: 7px var(--s-3);
	border: 0; border-radius: var(--r-sm);
	background: transparent; color: #8ea3bd;
	font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 600;
	text-align: left; white-space: nowrap; cursor: pointer;
	transition: background var(--t), color var(--t);
}
.sk-nav-title:hover { background: rgba(255,255,255,.055); color: #d6e2f0; }
.sk-nav-title .ico { flex: 0 0 16px; opacity: .8; transition: opacity var(--t), transform var(--t); }
.sk-nav-title:hover .ico { opacity: 1; transform: scale(1.08); }
.sk-nav-title .chev {
	flex: 0 0 12px; width: 12px; height: 12px; margin-left: auto;
	opacity: .5; transition: transform var(--t-slow), opacity var(--t);
}
.sk-nav-group.is-collapsed .chev { transform: rotate(-90deg); }

.sk-nav-items { display: grid; grid-template-rows: 1fr; opacity: 1; transition: opacity var(--t); }
.sk-nav-items > div { overflow: hidden; }
.sk-nav-group.is-collapsed .sk-nav-items { grid-template-rows: 0fr; opacity: 0; }

.linkClass { margin: 0; }

a.linkCss, .sk-nav a {
	position: relative;
	display: flex; align-items: center; gap: var(--s-3);
	width: auto; height: auto; margin: 1px 0;
	padding: 7px var(--s-3) 7px 42px;
	border: 0; border-radius: var(--r-sm);
	background: transparent; color: #9db2ca;
	font-size: var(--fs-sm); font-weight: 400;
	transition: background var(--t), color var(--t), padding-left var(--t-fast);
}
.sk-nav-group:not(.has-title) a.linkCss { padding-left: var(--s-3); }

a.linkCss:hover, .sk-nav a:hover {
	background: rgba(255,255,255,.06); color: #fff; border: 0; text-decoration: none;
	padding-left: 46px;
}
.sk-nav-group:not(.has-title) a.linkCss:hover { padding-left: var(--s-4); }

a.linkCss.is-active, .sk-nav a.is-active {
	background: linear-gradient(90deg, rgba(15,98,254,.42), rgba(15,98,254,.10));
	color: #fff; font-weight: 500;
}
a.linkCss.is-active::before {
	content: ""; position: absolute; left: 0; top: 5px; bottom: 5px; width: 3px;
	border-radius: 0 3px 3px 0;
	background: var(--blue-400);
	box-shadow: 0 0 10px rgba(15,98,254,.9);
	animation: growY .3s cubic-bezier(.22,1,.36,1) both;
}
@keyframes growY { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.sk-nav a .ico { opacity: .8; }

.sk-nav-badge {
	margin-left: auto; padding: 1px 7px; border-radius: 10px;
	background: rgba(192,38,32,.92); color: #fff;
	font-size: 10px; font-weight: 600; font-variant-numeric: tabular-nums;
}

.sk-themetoggle {
	margin-left: auto;
	display: grid; place-items: center;
	width: 28px; height: 28px;
	border: 1px solid rgba(255,255,255,.1); border-radius: var(--r-sm);
	background: rgba(255,255,255,.04); color: #9db2ca;
	box-shadow: none;
	cursor: pointer;
	transition: background var(--t), color var(--t), transform var(--t-fast);
}
.sk-themetoggle:hover { background: rgba(255,255,255,.1); color: #fff; }
.sk-themetoggle:active { transform: scale(.92); }

/* --------------------------------------------------------------------------
   7. PAGE HEADER
   -------------------------------------------------------------------------- */
.sk-page-head { display: flex; align-items: flex-end; gap: var(--s-4); margin-bottom: var(--s-5); }
.sk-crumb { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; color: var(--text-soft); font-size: var(--fs-xs); }
.sk-crumb a { color: var(--text-soft); }
.sk-crumb a:hover { color: var(--blue-600); }
.sk-crumb span { color: var(--n-300); }

.listHeader, .sk-title {
	margin: 0; padding: 0; border: 0; background: none;
	font-style: normal;   /* legacy style.css sets .listHeader{font-style:italic} */
	color: var(--text-strong);
	font-size: var(--fs-xl); font-weight: 600;
	letter-spacing: -.024em; line-height: 1.2;
}
.sk-head-actions { margin-left: auto; display: flex; gap: var(--s-2); }

/* --------------------------------------------------------------------------
   8. PANELS
   -------------------------------------------------------------------------- */
.formsection, .sk-panel {
	margin: 0 0 var(--s-5); padding: 0;
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-sm);
	overflow: hidden;
	transition: background var(--t), border-color var(--t), box-shadow var(--t);
}
.formsection > h3, .sk-panel-head, .headertext {
	display: flex; align-items: center; gap: var(--s-2);
	margin: 0; padding: var(--s-3) var(--s-4);
	border-bottom: 1px solid var(--border);
	background: transparent; color: var(--text-strong);
	font-size: var(--fs-md); font-weight: 600; letter-spacing: -.005em;
}
.sk-panel-head .ico, .headertext .ico { color: var(--n-400); width: 15px; height: 15px; flex: 0 0 15px; }
.sk-panel-body { padding: var(--s-4); }

/* --------------------------------------------------------------------------
   9. STAT TILES
   -------------------------------------------------------------------------- */
.sk-stats { display: grid; grid-template-columns: repeat(auto-fill, minmax(186px, 1fr)); gap: var(--s-3); margin-bottom: var(--s-5); }
.sk-stat {
	position: relative; display: block; padding: var(--s-4);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-xs);
	overflow: hidden;
	transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}
.sk-stat::after {
	content: ""; position: absolute; inset: auto 0 0 0; height: 2px;
	background: var(--accent, var(--blue-600));
	transform: scaleX(0); transform-origin: left;
	transition: transform var(--t-slow);
}
.sk-stat:hover { transform: translateY(-3px); border-color: var(--border-strong); box-shadow: var(--sh-md); }
.sk-stat:hover::after { transform: scaleX(1); }
.sk-stat-label {
	display: flex; align-items: center; gap: 6px; margin-bottom: var(--s-3);
	color: var(--text-soft); font-size: var(--fs-xs); font-weight: 600;
	letter-spacing: .04em; text-transform: uppercase;
}
.sk-stat-label::before { content: ""; width: 7px; height: 7px; border-radius: 2px; background: var(--accent, var(--blue-600)); }
.sk-stat-value {
	display: block; color: var(--text-strong);
	font-family: var(--font-mono); font-size: var(--fs-2xl); font-weight: 500;
	line-height: 1.05; letter-spacing: -.032em;
}
.sk-stat-foot { display: flex; align-items: center; gap: 5px; margin-top: var(--s-2); color: var(--text-soft); font-size: var(--fs-xs); }
.sk-stat.is-total { --accent: var(--blue-600); }
.sk-stat.is-total .sk-stat-value { color: var(--blue-600); }

/* --------------------------------------------------------------------------
   10. FORM CONTROLS
   -------------------------------------------------------------------------- */
/* [COMPAT] legacy style.css has wrapper-context rules like
   ".form .textbox{width:292px}" at (0,2,0) specificity, beating a plain
   ".textbox" reset at (0,1,0). Aesthetic properties (border/height/
   background/font) are made !important to survive that fight, deliberately
   -- this IS the authoritative form-control reset.

   WIDTH IS DELIBERATELY LEFT OUT of this reset. The app already has an
   opt-in class for full width: .fWidth, used 1,335 times. ~79 pages
   (search bars, e.g. callReport.php) rely on inputs staying COMPACT --
   they carry an explicit inline style="width:100px" and were never given
   .fWidth. A blanket width:100% here forced every one of those fields onto
   its own full-width row, breaking the compact inline search bar into a
   tall stack. Leaving width unset lets each field fall back to (in order)
   its own inline style, or .fWidth if present, or the browser default
   compact size -- matching what the original markup already asked for. */
.textbox, .SelectBox, .bigTextBox,
input[type="text"], input[type="password"], select, textarea {
	height: 36px !important; padding: 0 var(--s-3) !important;
	border: 1px solid var(--border-strong) !important; border-radius: var(--r) !important;
	background: var(--surface); color: var(--text-strong) !important;
	font-family: var(--font-ui) !important; font-size: var(--fs-md) !important; line-height: 34px !important;
	box-shadow: var(--sh-xs) !important;
	transition: border-color var(--t), box-shadow var(--t), background var(--t);
}
/* [COMPAT] background is deliberately NOT !important above.
   $os->changeStatusDD() (classes/modelsTable.php) renders an INTERACTIVE
   status dropdown with an inline background-color carrying the status
   meaning -- mif.php uses UW/UC/NC/NC-B/Closed, partServiceReport.php uses
   Open/Closed, each with their own colour map. An !important background
   here beats the inline style and silently erases that colour coding,
   which is real information, not decoration. Legacy style.css sets no
   competing background on these controls, so plain specificity is enough. */
select.statusDD { font-weight: 500; }
/* [COMPAT] .bigTextBox is NOT a textarea class. Legacy style.css gives it
   "width:290px; height:20px" and it is used on 142 <input type="text">
   elements and on zero <textarea>s. Grouping it with textarea here made
   every single-line field on every add/edit form 82px tall. */
textarea { height: auto !important; min-height: 82px !important; padding: var(--s-2) var(--s-3) !important; line-height: 1.55 !important; resize: vertical; }
select {
	padding-right: 30px !important;
	background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%2361708a' d='M.8 0 5 4.4 9.2 0 10 .8 5 6 0 .8z'/%3E%3C/svg%3E");
	background-repeat: no-repeat; background-position: right 11px center;
	-webkit-appearance: none; appearance: none; cursor: pointer;
}
.textbox:hover, select:hover, textarea:hover { border-color: var(--n-300) !important; }
.textbox:focus, .SelectBox:focus, .bigTextBox:focus,
input:focus, select:focus, textarea:focus {
	outline: none; border-color: var(--blue-500) !important; box-shadow: var(--ring) !important;
}
.textbox[readonly], input[readonly] { background: var(--page) !important; color: var(--text-soft) !important; box-shadow: none !important; cursor: default; }
.fWidth { width: 100% !important; }  /* the deliberate opt-in this reset now respects */

.dtpk {
	background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%2361708a' stroke-width='2' stroke-linecap='round'%3E%3Crect x='3' y='4.5' width='18' height='17' rx='2.5'/%3E%3Cpath d='M16 2.5v4M8 2.5v4M3 10h18'/%3E%3C/svg%3E");
	background-repeat: no-repeat; background-position: right 10px center; padding-right: 34px !important;
}

/* [COMPAT] legacy add/edit forms.
   The markup is a real two-column table: odd cells are labels, even cells
   are fields. Rows carry 2, 4 or 6 cells (one, two or three label/field
   pairs across). An earlier version of this file forced the whole table to
   display:block, which stacked every field full-width and turned an
   eight-field form into eight screens of scrolling. Keeping the table
   layout on desktop respects what the markup already says; the stack is
   kept for narrow screens, where it is the right answer. */
table.formClass {
	width: 100%;
	border-collapse: separate;
	border-spacing: 0;
}
table.formClass > tbody > tr > td {
	padding: 7px 0;
	vertical-align: middle;
}
/* Which cell is a label and which is a field cannot be decided by position:
   174 rows in these forms use colspan (usually colspan="10" to run a field
   to the end of the row), so cell 3 of a row is often the NEXT label, not
   the second field. Deciding by content -- a cell holding a control is a
   field, a cell holding none is its label -- is right regardless of how the
   colspans fall. */
table.formClass > tbody > tr > td:not(:has(input, select, textarea)) {
	width: 1%;
	padding-right: var(--s-4);
	color: var(--n-600);
	font-size: var(--fs-sm);
	font-weight: 500;
	white-space: nowrap;
}
table.formClass > tbody > tr > td:has(input, select, textarea) {
	min-width: 150px;
}
/* a second or third label in the same row needs air after the field before it */
table.formClass > tbody > tr > td:has(input, select, textarea) + td:not(:has(input, select, textarea)) {
	padding-left: var(--s-5);
}
/* a label sitting beside a textarea should align to the top of it */
table.formClass > tbody > tr:has(textarea) > td { vertical-align: top; }
table.formClass > tbody > tr:has(textarea) > td:not(:has(textarea)) { padding-top: 14px; }

/* Fields fill their cell so a form reads as one column of controls rather
   than a ragged mix -- productEdit.php, for instance, had 920px inputs next
   to a 110px select purely because only some of them carry the app's own
   .fWidth class. Deliberately NOT !important: a control with an inline
   style="width:100px" is the page asking for a compact field on purpose
   (quantities, pin codes, amounts) and inline style still wins. */
table.formClass > tbody > tr > td > .textbox,
table.formClass > tbody > tr > td > select,
table.formClass > tbody > tr > td > textarea,
table.formClass > tbody > tr > td > input[type="text"],
table.formClass > tbody > tr > td > input[type="password"] {
	width: 100%;
	max-width: 100%;
}

.formsection > fieldset.cFielSets,
.formsection > form > fieldset.cFielSets { max-width: 1020px; }

@media (max-width: 760px) {
	table.formClass, table.formClass > tbody,
	table.formClass > tbody > tr, table.formClass > tbody > tr > td {
		display: block; width: 100%;
	}
	table.formClass > tbody > tr { margin-bottom: var(--s-4); }
	table.formClass > tbody > tr > td { padding: 0; }
	table.formClass > tbody > tr > td:not(:has(input, select, textarea)) {
		width: 100%; margin-bottom: 5px; padding: 0;
		font-size: var(--fs-xs); font-weight: 600; letter-spacing: .03em;
		white-space: normal;
	}
	table.formClass > tbody > tr > td:has(input, select, textarea) + td:not(:has(input, select, textarea)) {
		padding-left: 0; margin-top: var(--s-3);
	}
	/* every field goes full width once stacked, whatever the page asked for */
	table.formClass .textbox, table.formClass select, table.formClass textarea,
	table.formClass input[type="text"], table.formClass input[type="password"] { width: 100% !important; }
}

fieldset.cFielSets {
	margin: 0 0 var(--s-5); padding: var(--s-5);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-sm);
}
legend.cLegend {
	padding: 0 var(--s-2); margin-left: -4px;
	color: var(--text-strong); font-size: var(--fs-md); font-weight: 600;
	letter-spacing: -.005em; text-transform: none;
}
.sk-req { color: var(--danger); margin-left: 2px; }
.sk-hint { display: block; margin-top: 5px; color: var(--text-soft); font-size: var(--fs-xs); }

/* Checkbox */
.sk-check {
	appearance: none; -webkit-appearance: none;
	width: 16px; height: 16px; flex: 0 0 16px;
	margin: 0; padding: 0;
	border: 1.5px solid var(--n-300); border-radius: 5px;
	background: var(--surface); box-shadow: none;
	cursor: pointer; position: relative;
	transition: background var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
}
.sk-check:hover { border-color: var(--blue-400); }
.sk-check:checked { background: var(--blue-600); border-color: var(--blue-600); }
.sk-check:checked::after {
	content: ""; position: absolute; left: 4.5px; top: 1px;
	width: 4px; height: 8px;
	border: solid #fff; border-width: 0 2px 2px 0;
	transform: rotate(45deg);
	animation: popCheck .16s ease both;
}
.sk-check:active { transform: scale(.9); }

/* --------------------------------------------------------------------------
   11. BUTTONS
   -------------------------------------------------------------------------- */
/* [COMPAT] .buttonSa is NOT a button primitive in the legacy app -- it is a
   bare wrapper (<td class="buttonSa">, <span class="buttonSa">) around a
   real control such as a <select> or an .editButton link, and carries no
   rule at all in the old style.css. Styling it as a button here would put
   visible button chrome around a container that already holds one. */
.submit, .searchButton, .refreshButton, .resetButton, .searchReset, .addButton,
.activationButton, .addNewFields, .loginbtn, .sk-btn,
button, input[type="submit"], input[type="button"] {
	display: inline-flex; align-items: center; justify-content: center; gap: 7px;
	width: auto; height: 36px; padding: 0 var(--s-4);
	border: 1px solid var(--border-strong); border-radius: var(--r);
	background: var(--surface); color: var(--n-700);
	font-family: var(--font-ui); font-size: var(--fs-sm); font-weight: 500; line-height: 1;
	white-space: nowrap; cursor: pointer; box-shadow: var(--sh-xs);
	transition: background var(--t), border-color var(--t), box-shadow var(--t), transform var(--t-fast), color var(--t);
}
.submit:hover, .searchButton:hover, .refreshButton:hover, .resetButton:hover,
.searchReset:hover, .addButton:hover,
.activationButton:hover, .addNewFields:hover, .loginbtn:hover, .sk-btn:hover, button:hover {
	background: var(--surface-sub); border-color: var(--n-300); box-shadow: var(--sh-sm); text-decoration: none;
}
.sk-btn:active, button:active { transform: translateY(1px) scale(.99); box-shadow: none; }

.submit, .searchButton, .sk-btn--primary, input[type="submit"] {
	border-color: transparent;
	background: linear-gradient(180deg, var(--blue-500), var(--blue-600));
	color: #fff;
	box-shadow: inset 0 1px 0 rgba(255,255,255,.22), var(--sh-glow);
}
.submit:hover, .searchButton:hover, .sk-btn--primary:hover, input[type="submit"]:hover {
	background: linear-gradient(180deg, var(--blue-600), var(--blue-700));
	border-color: transparent; color: #fff;
	box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 4px 16px rgba(15,98,254,.4);
}
.sk-btn--danger { border-color: transparent; background: var(--danger); color: #fff; }
.sk-btn--danger:hover { background: #96201a; color: #fff; }
.sk-btn--ghost { border-color: transparent; background: transparent; box-shadow: none; color: var(--blue-600); }
.sk-btn--ghost:hover { background: var(--blue-50); border-color: transparent; box-shadow: none; }
.sk-btn--sm { height: 30px; padding: 0 var(--s-3); font-size: var(--fs-xs); }
.sk-btn .ico { width: 15px; height: 15px; flex: 0 0 15px; }

.sk-actions {
	display: flex; align-items: center; gap: var(--s-2);
	padding: var(--s-3) var(--s-4);
	border-top: 1px solid var(--border);
	background: var(--surface-sub);
}

.sk-seg { display: inline-flex; padding: 3px; border: 1px solid var(--border-strong); border-radius: var(--r); background: var(--n-100); }
.sk-seg button {
	height: 26px; padding: 0 var(--s-3);
	border: 0; border-radius: 6px; background: transparent; box-shadow: none;
	color: var(--text-soft); font-size: var(--fs-xs); font-weight: 500;
}
.sk-seg button:hover { background: color-mix(in srgb, var(--surface) 70%, transparent); box-shadow: none; }
.sk-seg button.is-on { background: var(--surface); color: var(--text-strong); box-shadow: var(--sh-xs); }

/* Tooltip */
[data-tip] { position: relative; }
[data-tip]::after {
	content: attr(data-tip);
	position: absolute; bottom: calc(100% + 7px); left: 50%;
	transform: translateX(-50%) translateY(4px);
	padding: 4px 8px; border-radius: var(--r-sm);
	background: var(--n-900); color: var(--n-0);
	font-size: 10px; font-weight: 500; white-space: nowrap;
	opacity: 0; pointer-events: none;
	transition: opacity var(--t), transform var(--t);
	z-index: 80;
}
[data-tip]:hover::after { opacity: 1; transform: translateX(-50%) translateY(0); }

/* --------------------------------------------------------------------------
   12. FILTERS + CHIPS
   -------------------------------------------------------------------------- */
.sk-filters { display: grid; grid-template-columns: repeat(auto-fill, minmax(196px, 1fr)); gap: var(--s-4); padding: var(--s-5) var(--s-4); }
.sk-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.sk-field label { color: var(--n-600); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .03em; }

.sk-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); padding: 0 var(--s-4) var(--s-4); }
.sk-chip {
	display: inline-flex; align-items: center; gap: 6px;
	padding: 3px 6px 3px 10px; border: 1px solid var(--info-br); border-radius: 20px;
	background: var(--info-bg); color: var(--blue-700);
	font-size: var(--fs-xs); font-weight: 500;
	animation: pop .2s ease both;
}
.sk-chip b { font-weight: 600; }
.sk-chip button {
	width: 16px; height: 16px; padding: 0;
	border: 0; border-radius: 50%; background: transparent; box-shadow: none;
	color: var(--blue-700); font-size: 13px; line-height: 1;
	display: grid; place-items: center;
}
.sk-chip button:hover { background: rgba(15,98,254,.16); box-shadow: none; }

/* --------------------------------------------------------------------------
   13. [COMPAT] DATA TABLE
   -------------------------------------------------------------------------- */
.sk-tablewrap {
	position: relative; max-width: 100%; overflow: auto;
	border: 1px solid var(--border); border-radius: 0 0 var(--r-lg) var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-sm);
	max-height: calc(100vh - 310px);
	scrollbar-width: thin;
}
.sk-tablewrap::-webkit-scrollbar { width: 12px; height: 12px; }
.sk-tablewrap::-webkit-scrollbar-track { background: var(--page); }
.sk-tablewrap::-webkit-scrollbar-thumb { background: var(--n-300); border: 3px solid var(--page); border-radius: 8px; }
.sk-tablewrap::-webkit-scrollbar-thumb:hover { background: var(--n-400); }

table.listTable {
	width: max-content !important;   /* [COMPAT] beats inline width:1300px */
	min-width: 100%;
	border-collapse: separate; border-spacing: 0;
	background: var(--surface) !important;
	font-size: var(--fs-sm);
}

table.listTable tr.borderTitle > td {
	position: sticky; top: 0; z-index: 20;
	padding: var(--s-3);
	border-bottom: 1px solid var(--border);
	background: var(--surface-sub);
	color: var(--text-soft);
	font-size: var(--fs-xs); font-weight: 600; letter-spacing: .05em;
	text-transform: uppercase; text-align: left; white-space: nowrap;
	transition: box-shadow var(--t);
}
/* Shadow appears once the body scrolls under the header */
.sk-tablewrap.is-scrolled table.listTable tr.borderTitle > td { box-shadow: 0 6px 12px -8px rgba(15,23,42,.5); }

table.listTable > tbody > tr > td {
	padding: 10px var(--s-3);
	border-bottom: 1px solid var(--n-100);
	color: var(--text); white-space: nowrap; vertical-align: middle;
	transition: background var(--t-fast);
}
table.listTable > tbody > tr:hover > td { background: var(--blue-50); }
table.listTable > tbody > tr.is-selected > td { background: var(--info-bg); }
table.listTable > tbody > tr:last-child > td { border-bottom: 0; }

/* Compact density */
.sk-tablewrap.is-compact table.listTable > tbody > tr > td { padding: 5px var(--s-3); }
.sk-tablewrap.is-compact table.listTable tr.borderTitle > td { padding: 7px var(--s-3); }

/* Frozen identity columns */
/* Frozen identity columns: the tick-box and the Docket No, so the row can
   always be identified while scrolling a 25-column table sideways. */
table.listTable tr > td:nth-child(1),
table.listTable tr > td:nth-child(2) { position: sticky; z-index: 10; background: var(--surface); }
table.listTable tr > td:nth-child(1) { left: 0;  width: 42px; }
table.listTable tr > td:nth-child(2) { left: 42px; }
table.listTable > tbody > tr:hover > td:nth-child(1),
table.listTable > tbody > tr:hover > td:nth-child(2) { background: var(--blue-50); }
table.listTable > tbody > tr.is-selected > td:nth-child(1),
table.listTable > tbody > tr.is-selected > td:nth-child(2) { background: var(--info-bg); }
table.listTable tr.borderTitle > td:nth-child(1),
table.listTable tr.borderTitle > td:nth-child(2) { z-index: 30; background: var(--surface-sub); }
table.listTable tr > td:nth-child(2)::after {
	content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 10px;
	transform: translateX(100%);
	background: linear-gradient(to right, rgba(15,23,42,.08), transparent);
	opacity: 0; transition: opacity var(--t);
	pointer-events: none;
}
.sk-tablewrap.is-scrolled-x table.listTable tr > td:nth-child(2)::after { opacity: 1; }

.sk-docket { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 600; color: var(--blue-600); }
.sk-docket:hover { text-decoration: underline; }
.sk-num { font-family: var(--font-mono); text-align: right; }
.sk-muted { color: var(--text-soft); }

/* Bulk action bar */
.sk-bulk {
	position: sticky; bottom: 54px; z-index: 35;
	display: none; align-items: center; gap: var(--s-3);
	margin-top: var(--s-3); padding: var(--s-3) var(--s-4);
	border: 1px solid var(--blue-300); border-radius: var(--r-lg);
	background: var(--surface);
	box-shadow: var(--sh-md);
	animation: slideUp .22s cubic-bezier(.22,1,.36,1) both;
}
.sk-bulk.is-on { display: flex; }
.sk-bulk .sk-spacer { flex: 1; }
.sk-bulk-count {
	display: inline-flex; align-items: center; justify-content: center;
	min-width: 22px; height: 22px; padding: 0 6px;
	border-radius: 7px; background: var(--blue-600); color: #fff;
	font-size: var(--fs-xs); font-weight: 600; font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   14. STATUS PILLS
   -------------------------------------------------------------------------- */
.sk-pill {
	display: inline-flex; align-items: center; gap: 5px;
	padding: 3px 9px; border: 1px solid transparent; border-radius: 7px;
	font-size: var(--fs-xs); font-weight: 500; white-space: nowrap;
}
.sk-pill::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.sk-pill--closed  { background: var(--ok-bg);     border-color: var(--ok-br);     color: var(--ok); }
.sk-pill--pending { background: var(--warn-bg);   border-color: var(--warn-br);   color: var(--warn); }
.sk-pill--cancel,
.sk-pill--due     { background: var(--danger-bg); border-color: var(--danger-br); color: var(--danger); }
.sk-pill--alloc   { background: var(--info-bg);   border-color: var(--info-br);   color: var(--info); }
.sk-pill--free    { background: var(--idle-bg);   border-color: var(--idle-br);   color: var(--idle); }
.sk-pill--pending::before, .sk-pill--alloc::before { animation: pulseDot 2.2s ease-in-out infinite; }

.sk-age { font-family: var(--font-mono); font-weight: 600; }
.sk-age--ok  { color: var(--ok); }
.sk-age--mid { color: var(--warn); }
.sk-age--bad { color: var(--danger); }

/* --------------------------------------------------------------------------
   15. ROW ACTIONS
   -------------------------------------------------------------------------- */
.actionLink {
	display: inline-grid; place-items: center;
	width: 28px; height: 28px;
	border: 1px solid transparent; border-radius: var(--r-sm);
	background: transparent; box-shadow: none; color: var(--n-400);
	transition: background var(--t), color var(--t), border-color var(--t), transform var(--t-fast);
}
.actionLink:hover { background: var(--blue-50); border-color: var(--blue-100); color: var(--blue-600); transform: translateY(-1px); }
.actionLink--danger:hover { background: var(--danger-bg); border-color: var(--danger-br); color: var(--danger); }
.actionLink .ico { width: 15px; height: 15px; flex: 0 0 15px; }

/* --------------------------------------------------------------------------
   16. TOOLBAR + PAGING
   -------------------------------------------------------------------------- */
.sk-tabletools {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4);
	border: 1px solid var(--border); border-bottom: 0;
	border-radius: var(--r-lg) var(--r-lg) 0 0;
	background: var(--surface);
}
.sk-count { color: var(--n-600); font-size: var(--fs-sm); }
.sk-count b { color: var(--text-strong); font-variant-numeric: tabular-nums; }
.sk-tabletools .sk-spacer { flex: 1; }

.sk-paging {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); margin-top: var(--s-3);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-xs);
}
.sk-pages { display: flex; gap: 4px; margin-left: auto; }
.sk-pages a, .sk-pages span {
	display: grid; place-items: center; min-width: 30px; height: 30px; padding: 0 7px;
	border: 1px solid transparent; border-radius: var(--r-sm);
	color: var(--n-600); font-size: var(--fs-sm); font-variant-numeric: tabular-nums;
	transition: background var(--t-fast), color var(--t-fast);
}
.sk-pages a:hover { background: var(--n-100); color: var(--text-strong); }
.sk-pages .is-current { background: var(--blue-600); border-color: transparent; color: #fff; font-weight: 600; box-shadow: var(--sh-glow); }

/* --------------------------------------------------------------------------
   17. FLASH + TOASTS
   -------------------------------------------------------------------------- */
.sk-flash {
	display: flex; align-items: flex-start; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4);
	border: 1px solid var(--ok-br); border-radius: var(--r);
	background: var(--ok-bg); color: var(--ok);
	font-size: var(--fs-sm);
	animation: slideDown .3s cubic-bezier(.22,1,.36,1) both;
}
.sk-flash .ico { color: var(--ok); margin-top: 1px; }
.sk-flash--warn { border-color: var(--warn-br); background: var(--warn-bg); color: var(--warn); }

.sk-toasts {
	position: fixed; right: var(--s-5); bottom: 58px;
	display: flex; flex-direction: column; gap: var(--s-2);
	z-index: 95;
}
.sk-toast {
	display: flex; align-items: center; gap: var(--s-3);
	min-width: 260px; padding: var(--s-3) var(--s-4);
	border: 1px solid var(--border); border-radius: var(--r);
	background: var(--surface); color: var(--text-strong);
	box-shadow: var(--sh-lg);
	font-size: var(--fs-sm);
	animation: slideUp .26s cubic-bezier(.22,1,.36,1) both;
}
.sk-toast.is-out { animation: fade .2s ease reverse both; }
.sk-toast .ico { color: var(--blue-600); }

/* Skeleton */
.sk-skel {
	border-radius: var(--r-sm);
	background: linear-gradient(90deg, var(--n-100) 25%, var(--n-150) 37%, var(--n-100) 63%);
	background-size: 420px 100%;
	animation: shimmer 1.3s linear infinite;
}

/* --------------------------------------------------------------------------
   18. COMMAND PALETTE
   -------------------------------------------------------------------------- */
.sk-cmdk {
	position: fixed; inset: 0; z-index: 100;
	display: none; align-items: flex-start; justify-content: center;
	padding-top: 12vh;
	background: rgba(6,10,20,.55);
	backdrop-filter: blur(3px);
	animation: fade .16s ease both;
}
.sk-cmdk.is-on { display: flex; }
.sk-cmdk-box {
	width: min(560px, 92vw);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-lg);
	overflow: hidden;
	animation: slideUp .2s cubic-bezier(.22,1,.36,1) both;
}
.sk-cmdk-input {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-4); border-bottom: 1px solid var(--border);
}
.sk-cmdk-input .ico { color: var(--n-400); }
.sk-cmdk-input input {
	flex: 1; height: auto; padding: 0;
	border: 0; background: transparent; box-shadow: none;
	color: var(--text-strong); font-size: var(--fs-lg);
}
.sk-cmdk-input input:focus { box-shadow: none; border: 0; }
.sk-cmdk-list { max-height: 340px; overflow-y: auto; padding: var(--s-2); }
.sk-cmdk-item {
	display: flex; align-items: center; gap: var(--s-3);
	padding: 9px var(--s-3); border-radius: var(--r-sm);
	color: var(--text); font-size: var(--fs-md); cursor: pointer;
}
.sk-cmdk-item .grp { margin-left: auto; color: var(--n-400); font-size: var(--fs-xs); }
.sk-cmdk-item.is-on { background: var(--blue-50); color: var(--blue-700); }
.sk-cmdk-item.is-on .grp { color: var(--blue-500); }
.sk-cmdk-empty { padding: var(--s-6); text-align: center; color: var(--text-soft); font-size: var(--fs-sm); }
.sk-cmdk-foot {
	display: flex; gap: var(--s-4); padding: var(--s-2) var(--s-4);
	border-top: 1px solid var(--border); background: var(--surface-sub);
	color: var(--n-400); font-size: 10px;
}
.sk-cmdk-foot kbd {
	padding: 1px 5px; border: 1px solid var(--border-strong); border-radius: 4px;
	background: var(--surface); font-family: var(--font-mono); font-size: 10px;
}

/* --------------------------------------------------------------------------
   19. LOGIN
   -------------------------------------------------------------------------- */
.sk-login { display: grid; grid-template-columns: 1.05fr .95fr; min-height: 100vh; background: var(--surface); }
.sk-login-aside {
	position: relative; display: flex; flex-direction: column; justify-content: space-between;
	padding: var(--s-10);
	background:
		radial-gradient(1000px 520px at 76% 4%, rgba(15,98,254,.42), transparent 58%),
		linear-gradient(158deg, var(--ink-950) 0%, #0d1c3c 50%, #10306e 100%);
	color: #fff; overflow: hidden;
}
.sk-login-aside::before {
	content: ""; position: absolute; inset: 0;
	background-image:
		linear-gradient(rgba(255,255,255,.055) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255,255,255,.055) 1px, transparent 1px);
	background-size: 38px 38px;
	mask-image: radial-gradient(740px 470px at 26% 44%, #000, transparent 74%);
	-webkit-mask-image: radial-gradient(740px 470px at 26% 44%, #000, transparent 74%);
	pointer-events: none;
}
.sk-login-aside > * { position: relative; }
.sk-login-head { display: flex; align-items: center; gap: var(--s-3); animation: rise .5s cubic-bezier(.22,1,.36,1) both; }
.sk-login-head .sk-brand-mark { width: 36px; height: 36px; font-size: var(--fs-md); }
.sk-login-pitch { animation: rise .5s cubic-bezier(.22,1,.36,1) .08s both; }
.sk-login-pitch h1 { margin: 0 0 var(--s-4); max-width: 15ch; font-size: 46px; font-weight: 600; line-height: 1.06; letter-spacing: -.038em; }
.sk-login-pitch p { margin: 0; max-width: 46ch; color: #a9c2de; font-size: var(--fs-lg); }
.sk-login-facts { display: flex; gap: var(--s-8); animation: rise .5s cubic-bezier(.22,1,.36,1) .16s both; }
.sk-login-fact strong { display: block; font-family: var(--font-mono); font-size: 24px; font-weight: 500; letter-spacing: -.03em; }
.sk-login-fact span { color: #7592b4; font-size: var(--fs-xs); letter-spacing: .06em; text-transform: uppercase; }

.sk-login-main { display: grid; place-items: center; padding: var(--s-8); }
.sk-login-form { width: 100%; max-width: 360px; animation: rise .5s cubic-bezier(.22,1,.36,1) .1s both; }
.sk-login-form h2 { margin: 0 0 var(--s-1); font-size: var(--fs-2xl); font-weight: 600; letter-spacing: -.03em; }
.sk-login-form .sk-sub { margin: 0 0 var(--s-6); color: var(--text-soft); }
.sk-login-form .sk-field { margin-bottom: var(--s-4); }
.sk-login-form .textbox { height: 40px; }
.sk-login-form .submit { width: 100%; height: 42px; font-size: var(--fs-md); }
.sk-login-foot { margin-top: var(--s-6); color: var(--n-400); font-size: var(--fs-xs); text-align: center; }

/* --------------------------------------------------------------------------
   20. PRINT / BILL
   -------------------------------------------------------------------------- */
.sk-doc {
	max-width: 210mm; margin: 0 auto var(--s-8); padding: 16mm;
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-md); color: var(--text-strong);
}
.sk-doc-head { display: flex; align-items: flex-start; gap: var(--s-6); padding-bottom: var(--s-4); margin-bottom: var(--s-5); border-bottom: 2px solid var(--ink-900); }
.sk-doc-title { margin-left: auto; text-align: right; }
.sk-doc-title h1 { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; }
.sk-doc-title .sk-doc-no { font-family: var(--font-mono); color: var(--blue-600); font-weight: 600; }
.sk-doc-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-5) var(--s-8); margin-bottom: var(--s-5); }
.sk-dl { display: grid; grid-template-columns: 120px 1fr; gap: 6px var(--s-3); font-size: var(--fs-sm); margin: 0; }
.sk-dl dt { color: var(--text-soft); }
.sk-dl dd { margin: 0; font-weight: 500; }

table.sk-doc-table { width: 100%; border-collapse: collapse; margin-bottom: var(--s-5); font-size: var(--fs-sm); }
table.sk-doc-table th {
	padding: var(--s-2) var(--s-3); border-bottom: 1.5px solid var(--ink-900);
	color: var(--text-soft); font-size: var(--fs-xs); font-weight: 600;
	letter-spacing: .05em; text-transform: uppercase; text-align: left;
}
table.sk-doc-table td { padding: var(--s-2) var(--s-3); border-bottom: 1px solid var(--n-100); }
table.sk-doc-table tfoot td { border-top: 1.5px solid var(--ink-900); border-bottom: 0; font-weight: 600; }

.sk-sign { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-10); margin-top: var(--s-10); padding-top: var(--s-4); }
.sk-sign div { padding-top: var(--s-8); border-top: 1px solid var(--n-400); font-size: var(--fs-xs); color: var(--n-600); }

@media print {
	.sk-topbar, .container td.leftside, td.leftside, .sk-noprint, .sk-page-head, .sk-toasts, .sk-cmdk { display: none !important; }
	body { background: #fff; font-size: 11px; padding: 0 !important; }
	.container td.middle, td.middle { margin: 0 !important; padding: 0 !important; min-height: 0; }
	.sk-doc { max-width: none; margin: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none; }
	.sk-rise { animation: none !important; opacity: 1 !important; }
	@page { size: A4; margin: 14mm; }
}

/* --------------------------------------------------------------------------
   21. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 1240px) {
	:root { --sidebar-w: 64px; }
	.sk-brand-name, .sk-brand-sub,
	.sk-nav a span:not(.sk-nav-badge),
	.sk-nav-title span, .sk-nav-title .chev { display: none; }
	.sk-side-head { justify-content: center; padding: 0; }
	.sk-nav-title { justify-content: center; padding: 7px 0; }
	.sk-nav a, a.linkCss { justify-content: center; padding: 9px 0 !important; }
	.sk-nav-group.is-collapsed .sk-nav-items { grid-template-rows: 1fr; opacity: 1; }
	a.linkCss.is-active::before { display: none; }
	.sk-topsearch { width: 250px; }
}

@media (max-width: 900px) {
	:root { --sidebar-w: 0px; }
	/* [CHANGE] "More" now opens a bottom sheet, not a left-edge drawer --
	   same element (td.leftside), same content, repositioned: pinned to
	   the bottom edge instead of the left one, sliding up instead of in.
	   Only top/bottom/height/radius/shadow change; everything below that
	   restores brand/label text out of the base icon-rail collapse is
	   unaffected by which edge the sheet opens from. */
	.container td.leftside, td.leftside {
		top: auto !important; left: 0 !important; right: 0; bottom: 0 !important;
		width: 100% !important; max-height: 78vh;
		border-right: 0; border-radius: 18px 18px 0 0;
		transform: translateY(100%);
		transition: transform var(--t-slow);
		box-shadow: 0 -8px 30px rgba(0, 0, 0, .25);
	}
	/* drag-handle affordance, a pseudo-element so no PHP markup is needed */
	td.leftside::after {
		content: ""; position: absolute; top: 9px; left: 50%; transform: translateX(-50%);
		width: 36px; height: 4px; border-radius: 3px; background: rgba(255, 255, 255, .25);
	}
	body.nav-open td.leftside { transform: none; }
	/* [FIX] confirmed live via elementsFromPoint: every tap on a sheet
	   link was actually landing on the scrim underneath it, not the link
	   -- despite td.leftside's own z-index:60 being higher than the
	   scrim's 55. Root cause: the legacy vendor style.css (loaded before
	   this file) gives ".curvebox" (an ancestor of td.leftside) its own
	   "position:relative; z-index:10". That makes curvebox a stacking
	   context of its own, and td.leftside's z-index:60 only ever wins
	   fights INSIDE that context -- from the scrim's side (a body-level
	   sibling of curvebox, outside it), the whole curvebox subtree counts
	   as a single z:10 layer, well below the scrim's 55. Neutralised only
	   while the sheet is open, where curvebox's own stacking no longer
	   matters (everything behind the scrim is meant to be inert anyway). */
	body.nav-open .curvebox { position: static; z-index: auto; }
	/* [FIX] confirmed live (real elementFromPoint + textContent check): a
	   bare "span" here also matched .sk-rail-cap -- a second, normally
	   display:none copy of the same label kept only for the icon-rail's
	   64px flyout caption (section 55, RAIL CAPTIONS). Same (0,2,1)
	   specificity as ".sk-rail-cap { display:none }" but with an extra
	   type selector, so it won regardless of is-rail and printed every
	   label twice in the open drawer/sheet ("Calls Manager Calls
	   Manager"). :not() excludes it, matching how .sk-nav-badge is
	   already excluded here for the same reason. */
	body.nav-open .sk-brand-name, body.nav-open .sk-brand-sub,
	body.nav-open .sk-nav a span:not(.sk-rail-cap), body.nav-open .sk-nav-title span:not(.sk-rail-cap),
	body.nav-open .sk-nav-title .chev { display: block; }
	body.nav-open .sk-nav a, body.nav-open a.linkCss { justify-content: flex-start; padding: 7px var(--s-3) 7px 42px !important; }
	body.nav-open .sk-nav-title { justify-content: flex-start; padding: 7px var(--s-3); }
	/* [FIX] the icon-rail auto-mode above (section 21, <=1240px) centers
	   this row for a persistent icons-only rail; missed when the other
	   properties here were restored for the open drawer, so the brand
	   mark sat centered alone with the rail-toggle crowded next to it
	   instead of a normal left-aligned header. Extra top padding clears
	   the drag-handle above it now that the sheet opens from the bottom. */
	body.nav-open .sk-side-head { justify-content: flex-start; padding: 14px var(--s-4) 0; height: auto; }
	.sk-topbar { left: 0; }
	.container td.middle, td.middle {
		padding-left: var(--s-4) !important; padding-right: var(--s-4) !important;
		padding-bottom: calc(var(--s-10) + var(--bottomnav-h)) !important;
	}
	.sk-login { grid-template-columns: 1fr; }
	.sk-login-aside { display: none; }
	.sk-tablewrap { max-height: none; }
	.sk-doc-grid { grid-template-columns: 1fr; }
	.sk-toasts { left: var(--s-4); right: var(--s-4); }

	/* [FIX] minimal top bar: global search + account only, matching the
	   approved mobile-nav prototype. The hamburger moves to the bottom
	   nav's "More" tab (below), so it is dropped here rather than sitting
	   next to a second way to open the same drawer. Date/reload and the
	   name+role text next to the avatar are desktop-width conveniences,
	   not essentials, and were the reason the search box had no room and
	   got hidden outright before. */
	.sk-topsearch {
		display: block; position: static; flex: 1 1 auto;
		width: auto; max-width: none; transform: none;
	}
	.sk-topbar-spacer, .sk-topdate, .sk-topbar .sk-iconbtn, .sk-kbd { display: none; }
	/* [FIX] same specificity (0,2,0) as the unconditional ".sk-user .t"/
	   ".sk-user .chev" rules in section 6 (SIDEBAR), which sit LATER in
	   this file and so won the tie regardless of this block's own later
	   edit -- confirmed live, the name+role text and chevron still showed
	   at 375px. !important is the fix this file already uses for the same
	   tie-break problem elsewhere (see td.leftside above). */
	.sk-user .t, .sk-user .chev { display: none !important; }
	.sk-user { padding: 0; gap: 0; }

	/* [FIX] the icon-rail collapse control is a desktop-width affordance
	   (shrink the sidebar to icons-only to reclaim page width). In the
	   mobile drawer the sidebar is already an overlay you dismiss outright,
	   so this leaked a control with no purpose here -- and no visible
	   width to click, since body.is-rail was never meant to combine with
	   the off-canvas transform above. */
	/* [FIX] wins on display only because JS now refuses to apply is-rail
	   below 901px (see wireRail() in skyled.js) -- this alone still lost
	   the tie to the base ".sk-railtoggle { display: grid; ... }" rule
	   declared later in this file, same (0,1,0) specificity. */
	.sk-railtoggle { display: none !important; }
}

/* --------------------------------------------------------------------------
   MOBILE NAV -- scrim + bottom tab bar
   --------------------------------------------------------------------------
   The off-canvas drawer above already existed; it was missing two things
   the redesign prototype (approved via artifact feedback) called for: a
   scrim so the page behind the drawer reads as dismissed rather than just
   partly covered, and a fixed bottom tab bar so the four most-used
   sections are one tap away instead of two (open drawer, then pick).
   z-index sits between the topbar (50) and the drawer (60) so the drawer
   still draws on top of its own scrim.
   ========================================================================== */
.sk-nav-scrim {
	display: none;
	position: fixed; inset: 0; z-index: 55;
	background: rgba(6, 10, 20, .55);
	opacity: 0; pointer-events: none;
	transition: opacity var(--t-slow);
}
@media (max-width: 900px) {
	.sk-nav-scrim { display: block; }
	body.nav-open .sk-nav-scrim { opacity: 1; pointer-events: auto; }
}

.sk-bottomnav { display: none; }
@media (max-width: 900px) {
	.sk-bottomnav {
		display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 56;
		height: var(--bottomnav-h);
		background: var(--surface);
		border-top: 1px solid var(--border);
		box-shadow: 0 -1px 3px rgba(0, 0, 0, .05);
		padding-bottom: env(safe-area-inset-bottom);
	}
	/* [FIX] "More" is a <button> (it toggles the drawer, an <a> has to have
	   a real href), the other four are <a> -- a bare browser UA stylesheet
	   gives <button> its own font, line-height and box-sizing that survive
	   most manual resets. "all: unset" wipes that out completely first so
	   both tags land pixel-identical, confirmed misaligned live otherwise. */
	.sk-bottomnav .item {
		all: unset;
		box-sizing: border-box;
		flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
		gap: 3px; height: 100%;
		color: var(--n-400); font-family: var(--font-ui); font-size: 10px; font-weight: 500;
		text-decoration: none; cursor: pointer; -webkit-tap-highlight-color: transparent;
	}
	.sk-bottomnav .item .pill {
		width: 40px; height: 22px; border-radius: 20px;
		display: grid; place-items: center;
	}
	.sk-bottomnav .item .pill .ico { width: 20px; height: 20px; flex: 0 0 20px; }
	.sk-bottomnav .item.is-active { color: var(--blue-600); }
	.sk-bottomnav .item.is-active .pill { background: var(--info-bg); }
	.sk-bottomnav .item:active .pill { background: var(--n-100); }
	.sk-bottomnav .item.is-active:active .pill { background: var(--info-bg); }

	/* keep the sticky save bar and any bottom-fixed chrome clear of the tab bar */
	.savebar { bottom: calc(48px + var(--bottomnav-h)); }
}

@media (max-width: 560px) {
	.sk-filters { grid-template-columns: 1fr; }
	.sk-page-head { flex-wrap: wrap; }
	.sk-head-actions { margin-left: 0; width: 100%; }
	.sk-doc { padding: var(--s-5); }
}


/* ==========================================================================
   23. LIFECYCLE — canonical stages mapped from the app's real status values
   --------------------------------------------------------------------------
   wtos os.php ships 13 statuses across two lists (serviceDataStatus and
   serviceDataStatusAdmin). They encode BOTH progress and blockage, which is
   why "where is this call?" is unanswerable today. The stage model below is
   the progress axis; the "Pending for ..." values become a blocked flag ON a
   stage rather than a stage of their own.

     1 Registered   <- new / ALLOCATION (unassigned)
     2 Allocated    <- Assigned To ASP
     3 Accepted     <- Verified and Accepted by ASP
     4 Scheduled    <- ETA Fixed/Scheduled/Re-Scheduled
     5 In Progress  <- PENDING, Pending for ASP / Customer / Parts  (blocked)
     6 Completed    <- work done on site
     7 Billed       <- PAYMENT DUE
     8 Closed       <- CLOSED / FREE SERVICE
     x Canceled     <- CANCELED (terminal, breaks the chain)
   ========================================================================== */

.sk-life { padding: var(--s-4); }
.sk-life-track { display: flex; align-items: flex-start; gap: 0; }
.sk-life-step { position: relative; flex: 1 1 0; min-width: 0; text-align: center; }

.sk-life-step .dot {
	position: relative; z-index: 2;
	display: grid; place-items: center;
	width: 26px; height: 26px; margin: 0 auto 7px;
	border: 2px solid var(--border-strong); border-radius: 50%;
	background: var(--surface); color: var(--n-400);
	font-family: var(--font-mono); font-size: 10px; font-weight: 600;
	transition: background var(--t), border-color var(--t), color var(--t), transform var(--t);
}
.sk-life-step::before {
	content: ""; position: absolute; top: 12px; left: -50%; z-index: 1;
	width: 100%; height: 2px; background: var(--border-strong);
	transition: background var(--t);
}
.sk-life-step:first-child::before { display: none; }

.sk-life-step .lbl { display: block; color: var(--text-soft); font-size: var(--fs-xs); font-weight: 500; line-height: 1.3; }
.sk-life-step .at { display: block; margin-top: 2px; color: var(--n-400); font-size: 10px; font-family: var(--font-mono); }

.sk-life-step.is-done .dot { background: var(--ok); border-color: var(--ok); color: #fff; }
.sk-life-step.is-done::before, .sk-life-step.is-now::before { background: var(--ok); }
.sk-life-step.is-done .lbl { color: var(--text); }

.sk-life-step.is-now .dot {
	background: var(--blue-600); border-color: var(--blue-600); color: #fff;
	box-shadow: 0 0 0 4px var(--info-bg); transform: scale(1.12);
}
.sk-life-step.is-now .lbl { color: var(--blue-700); font-weight: 600; }

.sk-life-step.is-blocked .dot {
	background: var(--warn); border-color: var(--warn); color: #fff;
	box-shadow: 0 0 0 4px var(--warn-bg);
}
.sk-life-step.is-blocked .lbl { color: var(--warn); font-weight: 600; }

.sk-life-step.is-cancel .dot { background: var(--danger); border-color: var(--danger); color: #fff; }
.sk-life-step.is-cancel .lbl { color: var(--danger); font-weight: 600; }
.sk-life.is-canceled .sk-life-step:not(.is-cancel):not(.is-done) { opacity: .45; }

.sk-life-note {
	display: flex; align-items: center; gap: var(--s-2);
	margin-top: var(--s-4); padding: var(--s-2) var(--s-3);
	border: 1px solid var(--warn-br); border-radius: var(--r);
	background: var(--warn-bg); color: var(--warn); font-size: var(--fs-xs);
}
.sk-life-note.is-ok { border-color: var(--ok-br); background: var(--ok-bg); color: var(--ok); }

/* compact bar for table rows */
.sk-lifebar { display: inline-flex; gap: 2px; vertical-align: middle; }
.sk-lifebar i { width: 9px; height: 5px; border-radius: 1px; background: var(--n-150); transition: background var(--t); }
.sk-lifebar i.on { background: var(--ok); }
.sk-lifebar i.now { background: var(--blue-600); }
.sk-lifebar i.blocked { background: var(--warn); }
.sk-lifebar i.cancel { background: var(--danger); }
.sk-lifestage { margin-left: 7px; color: var(--text-soft); font-size: var(--fs-xs); }

/* [FIX] on a mobile card the 8-tick .sk-lifebar reads as an abstract sliver
   too small to mean anything -- feedback on the approved prototype asked
   for "the stage and number" instead. wireLifeBadge() (skyled.js) reads
   the same already-rendered ticks/label (no new PHP, one source of truth)
   and injects this badge as a sibling; only one of the two shows, by
   width, so desktop's segmented bar is untouched. */
.sk-stagebadge { display: none; align-items: center; gap: 8px; }
.sk-stagebadge .num {
	flex: 0 0 auto; display: grid; place-items: center;
	width: 20px; height: 20px; border-radius: 50%;
	background: var(--info-bg); color: var(--info);
	font-size: 10px; font-weight: 700; font-family: var(--font-mono);
}
.sk-stagebadge.is-blocked .num { background: var(--warn-bg); color: var(--warn); }
.sk-stagebadge.is-canceled .num { background: var(--danger-bg); color: var(--danger); }
.sk-stagebadge .lbl { font-size: var(--fs-xs); color: var(--text-soft); font-weight: 500; }
.sk-stagebadge .of { color: var(--n-400); font-weight: 400; }
@media (max-width: 680px) {
	.sk-lifebar { display: none; }
	/* [FIX] wireLifeBadge() inserts .sk-stagebadge directly after
	   .sk-lifebar, which puts it BETWEEN .sk-lifebar and .sk-lifestage in
	   the DOM -- breaking "+" (immediate next sibling) so this rule
	   stopped matching .sk-lifestage the moment the badge existed, and
	   the plain-text stage name showed a second time next to the new
	   badge ("... stage 2 of 8   Allocated"). "~" matches any later
	   sibling regardless of what sits in between. */
	.sk-lifebar ~ .sk-lifestage { display: none; }
	.sk-stagebadge { display: inline-flex; }
}

/* ==========================================================================
   24. DRAWER — record detail without leaving the list
   ========================================================================== */
.sk-drawer-scrim {
	position: fixed; inset: 0; z-index: 88;
	background: rgba(6, 10, 20, .42); backdrop-filter: blur(2px);
	opacity: 0; pointer-events: none; transition: opacity var(--t);
}
.sk-drawer-scrim.is-on { opacity: 1; pointer-events: auto; }

.sk-drawer {
	position: fixed; top: 0; right: 0; bottom: 0; z-index: 89;
	width: min(760px, 94vw);
	display: flex; flex-direction: column;
	background: var(--surface); border-left: 1px solid var(--border);
	box-shadow: var(--sh-lg);
	transform: translateX(100%); transition: transform var(--t-slow);
}
.sk-drawer.is-on { transform: none; }

.sk-drawer-head {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--border);
}
.sk-drawer-head .t { min-width: 0; }
.sk-drawer-head h3 {
	margin: 0; font-size: var(--fs-lg); font-weight: 600; letter-spacing: -.015em;
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sk-drawer-head .sub { color: var(--text-soft); font-size: var(--fs-xs); }
.sk-drawer-actions { margin-left: auto; display: flex; align-items: center; gap: var(--s-1); }

.sk-drawer-body { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; }
.sk-drawer-foot {
	display: flex; align-items: center; gap: var(--s-2);
	padding: var(--s-3) var(--s-5); border-top: 1px solid var(--border);
	background: var(--surface-sub);
}
.sk-drawer-foot .sk-spacer { flex: 1; }
@media (max-width: 640px) { .sk-drawer { width: 100vw; } }

/* tabs */
.sk-tabs { display: flex; gap: 2px; padding: 0 var(--s-5); border-bottom: 1px solid var(--border); }
.sk-tab {
	padding: 10px var(--s-3); border: 0; border-bottom: 2px solid transparent;
	border-radius: 0; background: transparent; box-shadow: none;
	color: var(--text-soft); font-size: var(--fs-sm); font-weight: 500;
	transition: color var(--t), border-color var(--t);
}
.sk-tab:hover { background: transparent; box-shadow: none; color: var(--text-strong); }
.sk-tab.is-on { color: var(--blue-600); border-bottom-color: var(--blue-600); }
.sk-tabpanel { display: none; padding: var(--s-5); }
.sk-tabpanel.is-on { display: block; animation: fade .18s ease both; }

/* key-value record summary */
.sk-kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4) var(--s-5); margin: 0; }
.sk-kv > div { min-width: 0; }
.sk-kv dt { color: var(--text-soft); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .03em; margin-bottom: 2px; }
.sk-kv dd { margin: 0; color: var(--text-strong); font-size: var(--fs-md); word-break: break-word; }
@media (max-width: 560px) { .sk-kv { grid-template-columns: 1fr; } }

/* timeline */
.sk-tl { position: relative; margin: 0; padding: 0; list-style: none; }
.sk-tl li { position: relative; padding: 0 0 var(--s-5) var(--s-6); }
.sk-tl li::before { content: ""; position: absolute; left: 6px; top: 16px; bottom: -2px; width: 1.5px; background: var(--border); }
.sk-tl li:last-child::before { display: none; }
.sk-tl li::after {
	content: ""; position: absolute; left: 2px; top: 5px;
	width: 9px; height: 9px; border-radius: 50%;
	background: var(--n-300); border: 2px solid var(--surface);
}
.sk-tl li.is-now::after { background: var(--blue-600); box-shadow: 0 0 0 3px var(--info-bg); }
.sk-tl li.is-ok::after { background: var(--ok); }
.sk-tl li.is-warn::after { background: var(--warn); }
.sk-tl b { display: block; font-size: var(--fs-md); font-weight: 600; }
.sk-tl span { color: var(--text-soft); font-size: var(--fs-xs); }
.sk-tl p { margin: 3px 0 0; color: var(--text-soft); font-size: var(--fs-sm); }

/* ==========================================================================
   25. DASHBOARD PARTS
   ========================================================================== */
.sk-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--s-3); margin-bottom: var(--s-4); }
.sk-kpi {
	position: relative; padding: var(--s-4);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-xs); overflow: hidden;
	transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}
.sk-kpi:hover { transform: translateY(-2px); border-color: var(--border-strong); box-shadow: var(--sh-md); }
.sk-kpi-top { display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-2); }
.sk-kpi-top .ico { color: var(--n-400); width: 14px; height: 14px; flex: 0 0 14px; }
.sk-kpi-label { color: var(--text-soft); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.sk-kpi-row { display: flex; align-items: flex-end; gap: var(--s-3); }
.sk-kpi-value { font-family: var(--font-mono); font-size: var(--fs-2xl); font-weight: 500; line-height: 1; letter-spacing: -.032em; color: var(--text-strong); }
.sk-delta { display: inline-flex; align-items: center; gap: 3px; font-size: var(--fs-xs); font-weight: 600; }
.sk-delta--up { color: var(--ok); }
.sk-delta--down { color: var(--danger); }
.sk-kpi-foot { margin-top: var(--s-2); color: var(--text-soft); font-size: var(--fs-xs); }

.sk-spark { margin-left: auto; width: 78px; height: 30px; overflow: visible; }
.sk-spark path.line { fill: none; stroke: var(--blue-500); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.sk-spark path.area { fill: var(--info-bg); stroke: none; }

.sk-funnel { display: flex; flex-direction: column; gap: 7px; padding: var(--s-4); }
.sk-funnel-row { display: grid; grid-template-columns: 128px 1fr 58px; align-items: center; gap: var(--s-3); font-size: var(--fs-sm); }
.sk-funnel-row .n { font-family: var(--font-mono); font-weight: 600; text-align: right; color: var(--text-strong); }
.sk-funnel-row .lbl { color: var(--text-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sk-funnel-bar { position: relative; height: 22px; border-radius: 4px; background: var(--n-100); overflow: hidden; }
.sk-funnel-bar i {
	position: absolute; inset: 0 auto 0 0; border-radius: 4px;
	background: linear-gradient(90deg, var(--blue-500), var(--blue-600));
	transform-origin: left; animation: growX .55s cubic-bezier(.22,1,.36,1) both;
}
.sk-funnel-row.is-drop .sk-funnel-bar i { background: linear-gradient(90deg, #e0a350, var(--warn)); }

.sk-bars { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-4); }
.sk-bar-row { display: grid; grid-template-columns: 168px 1fr 46px; align-items: center; gap: var(--s-3); font-size: var(--fs-sm); }
.sk-bar-label { color: var(--text-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sk-bar-track { height: 20px; border-radius: 4px; background: var(--n-100); overflow: hidden; }
.sk-bar-fill { height: 100%; border-radius: 4px; background: linear-gradient(90deg, var(--blue-400), var(--blue-600)); transform-origin: left; animation: growX .55s cubic-bezier(.22,1,.36,1) both; }
.sk-bar-fill.is-warn { background: linear-gradient(90deg, #e0a350, var(--warn)); }
.sk-bar-fill.is-danger { background: linear-gradient(90deg, #ef8078, var(--danger)); }
.sk-bar-val { font-family: var(--font-mono); font-weight: 600; text-align: right; color: var(--text-strong); }

.sk-heat { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: var(--s-2); padding: var(--s-4); }
.sk-heat-cell { padding: var(--s-3); border-radius: var(--r); text-align: center; transition: transform var(--t); }
.sk-heat-cell:hover { transform: translateY(-2px); }
.sk-heat-cell b { display: block; font-family: var(--font-mono); font-size: var(--fs-xl); font-weight: 500; line-height: 1.1; }
.sk-heat-cell span { font-size: 10px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; opacity: .85; }
.sk-heat-1 { background: var(--ok-bg); color: var(--ok); }
.sk-heat-2 { background: var(--info-bg); color: var(--info); }
.sk-heat-3 { background: var(--warn-bg); color: var(--warn); }
.sk-heat-4 { background: var(--danger-bg); color: var(--danger); }

.sk-quick { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s-2); padding: var(--s-4); }
.sk-quick a {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3); border: 1px solid var(--border); border-radius: var(--r);
	background: var(--surface); color: var(--text);
	font-size: var(--fs-sm); font-weight: 500;
	transition: background var(--t), border-color var(--t), transform var(--t);
}
.sk-quick a:hover { background: var(--blue-50); border-color: var(--blue-200); color: var(--blue-700); transform: translateY(-2px); }
.sk-quick .ico { color: var(--blue-600); }

.sk-stack { display: inline-flex; }
.sk-stack .sk-avatar { margin-left: -7px; border: 2px solid var(--surface); border-radius: 50%; width: 24px; height: 24px; }
.sk-stack .sk-avatar:first-child { margin-left: 0; }

/* ==========================================================================
   26. EMPTY STATE
   ========================================================================== */
.sk-empty { padding: var(--s-10) var(--s-5); text-align: center; }
.sk-empty .ico { width: 34px; height: 34px; margin: 0 auto var(--s-3); color: var(--n-300); }
.sk-empty h4 { margin: 0 0 var(--s-1); font-size: var(--fs-lg); font-weight: 600; }
.sk-empty p { margin: 0 auto var(--s-4); max-width: 40ch; color: var(--text-soft); font-size: var(--fs-sm); }

/* two-column page split, reusable */
.sk-split { display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--s-4); align-items: start; }
@media (max-width: 1080px) { .sk-split { grid-template-columns: 1fr; } }
.sk-split-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); align-items: start; }
@media (max-width: 1080px) { .sk-split-3 { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------------------
   27. OVERFLOW GUARDS
   Grid and flex children default to min-width:auto, so a wide table inside a
   column pushes the whole page sideways instead of scrolling in its own box.
   -------------------------------------------------------------------------- */
.sk-split > *, .sk-split-3 > *, .sk-kpis > *, .sk-stats > * { min-width: 0; }
.sk-page-head > div { min-width: 0; }
.sk-head-actions { flex-wrap: wrap; }
.sk-tabletools { flex-wrap: wrap; }
.sk-panel, .formsection { max-width: 100%; }
td.middle { max-width: 100vw; }

/* ==========================================================================
   28. DRAWER — richer header, inline actions, section headings
   ========================================================================== */
.sk-drawer-head { align-items: flex-start; gap: var(--s-3); }
.sk-drawer-id {
	display: flex; align-items: center; gap: var(--s-3); min-width: 0;
}
.sk-drawer-idmark {
	display: grid; place-items: center; flex: 0 0 40px;
	width: 40px; height: 40px; border-radius: 11px;
	background: var(--info-bg); color: var(--blue-600);
}
.sk-drawer-idmark .ico { width: 19px; height: 19px; flex: 0 0 19px; }
.sk-drawer-head .docket {
	display: flex; align-items: baseline; gap: var(--s-2);
	font-family: var(--font-mono); font-size: 19px; font-weight: 600;
	letter-spacing: -.02em; color: var(--text-strong); line-height: 1.15;
}
.sk-copybtn {
	display: inline-flex; align-items: center; gap: 4px;
	height: 22px; padding: 0 7px 0 6px;
	border: 1px solid var(--border-strong); border-radius: 20px;
	background: var(--surface); color: var(--text-soft);
	font-family: var(--font-ui); font-size: 10px; font-weight: 600; letter-spacing: .01em;
	white-space: nowrap; cursor: pointer;
	transition: background var(--t), border-color var(--t), color var(--t);
}
.sk-copybtn .ico { width: 11px; height: 11px; flex: 0 0 11px; }
.sk-copybtn:hover { background: var(--blue-50); border-color: var(--blue-300); color: var(--blue-700); }
.sk-copybtn.is-copied { background: var(--ok-bg); border-color: var(--ok-br); color: var(--ok); }
.sk-drawer-head .who { display: block; font-size: var(--fs-md); color: var(--text); }
.sk-drawer-head .sub { display: block; color: var(--text-soft); font-size: var(--fs-xs); margin-top: 1px; }

/* section heading inside panels/drawers */
.sk-sec {
	display: flex; align-items: center; gap: var(--s-2);
	margin: 0 0 var(--s-3);
	color: var(--text-soft);
	font-size: var(--fs-xs); font-weight: 600;
	letter-spacing: .06em; text-transform: uppercase;
}
.sk-sec .ico { width: 14px; height: 14px; flex: 0 0 14px; color: var(--n-400); }
.sk-sec::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.sk-sec + .sk-kv { margin-bottom: var(--s-5); }

/* inline quick actions — removes page hopping */
.sk-inline-actions {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
	gap: var(--s-2); margin-bottom: var(--s-5);
}
.sk-inline-actions button, .sk-inline-actions a {
	justify-content: flex-start;
	height: 38px; padding: 0 var(--s-3);
	font-size: var(--fs-sm);
}
.sk-inline-actions .ico { color: var(--blue-600); }

/* the one action that matters for this stage */
.sk-nextaction {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); margin: 0 0 var(--s-5);
	border: 1px solid var(--info-br); border-radius: var(--r-lg);
	background: linear-gradient(180deg, var(--blue-50), transparent);
}
.sk-nextaction .t { min-width: 0; }
.sk-nextaction b { display: block; font-size: var(--fs-md); color: var(--text-strong); }
.sk-nextaction span { color: var(--text-soft); font-size: var(--fs-xs); }
.sk-nextaction .sk-btn { margin-left: auto; flex: 0 0 auto; }
.sk-nextaction.is-blocked { border-color: var(--warn-br); background: linear-gradient(180deg, var(--warn-bg), transparent); }
.sk-nextaction.is-done { border-color: var(--ok-br); background: linear-gradient(180deg, var(--ok-bg), transparent); }

/* ==========================================================================
   29. LIST — collapsible advanced search, simple docket search
   ========================================================================== */
.sk-searchbar {
	display: flex; align-items: center; gap: var(--s-2);
	padding: var(--s-3) var(--s-4);
}
.sk-searchbar .find { position: relative; flex: 1 1 340px; max-width: 640px; }
.sk-searchbar .find input { padding-left: 34px; height: 38px; }
.sk-searchbar .find .ico {
	position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
	width: 15px; height: 15px; color: var(--n-400); pointer-events: none;
}
.sk-filtertoggle .chev { transition: transform var(--t-slow); width: 13px; height: 13px; flex: 0 0 13px; }
.sk-filtertoggle[aria-expanded="true"] .chev { transform: rotate(180deg); }
.sk-filtertoggle .cnt {
	display: inline-grid; place-items: center;
	min-width: 17px; height: 17px; padding: 0 5px;
	border-radius: 9px; background: var(--blue-600); color: #fff;
	font-size: 10px; font-weight: 600;
}

.sk-adv { display: grid; grid-template-rows: 0fr; opacity: 0; transition: opacity var(--t); }
.sk-adv.is-open { opacity: 1; }
.sk-adv > div { overflow: hidden; }
.sk-adv.is-open { grid-template-rows: 1fr; }
.sk-adv-inner { border-top: 1px solid var(--border); }

/* ==========================================================================
   30. FORM PAGE — record identity header
   ========================================================================== */
.sk-recordhead {
	display: flex; align-items: center; gap: var(--s-4);
	padding: var(--s-4) var(--s-5); margin-bottom: var(--s-5);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-sm);
}
.sk-recordhead-mark {
	display: grid; place-items: center; flex: 0 0 52px;
	width: 52px; height: 52px; border-radius: 14px;
	background: linear-gradient(140deg, var(--blue-500), var(--blue-700));
	color: #fff; box-shadow: var(--sh-glow);
}
.sk-recordhead-mark .ico { width: 24px; height: 24px; flex: 0 0 24px; }
.sk-recordhead .id { min-width: 0; }
.sk-recordhead .docket {
	display: block; font-family: var(--font-mono);
	font-size: 30px; font-weight: 600; letter-spacing: -.035em; line-height: 1.05;
	color: var(--text-strong);
}
.sk-recordhead .meta {
	display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2);
	margin-top: 5px; color: var(--text-soft); font-size: var(--fs-sm);
}
.sk-recordhead .meta i { width: 3px; height: 3px; border-radius: 50%; background: var(--n-300); }
.sk-recordhead-right { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }
.sk-recordhead-stat { text-align: right; padding-left: var(--s-4); }
.sk-recordhead-stat b { display: block; font-family: var(--font-mono); font-size: var(--fs-xl); font-weight: 500; letter-spacing: -.02em; }
.sk-recordhead-stat span { color: var(--text-soft); font-size: var(--fs-xs); letter-spacing: .04em; text-transform: uppercase; }
@media (max-width: 720px) {
	.sk-recordhead { flex-wrap: wrap; }
	.sk-recordhead .docket { font-size: 24px; }
	.sk-recordhead-right { margin-left: 0; width: 100%; }
}

/* legend with icon */
legend.cLegend { display: inline-flex; align-items: center; gap: 7px; }
legend.cLegend .ico { width: 15px; height: 15px; flex: 0 0 15px; color: var(--blue-600); }

/* ==========================================================================
   31. TODAY'S OPS — the working board
   ========================================================================== */
.sk-today {
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-sm);
	margin-bottom: var(--s-4); overflow: hidden;
}
.sk-today-head {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4);
	border-bottom: 1px solid var(--border);
}
.sk-today-head h3 { margin: 0; font-size: var(--fs-md); font-weight: 600; display: flex; align-items: center; gap: var(--s-2); }
.sk-today-head .ico { color: var(--blue-600); }
.sk-today-date { color: var(--text-soft); font-size: var(--fs-xs); }

.sk-today-grid {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
	gap: 0;
}
.sk-queue { border-right: 1px solid var(--border); display: flex; flex-direction: column; min-width: 0; }
.sk-queue:last-child { border-right: 0; }
.sk-queue-head {
	display: flex; align-items: center; gap: var(--s-2);
	padding: var(--s-3) var(--s-4) var(--s-2);
}
.sk-queue-head .n {
	font-family: var(--font-mono); font-size: var(--fs-xl); font-weight: 600;
	letter-spacing: -.02em; line-height: 1;
}
.sk-queue-head .lbl { color: var(--text-soft); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.sk-queue-head .dot { width: 7px; height: 7px; border-radius: 2px; }
.sk-queue.is-urgent .sk-queue-head .n { color: var(--danger); }
.sk-queue.is-urgent .sk-queue-head .dot { background: var(--danger); }
.sk-queue.is-warn .sk-queue-head .n { color: var(--warn); }
.sk-queue.is-warn .sk-queue-head .dot { background: var(--warn); }
.sk-queue.is-info .sk-queue-head .n { color: var(--blue-600); }
.sk-queue.is-info .sk-queue-head .dot { background: var(--blue-600); }
.sk-queue.is-ok .sk-queue-head .n { color: var(--ok); }
.sk-queue.is-ok .sk-queue-head .dot { background: var(--ok); }

.sk-queue-list { flex: 1; padding: 0 var(--s-2) var(--s-2); }
.sk-queue-item {
	display: block; padding: 7px var(--s-2);
	border-radius: var(--r-sm);
	transition: background var(--t-fast);
}
.sk-queue-item:hover { background: var(--blue-50); text-decoration: none; }
.sk-queue-item .d { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 600; color: var(--blue-600); }
.sk-queue-item .c { display: block; font-size: var(--fs-sm); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sk-queue-item .m { color: var(--text-soft); font-size: 10px; }
.sk-queue-foot { padding: var(--s-2) var(--s-3) var(--s-3); }
.sk-queue-foot a { font-size: var(--fs-xs); font-weight: 500; }
.sk-queue-empty { padding: var(--s-4) var(--s-3); color: var(--n-400); font-size: var(--fs-xs); text-align: center; }

/* --------------------------------------------------------------------------
   32. COLLAPSE FIX
   Chrome does not reliably interpolate grid-template-rows between 0fr and 1fr
   when the container height is indefinite — the element gets stuck at the old
   track size. The row change is therefore instant and only opacity animates,
   which is robust and still reads as a reveal.
   -------------------------------------------------------------------------- */
.sk-nav-items, .sk-adv { transition: opacity var(--t) !important; }
.sk-nav-items > div, .sk-adv > div { overflow: hidden; }

/* ==========================================================================
   33. VITALS STRIP — the four facts needed every day, before anything else
   ========================================================================== */
.sk-vitals {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
	gap: 1px; margin-bottom: var(--s-5);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--border); overflow: hidden;
}
.sk-vital { padding: var(--s-3) var(--s-4); background: var(--surface); min-width: 0; }
.sk-vital dt {
	display: flex; align-items: center; gap: 5px; margin-bottom: 5px;
	color: var(--text-soft); font-size: 10px; font-weight: 600;
	letter-spacing: .07em; text-transform: uppercase;
}
.sk-vital dt .ico { width: 12px; height: 12px; flex: 0 0 12px; color: var(--n-400); }
.sk-vital dd { margin: 0; font-size: var(--fs-lg); font-weight: 600; letter-spacing: -.015em; color: var(--text-strong); line-height: 1.25; }
.sk-vital dd small { display: block; font-size: var(--fs-xs); font-weight: 400; color: var(--text-soft); letter-spacing: 0; }
.sk-vital dd.money { font-family: var(--font-mono); font-size: var(--fs-xl); letter-spacing: -.03em; }
.sk-vital.is-danger dd { color: var(--danger); }
.sk-vital.is-ok dd { color: var(--ok); }
.sk-vital.is-warn dd { color: var(--warn); }

/* ==========================================================================
   34. RECORD CARDS — replaces the flat section headings
   ========================================================================== */
.sk-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--s-3); }
.sk-card {
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); overflow: hidden; min-width: 0;
}
.sk-card-head {
	display: flex; align-items: center; gap: var(--s-2);
	padding: var(--s-3) var(--s-4);
	border-bottom: 1px solid var(--border);
	background: var(--surface-sub);
}
.sk-card-head .ico { width: 15px; height: 15px; flex: 0 0 15px; color: var(--blue-600); }
.sk-card-head h4 {
	margin: 0; font-size: var(--fs-md); font-weight: 600;
	letter-spacing: -.005em; color: var(--text-strong);
}
.sk-card-head .tail { margin-left: auto; color: var(--text-soft); font-size: var(--fs-xs); }
.sk-card-body { padding: var(--s-4); }
.sk-card--wide { grid-column: 1 / -1; }

/* field rows inside a card — label left, value right, easy to scan */
.sk-fields { display: flex; flex-direction: column; }
.sk-fields > div {
	display: flex; align-items: baseline; gap: var(--s-4);
	padding: 7px 0; border-bottom: 1px dashed var(--border);
}
.sk-fields > div:last-child { border-bottom: 0; }
.sk-fields dt {
	flex: 0 0 118px; color: var(--text-soft);
	font-size: var(--fs-sm); font-weight: 500;
}
.sk-fields dd {
	margin: 0; flex: 1; min-width: 0;
	color: var(--text-strong); font-size: var(--fs-md); font-weight: 500;
	word-break: break-word;
}
.sk-fields dd.mono { font-family: var(--font-mono); }

/* ==========================================================================
   35. MENU — dropdown for secondary actions
   ========================================================================== */
.sk-menu-wrap { position: relative; }
.sk-menu {
	position: absolute; top: calc(100% + 6px); right: 0; z-index: 92;
	min-width: 216px; padding: var(--s-1);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-lg);
	opacity: 0; transform: translateY(-4px) scale(.98);
	pointer-events: none;
	transition: opacity var(--t), transform var(--t);
}
.sk-menu.is-on { opacity: 1; transform: none; pointer-events: auto; }
.sk-menu button, .sk-menu a {
	display: flex; align-items: center; gap: var(--s-3);
	width: 100%; height: 34px; padding: 0 var(--s-3);
	border: 0; border-radius: var(--r-sm); background: transparent; box-shadow: none;
	color: var(--text); font-size: var(--fs-sm); font-weight: 400;
	text-align: left; justify-content: flex-start;
}
.sk-menu button:hover, .sk-menu a:hover { background: var(--blue-50); color: var(--blue-700); box-shadow: none; }
.sk-menu .ico { color: var(--n-400); width: 15px; height: 15px; flex: 0 0 15px; }
.sk-menu button:hover .ico, .sk-menu a:hover .ico { color: var(--blue-600); }
.sk-menu hr { margin: var(--s-1) 0; border: 0; border-top: 1px solid var(--border); }
.sk-menu-label {
	padding: var(--s-2) var(--s-3) 4px; color: var(--text-soft);
	font-size: 10px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
}

/* ==========================================================================
   36. SIDEBAR RAIL — user-controlled collapse
   ========================================================================== */
.sk-railtoggle {
	display: grid; place-items: center;
	width: 26px; height: 26px; margin-left: auto;
	border: 1px solid rgba(255,255,255,.12); border-radius: var(--r-sm);
	background: rgba(255,255,255,.05); color: #9db2ca;
	box-shadow: none; cursor: pointer;
	transition: background var(--t), color var(--t);
}
.sk-railtoggle:hover { background: rgba(255,255,255,.12); color: #fff; }
.sk-railtoggle .ico { width: 14px; height: 14px; flex: 0 0 14px; transition: transform var(--t-slow); }
body.is-rail .sk-railtoggle .ico { transform: rotate(180deg); }

body.is-rail { --sidebar-w: 72px; }
body.is-rail .sk-brand-name,
body.is-rail .sk-brand-sub,
body.is-rail .sk-nav a span:not(.sk-nav-badge),
body.is-rail .sk-nav-title span,
body.is-rail .sk-nav-title .chev { display: none; }
body.is-rail .sk-side-head { justify-content: center; padding: 0; }
body.is-rail .sk-railtoggle { position: absolute; bottom: var(--s-3); left: 50%; transform: translateX(-50%); margin: 0; }
body.is-rail .sk-nav-title { justify-content: center; padding: 7px 0; }
body.is-rail .sk-nav a, body.is-rail a.linkCss { justify-content: center; padding: 9px 0 !important; margin-bottom: 3px; }
body.is-rail .sk-nav-group.is-collapsed .sk-nav-items { grid-template-rows: 1fr; opacity: 1; }
body.is-rail a.linkCss.is-active::before { display: none; }
body.is-rail .sk-nav-badge {
	position: absolute; top: 3px; right: 8px; margin: 0;
	min-width: 15px; padding: 0 4px; font-size: 9px; line-height: 15px;
}

/* ==========================================================================
   37. FIELDSET → CARD HEADER  (no markup change; legend becomes a real header)
   ========================================================================== */
fieldset.cFielSets { padding: 0; border: 1px solid var(--border); overflow: hidden; }
legend.cLegend {
	float: left; width: 100%; margin: 0; padding: var(--s-3) var(--s-4);
	border-bottom: 1px solid var(--border);
	background: var(--surface-sub);
	font-size: var(--fs-md); font-weight: 600; letter-spacing: -.005em;
	color: var(--text-strong);
}
legend.cLegend + * { clear: both; }
fieldset.cFielSets > *:not(legend) { padding: 0 var(--s-4); }
fieldset.cFielSets > *:not(legend):first-of-type { padding-top: var(--s-4); }
fieldset.cFielSets > *:not(legend):last-child { padding-bottom: var(--s-2); }
fieldset.cFielSets .form-cols { padding-top: var(--s-4); }

/* ==========================================================================
   38. STAGE STRIP on the record page
   ========================================================================== */
.sk-stagestrip {
	margin-bottom: var(--s-5);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-sm);
	overflow: hidden;
}
.sk-stagestrip .sk-life { padding: var(--s-5) var(--s-4) var(--s-4); }
.sk-stagestrip .sk-life-note { margin: 0 var(--s-4) var(--s-4); }

/* ==========================================================================
   39. CONSISTENCY PASS
   The prototype had grown three header treatments and six icon stroke widths.
   These rules collapse them to one of each.
   ========================================================================== */

/* Inline SVG presentation attributes lose to CSS, so this normalises every
   icon in the app regardless of what the markup says. */
svg.ico, svg.chev { stroke-width: 1.7; }
svg.ico[stroke-width="2.2"] { stroke-width: 2.2; }   /* delta arrows stay bolder */

/* One panel header treatment — .sk-panel-head, .headertext and .sk-card-head
   were drifting apart. */
.formsection > h3, .sk-panel-head, .headertext, .sk-card-head {
	display: flex; align-items: center; gap: var(--s-3);
	margin: 0; padding: var(--s-3) var(--s-4);
	border-bottom: 1px solid var(--border);
	background: var(--surface-sub);
	color: var(--text-strong);
	font-size: var(--fs-md); font-weight: 600; letter-spacing: -.005em;
}

/* ==========================================================================
   40. CARDS — refined
   ========================================================================== */
.sk-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(316px, 1fr)); gap: var(--s-4); }

.sk-card {
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); overflow: hidden; min-width: 0;
	box-shadow: var(--sh-xs);
	transition: border-color var(--t), box-shadow var(--t);
}
.sk-card:hover { border-color: var(--border-strong); box-shadow: var(--sh-sm); }

/* icon sits in its own tinted tile — reads as designed, not decorated */
.sk-card-ico {
	display: grid; place-items: center; flex: 0 0 26px;
	width: 26px; height: 26px; border-radius: 8px;
	background: var(--info-bg); color: var(--blue-600);
}
.sk-card-ico .ico { width: 14px; height: 14px; flex: 0 0 14px; }
.sk-card-head h4 { margin: 0; font-size: var(--fs-md); font-weight: 600; letter-spacing: -.005em; }
.sk-card-body { padding: var(--s-2) var(--s-4) var(--s-3); }

/* field rows — hairline rules, tighter rhythm, clear label/value contrast */
.sk-fields { display: flex; flex-direction: column; margin: 0; }
.sk-fields > div {
	display: flex; align-items: baseline; gap: var(--s-4);
	padding: 9px 0;
	border-bottom: 1px solid var(--border);
}
.sk-fields > div:last-child { border-bottom: 0; }
.sk-fields dt {
	flex: 0 0 104px; margin: 0;
	color: var(--text-soft);
	font-size: var(--fs-xs); font-weight: 600;
	letter-spacing: .04em; text-transform: uppercase;
	line-height: 1.5;
}
.sk-fields dd {
	margin: 0; flex: 1; min-width: 0;
	color: var(--text-strong);
	font-size: var(--fs-md); font-weight: 500;
	line-height: 1.45; word-break: break-word;
}
.sk-fields dd.mono { font-family: var(--font-mono); font-size: var(--fs-sm); letter-spacing: -.01em; }

/* ==========================================================================
   41. VITALS — refined
   ========================================================================== */
.sk-vitals {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(146px, 1fr));
	gap: 1px; margin-bottom: var(--s-4);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--border); overflow: hidden;
	box-shadow: var(--sh-xs);
}
.sk-vital { padding: var(--s-3) var(--s-4) var(--s-4); background: var(--surface); min-width: 0; }
.sk-vital dt {
	display: flex; align-items: center; gap: 6px; margin: 0 0 var(--s-2);
	color: var(--text-soft); font-size: 10px; font-weight: 600;
	letter-spacing: .08em; text-transform: uppercase;
}
.sk-vital dd { margin: 0; font-size: var(--fs-lg); font-weight: 600; letter-spacing: -.015em; line-height: 1.2; }
.sk-vital dd small {
	display: block; margin-top: 3px;
	font-size: var(--fs-xs); font-weight: 400; letter-spacing: 0;
	color: var(--text-soft);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* record body wrapper — one padding rule for drawer and full page */
.sk-recordbody { padding: var(--s-5); }
.sk-drawer .sk-recordbody { padding: var(--s-5); }

/* menu button chevron */
#drawerMore .chev { width: 12px; height: 12px; flex: 0 0 12px; opacity: .6; }

/* ==========================================================================
   42. EDIT-PAGE RAIL — use the shared card component, not bespoke CSS
   ========================================================================== */
.sk-rail-summary { display: flex; flex-direction: column; }
.sk-rail-summary > div {
	display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3);
	padding: 9px 0; border-bottom: 1px solid var(--border);
	font-size: var(--fs-md);
}
.sk-rail-summary > div:last-child { border-bottom: 0; }
.sk-rail-summary dt { color: var(--text-soft); font-size: var(--fs-sm); margin: 0; }
.sk-rail-summary dd { margin: 0; font-family: var(--font-mono); font-weight: 500; }
.sk-rail-summary .is-total dt { color: var(--text-strong); font-weight: 600; }
.sk-rail-summary .is-total dd { color: var(--danger); font-weight: 600; font-size: var(--fs-lg); }

.sk-person { display: flex; align-items: center; gap: var(--s-3); }
.sk-person .sk-avatar { width: 36px; height: 36px; border-radius: 10px; font-size: var(--fs-sm); }
.sk-person b { display: block; font-size: var(--fs-md); font-weight: 600; }
.sk-person span { color: var(--text-soft); font-size: var(--fs-xs); }

/* ==========================================================================
   43. MOBILE — real fixes, not clipping
   --------------------------------------------------------------------------
   The earlier `overflow-x: clip` guard on td.middle stopped the PAGE scrolling
   sideways but simply cut off anything too wide (paging spilled to 437px in a
   375px viewport). Content now wraps or scrolls in its own box instead.
   ========================================================================== */
td.middle { overflow-x: visible; }

@media (max-width: 900px) {
	/* nothing may silently exceed the viewport */
	body { overflow-x: hidden; }

	/* paging: keep prev/next reachable, let the numbers scroll */
	.sk-paging { flex-wrap: wrap; gap: var(--s-2); }
	.sk-pages {
		margin-left: 0; width: 100%;
		overflow-x: auto; -webkit-overflow-scrolling: touch;
		scrollbar-width: none; padding-bottom: 2px;
	}
	.sk-pages::-webkit-scrollbar { display: none; }
	.sk-pages a, .sk-pages span { flex: 0 0 auto; }

	/* toolbars stack rather than spill */
	.sk-tabletools, .sk-searchbar, .sk-actions, .sk-today-head { flex-wrap: wrap; }
	.sk-searchbar .find { flex: 1 1 100%; max-width: none; }
	.sk-tabletools .sk-spacer, .sk-today-head > span[style] { display: none; }

	/* record identity stacks */
	.sk-recordhead { flex-wrap: wrap; gap: var(--s-3); }
	.sk-recordhead .docket { font-size: 26px; }
	.sk-recordhead-right { width: 100%; flex-wrap: wrap; margin-left: 0; }
	.sk-recordhead-stat { padding-left: 0; text-align: left; }
	.sk-recordhead-stat + .sk-recordhead-stat { border-left: 0 !important; padding-left: var(--s-4); }

	/* drawer takes the screen */
	.sk-drawer { width: 100vw; }
	.sk-drawer-head { flex-wrap: wrap; }
	.sk-drawer-actions { width: 100%; justify-content: flex-end; }
	.sk-recordbody { padding: var(--s-4); }

	/* lifecycle: 8 steps do not fit — scroll it */
	.sk-life-track {
		overflow-x: auto; -webkit-overflow-scrolling: touch;
		padding-bottom: var(--s-2); scrollbar-width: none;
	}
	.sk-life-track::-webkit-scrollbar { display: none; }
	.sk-life-step { flex: 0 0 92px; }

	/* one-column reading */
	.sk-cards { grid-template-columns: 1fr; }
	.sk-vitals { grid-template-columns: 1fr 1fr; }
	.sk-kv { grid-template-columns: 1fr; }
	.form-cols { grid-template-columns: 1fr !important; }
	.form-main { grid-template-columns: 1fr !important; }

	/* today board: one queue per row, scrollable lists */
	.sk-today-grid { grid-template-columns: 1fr; }
	.sk-queue { border-right: 0; border-bottom: 1px solid var(--border); }
	.sk-queue:last-child { border-bottom: 0; }

	/* the sticky save bar must clear the prototype bar */
	.savebar { bottom: 48px; flex-wrap: wrap; }

	/* command palette */
	.sk-cmdk { padding-top: 6vh; }

	/* prototype chrome scrolls instead of spilling */
}

@media (max-width: 560px) {
	.sk-vitals { grid-template-columns: 1fr; }
	.sk-fields > div { flex-direction: column; gap: 2px; padding: 8px 0; }
	.sk-fields dt { flex: none; }
	.sk-head-actions { flex-wrap: wrap; }
	.sk-head-actions .sk-btn { flex: 1 1 auto; }
	.sk-recordhead .docket { font-size: 22px; }
	.sk-drawer-head .docket { font-size: 17px; }
	.listHeader, .sk-title { font-size: 17px; }
	.sk-tab { padding: 10px var(--s-2); font-size: var(--fs-xs); }
	.sk-doc { padding: var(--s-4); }
	.sk-dl { grid-template-columns: 96px 1fr; }
}

/* touch targets */
@media (pointer: coarse) {
	.actionLink { width: 34px; height: 34px; }
	.sk-pages a, .sk-pages span { min-width: 36px; height: 36px; }
	.sk-check { width: 19px; height: 19px; flex: 0 0 19px; }
	.sk-check:checked::after { left: 5.5px; top: 2px; }
}

/* ==========================================================================
   44. [COMPAT] SEARCH BAR — the flat #C4ECFF legacy box, modernised
   --------------------------------------------------------------------------
   79 live pages build their filter bar as .searchB > <table><tr>
   <td class="buttonSa"> containing a loose flow of "Label: <input>" pairs,
   a Search link and a Reset link, with no per-field wrapper markup at all.
   19 of those pages are reachable from the live menu (callReport, agent,
   dealer, make, model, product, TCRMaster, dashBoard's DSR box, etc).

   This is handled entirely in CSS, with no page edits, using flexbox:
   turning the .searchB > table > tr > td.buttonSa cell into a wrapping flex
   row makes every text run and every control (input/select/link) become
   its own flex item, arranging automatically into a tidy wrapped bar --
   which is what a table-cell full of loose inline content cannot do on
   its own. Scoped to ".searchB td.buttonSa" specifically (not bare
   .buttonSa) so the other two unrelated uses of that class elsewhere in
   the app -- a single-control wrapper, and a hidden row-action holder --
   are completely unaffected.
   ========================================================================== */

.searchB {
	background: var(--surface) !important;
	border: 1px solid var(--border);
	border-radius: var(--r-lg);
	padding: 0 !important;
	margin: 0 0 var(--s-4);
	box-shadow: var(--sh-sm);
	overflow: hidden;
}
.searchB table { width: 100%; border-collapse: collapse; }
.searchB table td { border: 0; }

.searchB td.buttonSa:only-child {
	display: flex !important;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 14px;
	padding: var(--s-4) !important;
}
/* every bare run of label text between controls becomes its own flex item;
   give it the same treatment as a real .sk-field label */
.searchB td.buttonSa:only-child {
	font-size: var(--fs-sm);
	color: var(--text-soft);
	font-weight: 500;
}
/* controls keep their own compact/full width per the rule above this one
   (inline style, .fWidth, or default) -- just align them on the same line */
.searchB td.buttonSa:only-child input,
.searchB td.buttonSa:only-child select {
	flex: 0 0 auto;
}
/* [FIX] :not(:has(#skSearchbar)) matters here: once wireSearchBar() (js/skyled.js)
   rebuilds this cell, every select.fWidth is re-parented into .sk-field, a FLEX
   COLUMN container -- where flex-basis sets the main axis, i.e. HEIGHT, not width.
   This rule was written for the earlier flat flex-ROW "bag of controls" layout,
   where 200px meant width. Left unscoped it silently turned every dropdown in the
   rebuilt Advanced panel into a 200px-TALL box (found live: the Dealer select
   rendered as an open-looking 200px listbox). Guarded so it only still applies to
   the handful of pages with too few fields for wireSearchBar() to touch
   (agent.php, dealer.php, make.php, ...), where the original flat layout remains. */
.searchB td.buttonSa:only-child:not(:has(#skSearchbar)) select.fWidth {
	flex: 1 1 200px;   /* the rare explicit-fWidth dropdown gets a row of its own */
}
/* belt and braces: inside the rebuilt panel, a field's control always fills its
   own grid cell, never grows/shrinks against unrelated siblings */
.sk-field > select.fWidth,
.sk-field > input.fWidth,
.sk-field > .textbox {
	flex: 0 0 auto;
}
.searchB td.buttonSa:only-child a.searchButton,
.searchB td.buttonSa:only-child a.resetButton,
.searchB td.buttonSa:only-child input[type="submit"] {
	margin-left: auto;
}
.searchB td.buttonSa:only-child a.resetButton { margin-left: 0; }

/* headertext immediately above a searchB reads as the panel title */
.headertext + .searchB,
.headertext ~ .searchB { margin-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }

/* row selection tint (set by the list page's own script) */
table.listTable > tbody > tr.is-selected > td { background: var(--info-bg); }

/* ==========================================================================
   45. ROW ACTIONS -- Edit / Delete / View inside a table row
   --------------------------------------------------------------------------
   These are NOT page-level buttons. In the legacy markup they sit inside
   <td class="actionLink"> within a <span class="buttonSa" style="display:none">
   that the row reveals on hover, and they carry the words "Edit"/"Delete".
   Styling them as full buttons blew the row height apart and put a large
   red Delete block in every row. They are compact text actions instead.
   ========================================================================== */
td.actionLink { white-space: nowrap; }
td.actionLink .buttonSa { display: inline-flex !important; align-items: center; gap: var(--s-2); }

a.editButton, a.deleteButton, a.viewButton {
	display: inline-flex; align-items: center; justify-content: center;
	height: 26px; padding: 0 10px;
	border: 1px solid var(--border-strong); border-radius: var(--r-sm);
	background: var(--surface);
	color: var(--n-600);
	font-size: var(--fs-xs); font-weight: 500; line-height: 1;
	white-space: nowrap; text-decoration: none;
	box-shadow: none;
	transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
a.editButton:hover  { background: var(--blue-50);   border-color: var(--blue-200); color: var(--blue-700); text-decoration: none; }
a.viewButton:hover  { background: var(--blue-50);   border-color: var(--blue-200); color: var(--blue-700); text-decoration: none; }
a.deleteButton      { color: var(--danger); border-color: var(--danger-br); }
a.deleteButton:hover{ background: var(--danger-bg); border-color: var(--danger); color: var(--danger); text-decoration: none; }

/* ==========================================================================
   46. LAYOUT FIXES found by measuring the live pages
   -------------------------------------------------------------------------- */

/* (a) The global "call not closed" alert is emitted by top.php INSIDE
   .curvebox, i.e. before <table class="container"> and therefore outside the
   content column. With the topbar fixed, it rendered at top:-6px -- entirely
   hidden behind the topbar while still consuming ~60px on every page, which
   is what made every screen start with a large empty band.
   .curvebox now clears the topbar, and the alert is aligned to the content
   column and made compact. */
.curvebox { padding-top: var(--topbar-h); }
.container td.middle, td.middle {
	padding-top: var(--s-5) !important;
}
.curvebox > .sk-flash {
	margin: var(--s-4) var(--s-6) 0 calc(var(--sidebar-w) + var(--s-6));
	padding: 7px var(--s-3);
	font-size: var(--fs-xs);
	transition: margin-left var(--t);
}
.curvebox > .sk-flash .ico { width: 13px !important; height: 13px !important; flex: 0 0 13px !important; }

/* (b) "Search Option / Record per page" (.headertext) and the filter box
   (.searchB) are two separate elements in the legacy markup and were
   rendering as two stacked cards with a gap. They are one control, so they
   are merged into a single card: header on top, fields below. */
.headertext {
	margin-bottom: 0;
	border: 1px solid var(--border);
	border-bottom: 0;
	border-radius: var(--r-lg) var(--r-lg) 0 0;
	/* a tinted header band gives the search card a top, instead of the
	   plain-white-on-white the header and the row beneath it shared */
	background: var(--surface-sub);
}
.sk-searchbar { background: var(--surface); }
.searchB {
	margin-top: 0 !important;
	border-top: 0;
	border-radius: 0 0 var(--r-lg) var(--r-lg);
}
/* a .headertext used as a panel head inside a card keeps square corners */
.formsection > .headertext,
.sk-panel > .headertext {
	border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
}

/* (c) the search card was built at full form-field height (36-38px controls,
   12px padding on both the header and the search row) even though its
   default state -- no filters open -- is just one search field, a page-size
   dropdown and a button. Shrunk to a compact bar; the advanced panel that
   drops down from .sk-filtertoggle keeps its own full-size fields, this
   only touches the always-visible header + search row. */
.headertext:has(+ .searchB) {
	padding: 6px var(--s-4) !important;
}
.headertext:has(+ .searchB) select {
	height: 26px !important; line-height: 24px !important;
	padding: 0 22px 0 8px !important; font-size: var(--fs-xs) !important;
	background-position: right 8px center !important;
}
.sk-searchbar {
	padding: var(--s-2) var(--s-4) !important;
}
.sk-searchbar .find input {
	height: 32px !important;
	/* [FIX] the moved control keeps whatever inline width the legacy markup
	   gave it (several pages hardcode style="width:100px"), so it sat tiny
	   and truncated inside a .find wrapper that was growing around it for
	   no visible benefit. The wrapper's width is now the input's width. */
	width: 100% !important;
}
.sk-searchbar .sk-btn {
	height: 32px !important; padding: 0 var(--s-3) !important; font-size: var(--fs-xs) !important;
}

/* (d) wireSearchBar() (js/skyled.js) folds the "Search Option / Record per
   page" header into this same row and hides the header div entirely --
   the header's own tinted-top-and-radius treatment from (b) above is gone
   with it, so the now-solo .searchB needs its full card shape back. */
.searchB.sk-merged {
	border-top: 1px solid var(--border) !important;
	border-radius: var(--r-lg) !important;
}
.sk-searchbar .sk-pp {
	display: flex; align-items: center; gap: 6px;
	color: var(--text-soft); font-size: var(--fs-xs); font-weight: 500;
	white-space: nowrap;
}
.sk-searchbar .sk-pp select {
	height: 32px !important; width: auto; min-width: 54px;
	padding: 0 22px 0 8px !important; font-size: var(--fs-xs) !important;
	background-position: right 8px center !important;
}

/* ==========================================================================
   47. DATA TABLE — modern treatment
   --------------------------------------------------------------------------
   77 live pages render a .listTable; 60 of them end with a td.actionLink
   holding the row's Edit/Delete controls. Because these tables are wider
   than the viewport, that action column was scrolled off the right edge and
   became unreachable without horizontal scrolling. It is now frozen to the
   right, mirroring the frozen identity column on the left, so a row's
   identity and its actions are both always on screen.
   ========================================================================== */

/* --- header --------------------------------------------------------------- */
table.listTable tr.borderTitle > td {
	padding: 11px var(--s-3) !important;
	height: auto;
	background: var(--surface-sub) !important;
	color: var(--text-soft) !important;
	font-size: 10px !important;
	font-weight: 600 !important;
	letter-spacing: .07em !important;
	text-transform: uppercase;
	text-align: left !important;
	white-space: nowrap;
	border-bottom: 1px solid var(--border) !important;
	border-left: 0 !important;
	vertical-align: middle;
}
table.listTable tr.borderTitle > td b { font-weight: 600; }

/* --- body ----------------------------------------------------------------- */
table.listTable > tbody > tr > td,
table.listTable > tr > td {
	padding: 11px var(--s-3);
	border-bottom: 1px solid var(--n-100);
	border-left: 0;
	border-right: 0;
	color: var(--text);
	font-size: var(--fs-sm);
	line-height: 1.45;
	vertical-align: middle;
	background: var(--surface);
}
table.listTable > tbody > tr:hover > td,
table.listTable > tr:hover > td { background: var(--blue-50); }

/* legacy zebra/border classes must not fight the new look */
table.listTable tr.border > td { border-top: 0; }

/* --- frozen ACTION column, right edge -------------------------------------
   ONLY on tables whose last cell is a row-action cell. Freezing the last
   column unconditionally pinned real data (e.g. "status" on the check
   in/out report), which is wrong -- a data column has no reason to follow
   the horizontal scroll. Gated with :has(); browsers without it simply get
   a normal scrolling table, which is the old behaviour. */
table.listTable tr:has(> td.actionLink) > td:last-child {
	position: sticky;
	right: 0;
	z-index: 12;
	background: var(--surface);
	box-shadow: -8px 0 12px -10px rgba(15, 23, 42, .45);
}
table.listTable:has(td.actionLink) tr.borderTitle > td:last-child {
	position: sticky;
	right: 0;
	z-index: 32;
	background: var(--surface-sub);
	box-shadow: -8px 0 12px -10px rgba(15, 23, 42, .45);
}
table.listTable > tbody > tr:hover:has(> td.actionLink) > td:last-child,
table.listTable > tr:hover:has(> td.actionLink) > td:last-child { background: var(--blue-50); }
table.listTable > tbody > tr.is-selected:has(> td.actionLink) > td:last-child { background: var(--info-bg); }

/* the action cell itself: keep controls on one line, comfortably padded */
table.listTable td.actionLink {
	/* legacy markup carries an inline style="width:80px" that is too narrow
	   for "Edit + Delete" once they are real controls -- the content clipped
	   inside the frozen cell. */
	width: auto !important;
	min-width: 132px !important;
	padding: 8px var(--s-3) !important;
	text-align: right;
	white-space: nowrap;
}

/* --- row actions are revealed on hover in the legacy markup ---------------
   <span class="buttonSa" style="display:none"> is un-hidden by the page's
   own JS on mouseover. Showing them always is steadier to use and avoids a
   row that looks empty until hovered. */
table.listTable td.actionLink .buttonSa[style*="display:none"] {
	display: inline-flex !important;
}

/* --- compact density ------------------------------------------------------ */
.sk-tablewrap.is-compact table.listTable > tbody > tr > td,
.sk-tablewrap.is-compact table.listTable > tr > td { padding: 5px var(--s-3); }
.sk-tablewrap.is-compact table.listTable tr.borderTitle > td { padding: 7px var(--s-3) !important; }
.sk-tablewrap.is-compact table.listTable td.actionLink { padding: 3px var(--s-3); }

/* --- the scroll container ------------------------------------------------- */
.sk-tablewrap {
	border-radius: var(--r-lg);
	border: 1px solid var(--border);
}
.sk-tabletools + .sk-tablewrap { border-radius: 0 0 var(--r-lg) var(--r-lg); border-top: 0; }
.sk-tablewrap table.listTable { border: 0 !important; }

/* legacy wrappers that used to do the scrolling themselves */
.row[style*="overflow"] { overflow: visible !important; }

/* ==========================================================================
   48. DASHBOARD — status breakdown
   The old dashboard was a 600px table of status names and raw counts, with
   no sense of proportion and nothing clickable. Same numbers, but each row
   now carries its share of the total and links straight to the filtered
   list, which is what people were doing manually afterwards anyway.
   ========================================================================== */
.sk-kpi { display: block; text-decoration: none; color: inherit; }
.sk-kpi:hover .sk-kpi-value { color: var(--blue-600); }
.sk-kpi-value--warn { color: var(--warn-600, #b45309); }
.sk-kpi-value--mute { color: var(--text-soft); }

.sk-card--dash { margin-bottom: var(--s-4); }
.sk-card--dash .sk-card-head { padding: var(--s-3) var(--s-4); }

.sk-statuslist { display: flex; flex-direction: column; }
.sk-statusrow {
	display: grid;
	grid-template-columns: minmax(160px, 1.5fr) minmax(80px, 3fr) 72px 60px;
	align-items: center;
	gap: var(--s-3);
	padding: 10px var(--s-4);
	border-top: 1px solid var(--n-100);
	color: var(--text);
	font-size: var(--fs-sm);
	text-decoration: none;
	transition: background var(--t);
}
.sk-statusrow:first-child { border-top: 0; }
.sk-statusrow:hover { background: var(--blue-50); }
.sk-statusrow:hover .sk-statusrow-name { color: var(--blue-700); }
.sk-statusrow-name { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }
.sk-statusrow-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* a plain inline marker -- distinct from .sk-dot, which is the absolutely
   positioned notification badge in the top bar */
.sk-statdot {
	flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%;
	background: var(--n-400);
}
.sk-statdot.sk-pill--alloc   { background: var(--blue-500); }
.sk-statdot.sk-pill--pending { background: #d97706; }
.sk-statdot.sk-pill--due     { background: var(--danger); }
.sk-statdot.sk-pill--closed  { background: var(--ok); }
.sk-statdot.sk-pill--cancel  { background: var(--n-400); }

.sk-statusrow-bar {
	position: relative; height: 6px; border-radius: 999px;
	background: var(--n-100); overflow: hidden;
}
.sk-statusrow-bar > i {
	display: block; height: 100%; border-radius: 999px;
	background: var(--blue-500);
	transition: width .4s var(--ease, ease);
}
.sk-statusrow-n {
	font-family: var(--font-mono); font-size: var(--fs-sm);
	text-align: right; color: var(--text-strong);
}
.sk-statusrow-pct {
	font-family: var(--font-mono); font-size: var(--fs-xs);
	text-align: right; color: var(--text-soft);
}

@media (max-width: 700px) {
	.sk-statusrow { grid-template-columns: 1fr 64px 54px; }
	.sk-statusrow-bar { grid-column: 1 / -1; grid-row: 2; }
}

/* ==========================================================================
   49. CALL REGISTRATION — the form / docket-history split
   servicedataEdit.php lays its two panels out as a table with a 650px cell
   and a 550px cell. That is 1200px of fixed width inside a content column
   that is ~970px on a 1512px screen, so both panels were crushed: labels
   wrapped mid-word and "Service Type" got a 25px select. Same two panels,
   sized in proportion instead, stacking when there is no room for both.
   ========================================================================== */
table.sk-formsplit,
table.sk-formsplit > tbody,
table.sk-formsplit > tbody > tr { display: block; width: 100%; }
table.sk-formsplit > tbody > tr {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--s-5);
	align-items: start;
}
table.sk-formsplit > tbody > tr > td {
	display: block;
	width: auto !important;
	min-width: 0;
	padding: 0;
}
/* Side by side only where both panels genuinely fit. Measured on the live
   page: the form needs 622px of min-content and the content row is 920px
   at a 1512px viewport, so a two-column split at that size squeezes the
   form back into the state this was meant to fix. Below the threshold the
   history reads better full width underneath than in a 400px gutter. */
@media (min-width: 1680px) {
	table.sk-formsplit > tbody > tr {
		grid-template-columns: minmax(620px, 1.3fr) minmax(380px, 1fr);
	}
}

/* previous dockets for the customer being typed in -- was a bare 550x320
   inline scroll box with no edge, so it read as loose text on the page.
   [FIX] callUpdation.php lays this out old-school -- a two-column
   <table>, this box in the right <td>, the real form (Call Details,
   Billing, Repair, five Document rows) in the left one. A table row
   always matches its tallest cell, so with a ~260px box next to a
   ~1650px form, the right column was actually ~1650px tall -- box at
   the top, then well over 1000px of pure blank white below it,
   confirmed live via getBoundingClientRect(). Anyone scrolling down for
   Engineer Allocation or Spare Master (both come after this table) had
   to scroll through that dead space to get there. position:sticky keeps
   the box docked near the top of the viewport for as long as its
   over-tall cell is on screen, instead of sitting still while a
   half-empty cell scrolls past it. */
.sk-dockethistory {
	height: 260px;
	position: sticky;
	top: calc(var(--topbar-h) + var(--s-4));
	overflow-y: auto;
	width: 100%;
	padding: var(--s-3);
	border: 1px solid var(--border);
	border-radius: var(--r-lg);
	background: var(--surface-sub);
}
.sk-dockethistory:empty::before,
.sk-dockethistory > div:empty::before {
	content: "Previous calls for this customer appear here.";
	color: var(--text-soft);
	font-size: var(--fs-sm);
}

/* ==========================================================================
   50. SEARCH BARS — stop one long option from widening the whole page
   A <select> sizes itself to its longest option. mif.php's Customer filter
   holds full customer names, so it rendered 445px wide, pushed its search
   table to 1001px and made the entire document scroll sideways -- the list
   table's own header was cut off the right edge as a result. Capping the
   control does not hide anything: the full text is still shown in the
   dropdown when it is opened.
   ========================================================================== */
.searchB select,
.searchB input[type="text"] { max-width: 230px; }
.searchB select { text-overflow: ellipsis; }
.searchB table { max-width: 100%; }

/* nothing in the page frame may force the document itself to scroll sideways;
   wide content belongs in its own scroll container (.sk-tablewrap) */
table.container > tbody > tr > td.middle { min-width: 0; max-width: 100%; }

/* --- the OTHER search-bar shape ------------------------------------------
   Not every filter bar is one big cell. mif.php and partServiceReport.php
   build a real multi-cell table: <td>Label:</td><td><control></td> repeated
   across a row. Those rows cannot wrap, so on mif.php the bar demanded
   1001px inside a 1007px column and the whole DOCUMENT scrolled sideways --
   the list table's own header was cut off at the right edge as a result.
   Laying the row out as a wrapping flex line fixes it without touching the
   markup, and leaves the single-cell shape above alone. */
.searchB table > tbody > tr:has(> td + td) {
	/* a grid of label/field PAIRS, not a plain wrapping line: with flex-wrap
	   a label could wrap onto the next line away from its own field, which
	   is exactly what happened to "From:" on partServiceReport.php */
	display: grid;
	grid-template-columns: max-content minmax(110px, 1fr) max-content minmax(110px, 1fr) max-content minmax(110px, 1fr);
	align-items: center;
	gap: 12px 8px;
	padding: var(--s-4);
}
@media (max-width: 1100px) {
	.searchB table > tbody > tr:has(> td + td) {
		grid-template-columns: max-content minmax(110px, 1fr) max-content minmax(110px, 1fr);
	}
}
@media (max-width: 700px) {
	.searchB table > tbody > tr:has(> td + td) {
		grid-template-columns: max-content minmax(0, 1fr);
	}
}
.searchB table > tbody > tr:has(> td + td) > td {
	display: flex;
	align-items: center;
	padding: 0 !important;
	font-size: var(--fs-sm);
	color: var(--text-soft);
	font-weight: 500;
}
/* a label cell hugs its text; the control cell that follows it gets the room */
.searchB table > tbody > tr:has(> td + td) > td:not(:has(input, select, textarea)) {
	padding-right: 4px !important;
	white-space: nowrap;
}
.searchB table > tbody > tr:has(> td + td) > td:has(input, select) {
	padding-right: var(--s-4) !important;
}
.searchB table > tbody > tr:has(> td + td) > td:has(input, select) > * { width: 100%; max-width: 230px; }
/* cells the page itself hides must not take part in the flex line */
.searchB table > tbody > tr > td[style*="display:none"] { display: none !important; }

/* ==========================================================================
   51. RECORD DRAWER — the parts that were styled but never wired
   The drawer, lifecycle stepper, key-value grid and timeline rules already
   existed in this file from the prototype port. What did not exist was
   anything that opened them: the docket cell was a <span>, there was no
   endpoint, and no JS. These are the few pieces the live version needs on
   top of what was already here.
   ========================================================================== */

/* the docket cell is now a real control */
a.sk-docket { cursor: pointer; text-decoration: none; }
a.sk-docket:hover { text-decoration: underline; }
a.sk-docket:focus-visible { outline: 2px solid var(--blue-500); outline-offset: 2px; border-radius: 3px; }

/* padding wrapper inside the Overview tab (the stepper sits edge to edge) */
.sk-drawer-pad { padding: 0 var(--s-5) var(--s-5); }

/* count badge on a tab */
.sk-tabn {
	display: inline-block; min-width: 17px; padding: 0 5px; margin-left: 5px;
	border-radius: 999px; background: var(--n-150); color: var(--text-soft);
	font-family: var(--font-mono); font-size: 10px; line-height: 16px; text-align: center;
}
.sk-tab.is-on .sk-tabn { background: var(--info-bg); color: var(--blue-700); }

/* four facts that answer "what is going on with this call" at a glance */
.sk-tiles {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 1px; margin: 0 0 var(--s-5);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--border); overflow: hidden;
}
.sk-tile { display: flex; flex-direction: column; gap: 3px; padding: var(--s-3) var(--s-4); background: var(--surface); }
.sk-tile .k { color: var(--text-soft); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.sk-tile .v { font-size: var(--fs-lg); font-weight: 600; color: var(--text-strong); line-height: 1.2; }
.sk-tile .v.sk-num, .sk-tile .v .sk-num { font-family: var(--font-mono); letter-spacing: -.02em; }
.sk-tile .s { color: var(--text-soft); font-size: var(--fs-xs); }

/* loading skeleton while ajxRecord.php replies */
.sk-drawer-loading { padding: var(--s-5); }
.sk-drawer-loading i {
	display: block; height: 13px; margin-bottom: 11px; border-radius: 5px;
	background: linear-gradient(90deg, var(--n-100), var(--n-150), var(--n-100));
	background-size: 200% 100%; animation: skShimmer 1.1s linear infinite;
}
.sk-drawer-loading i:nth-child(1) { width: 46%; }
.sk-drawer-loading i:nth-child(2) { width: 88%; }
.sk-drawer-loading i:nth-child(3) { width: 72%; }
.sk-drawer-loading i:nth-child(4) { width: 92%; }
.sk-drawer-loading i:nth-child(5) { width: 58%; }
@keyframes skShimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* the page behind the drawer must not scroll with it */
body.sk-drawer-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
	.sk-drawer { transition: none; }
	.sk-drawer-loading i { animation: none; }
}

/* ==========================================================================
   52. DASHBOARD — today's operations board
   Four work queues instead of a status tally. Each column is a decision the
   app can actually act on, lists the real dockets, and links to the screen
   that acts on them. Clicking a docket opens the record drawer in place via
   ?docket=, so triage never leaves the dashboard.
   ========================================================================== */
.sk-ops {
	margin-bottom: var(--s-4);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface); box-shadow: var(--sh-xs); overflow: hidden;
}
.sk-ops-head {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--border);
	font-size: var(--fs-sm);
}
.sk-ops-head b { font-size: var(--fs-md); font-weight: 600; color: var(--text-strong); }
.sk-ops-head .sk-spacer { flex: 1; }
.sk-ops-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--border); }
.sk-ops-col { display: flex; flex-direction: column; padding: var(--s-4); background: var(--surface); min-width: 0; }

.sk-ops-count { display: flex; align-items: baseline; gap: var(--s-2); margin-bottom: var(--s-3); }
.sk-ops-count b {
	font-family: var(--font-mono); font-size: 26px; font-weight: 600;
	line-height: 1; letter-spacing: -.03em;
}
.sk-ops-count span { color: var(--text-soft); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }
.sk-ops-col.is-red   .sk-ops-count b { color: var(--danger); }
.sk-ops-col.is-blue  .sk-ops-count b { color: var(--blue-600); }
.sk-ops-col.is-amber .sk-ops-count b { color: #b45309; }
.sk-ops-col.is-green .sk-ops-count b { color: var(--ok); }

.sk-ops-row {
	display: grid; grid-template-columns: 1fr auto; gap: 0 var(--s-2);
	padding: 7px 0; border-top: 1px solid var(--n-100);
	text-decoration: none; color: var(--text);
}
.sk-ops-row:first-of-type { border-top: 0; }
.sk-ops-row:hover { background: var(--blue-50); }
.sk-ops-row .d { font-family: var(--font-mono); font-size: var(--fs-sm); font-weight: 600; color: var(--blue-600); }
.sk-ops-row .a { font-family: var(--font-mono); font-size: var(--fs-xs); text-align: right; }
.sk-ops-row .c {
	grid-column: 1 / -1; color: var(--text-soft); font-size: var(--fs-xs);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sk-ops-empty { margin: 0; color: var(--text-soft); font-size: var(--fs-sm); }
.sk-ops-more { display: block; margin-top: auto; padding-top: var(--s-3); color: var(--blue-600); font-size: var(--fs-xs); font-weight: 600; text-decoration: none; }
.sk-ops-more:hover { text-decoration: underline; }

@media (max-width: 1100px) { .sk-ops-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .sk-ops-grid { grid-template-columns: 1fr; } }

/* ==========================================================================
   53. EMBEDDED MODE, ACCOUNT MENU, AND A COLLAPSED RAIL THAT WORKS
   ========================================================================== */

/* --- embedded (iframe / popup) --------------------------------------------
   callUpdation.php embeds servicehistory.php and servicespare.php in 250px
   iframes carrying hideTopLeft=1. top.php now skips the chrome entirely in
   that case; this undoes the layout offsets that assume it is there. The
   !important on td.leftside elsewhere in this file is exactly what broke
   the vendor's own .leftside{display:none}, so it is overridden here too. */
body.sk-embed .sk-topbar,
body.sk-embed .sk-flash,
body.sk-embed .sk-progress,
body.sk-embed td.leftside,
body.sk-embed .container td.leftside { display: none !important; }
body.sk-embed .container td.middle,
body.sk-embed td.middle {
	margin-left: 0 !important;
	padding: var(--s-3) !important;
	min-height: 0 !important;
	background: transparent !important;
}
body.sk-embed .curvebox { padding-top: 0 !important; }
body.sk-embed .sk-page-head { display: none; }
body.sk-embed .sk-tablewrap { box-shadow: none; }
body.sk-embed { background: var(--surface); }

/* --- topbar date + account ------------------------------------------------ */
.sk-today { color: var(--text-soft); font-size: var(--fs-sm); white-space: nowrap; }

.sk-account { margin-left: var(--s-1); }
.sk-user .t { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.15; min-width: 0; }
.sk-user .n { font-weight: 600; color: var(--text-strong); font-size: var(--fs-sm); }
.sk-user .r { color: var(--text-soft); font-size: 10.5px; }
.sk-user { height: 40px; padding: 0 var(--s-2); gap: var(--s-2); }
.sk-user .chev { width: 14px; height: 14px; flex: 0 0 14px; color: var(--n-400); transition: transform var(--t); }
.sk-user[aria-expanded="true"] { background: var(--n-100); }
.sk-user[aria-expanded="true"] .chev { transform: rotate(180deg); }

.sk-account .sk-menu { right: 0; left: auto; min-width: 236px; }
.sk-menu-head {
	display: flex; align-items: center; gap: var(--s-2);
	padding: var(--s-3); margin-bottom: var(--s-1);
	border-bottom: 1px solid var(--border);
}
.sk-menu-head .t { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.sk-menu-head .n { font-weight: 600; color: var(--text-strong); font-size: var(--fs-sm); }
.sk-menu-head .r { color: var(--text-soft); font-size: var(--fs-xs); }
.sk-menu a.is-danger { color: var(--danger); }
.sk-menu a.is-danger .ico { color: var(--danger); }
.sk-menu a.is-danger:hover { background: var(--danger-bg); color: var(--danger); }

/* --- collapsed rail -------------------------------------------------------
   The old rule kept every group EXPANDED in rail mode
   (.sk-nav-group.is-collapsed .sk-nav-items { grid-template-rows: 1fr }),
   so all the child links stayed in the DOM flow as label-less blank rows --
   which is the stack of empty blue slabs in the reported screenshot. In a
   64px rail only the section icons belong; the children appear in a flyout
   on hover, which is what a rail is for. */
body.is-rail .sk-nav-items {
	position: absolute; top: 0; left: 100%; z-index: 60;
	display: block; width: 208px; padding: var(--s-2);
	margin-left: 0;   /* touching the rail on purpose -- a gap here is exactly
	                     what made the flyout hard to reach: the mouse loses
	                     :hover crossing it before landing on the panel */
	border: 1px solid rgba(255,255,255,.09); border-radius: var(--r-lg);
	background: var(--ink-800, #0f1e35);
	box-shadow: var(--sh-lg);
	opacity: 0; visibility: hidden; transform: translateX(-4px);
	transition: opacity var(--t), transform var(--t), visibility var(--t);
}
body.is-rail .sk-nav-group { position: relative; }
body.is-rail .sk-nav-group:hover > .sk-nav-items,
body.is-rail .sk-nav-group:focus-within > .sk-nav-items {
	opacity: 1; visibility: visible; transform: none;
}
body.is-rail .sk-nav-group:hover > .sk-nav-title { background: rgba(255,255,255,.09); color: #fff; }
/* inside the flyout the labels come back */
body.is-rail .sk-nav-items a span:not(.sk-nav-badge) { display: inline !important; }
body.is-rail .sk-nav-items a,
body.is-rail .sk-nav-items a.linkCss {
	justify-content: flex-start !important;
	padding: 8px var(--s-3) !important;
	border-radius: var(--r);
}
body.is-rail .sk-nav-items a.linkCss.is-active::before { display: block; }
/* the rail itself must not scroll -- 6 icons always fit */
body.is-rail .sk-nav { overflow: visible; }
body.is-rail .sk-side { overflow: visible; }
/* [FIX] .sk-nav-title keeps width:100% from its base rule (line ~403), sized
   for the EXPANDED sidebar where it carries no horizontal margin. Rail mode
   adds an 8px margin on both sides for the rounded hover chip -- on top of
   an unchanged width:100%, that pushes the box 8px past its container's
   right edge while the left margin is honoured, so its centered content
   reads as shoved left with a dead gap on the right. Width is corrected to
   leave room for both margins instead of overflowing past them. */
body.is-rail .sk-nav-title { border-radius: var(--r); margin: 0 var(--s-2) var(--s-2); width: calc(100% - (var(--s-2) * 2)); }
body.is-rail .sk-nav-title .ico { flex: 0 0 19px; width: 19px; height: 19px; opacity: .95; }

/* a rail icon that is the current section reads as selected */
body.is-rail .sk-nav-group.is-current > .sk-nav-title {
	background: linear-gradient(90deg, var(--blue-600), var(--blue-500));
	color: #fff;
}

/* leftover 2011 accent inside the embedded panels: servicehistory.php:149 and
   servicespare.php carry an inline style="background:#FFEFE8" on the form
   wrapper. Neutralised only in embedded mode so the panels sit flat inside
   callUpdation.php rather than looking like an error state. */
body.sk-embed [style*="FFEFE8"],
body.sk-embed [style*="ffefe8"] { background: var(--surface-sub) !important; border-radius: var(--r-lg); padding: var(--s-3) !important; }
body.sk-embed table.container { border: 0 !important; }
body.sk-embed .formsection, body.sk-embed fieldset.cFielSets { box-shadow: none; border: 0; margin: 0; }

/* --- command palette: real results, grouped ------------------------------- */
.sk-cmdk-grp {
	padding: var(--s-3) var(--s-4) 5px;
	color: var(--text-soft); font-size: var(--fs-xs); font-weight: 600;
	letter-spacing: .06em; text-transform: uppercase;
}
.sk-cmdk-item { display: flex; align-items: center; gap: var(--s-2); }
.sk-cmdk-item .l { font-weight: 500; color: var(--text-strong); white-space: nowrap; }
.sk-cmdk-item .m {
	color: var(--text-soft); font-size: var(--fs-sm);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1;
}
.sk-cmdk-item .grp { margin-left: auto; }
.sk-cmdk-kind { flex: 0 0 7px; width: 7px; height: 7px; border-radius: 50%; background: var(--n-300); }
.sk-cmdk-kind--docket   { background: var(--blue-500); }
.sk-cmdk-kind--customer { background: var(--ok); }
.sk-cmdk-kind--centre   { background: #d97706; }
.sk-cmdk-kind--staff    { background: #7c3aed; }
.sk-cmdk-kind--page     { background: var(--n-300); }
/* a docket is monospaced wherever it appears */
.sk-cmdk-kind--docket + .l { font-family: var(--font-mono); }

/* --- rail: two faults found by collapsing it and trying to work ----------- */

/* 1. The expand button disappeared. It was absolutely positioned against an
      unpositioned .sk-side-head, so in rail mode it left the visible area and
      there was no way back to the full menu except clearing localStorage. */
body.is-rail .sk-side-head {
	flex-direction: column;
	gap: 6px;
	height: auto;
	padding: var(--s-3) 0 var(--s-2);
}
body.is-rail .sk-railtoggle {
	position: static;
	transform: none;
	margin: 0;
}

/* 2. The Dashboard link vanished. Its group carries no title (see
      includes/nav.php -- the first group is title=>null), so it has no
      .sk-nav-title icon to act as a rail trigger, and turning .sk-nav-items
      into a hover flyout left it with nothing to hover. A group with no
      title keeps its items inline as ordinary rail icons instead. */
body.is-rail .sk-nav-group:not(:has(> .sk-nav-title)) > .sk-nav-items {
	position: static; width: auto; margin: 0; padding: 0;
	border: 0; background: none; box-shadow: none;
	opacity: 1; visibility: visible; transform: none;
}
body.is-rail .sk-nav-group:not(:has(> .sk-nav-title)) > .sk-nav-items a span:not(.sk-nav-badge):not(.sk-rail-cap) { display: none !important; }
body.is-rail .sk-nav-group:not(:has(> .sk-nav-title)) > .sk-nav-items a,
body.is-rail .sk-nav-group:not(:has(> .sk-nav-title)) > .sk-nav-items a.linkCss {
	justify-content: center !important; padding: 9px 0 !important;
}

/* the flyout needs a little breathing room from the rail edge and must not be
   clipped by the sidebar's own overflow */
body.is-rail .sk-side, body.is-rail .sk-nav { overflow: visible !important; }

/* the flyout is drawn but was clipped: td.leftside is the 64px scroll box in
   rail mode. Six icons always fit vertically, so it can overflow freely. */
body.is-rail .container td.leftside,
body.is-rail td.leftside { overflow: visible !important; }

/* ==========================================================================
   54. DATA TABLES — sort, page, filter, row menu
   ========================================================================== */

/* --- sortable header ------------------------------------------------------ */
table.listTable tr.borderTitle a.sk-sort {
	display: inline-flex; align-items: center; gap: 5px;
	color: inherit; text-decoration: none; white-space: nowrap;
}
table.listTable tr.borderTitle a.sk-sort:hover { color: var(--blue-600); }
.sk-sort-i { width: 12px; height: 12px; flex: 0 0 12px; opacity: 0; transition: opacity var(--t), transform var(--t); }
table.listTable tr.borderTitle a.sk-sort:hover .sk-sort-i { opacity: .5; }
a.sk-sort.is-on { color: var(--blue-600); }
a.sk-sort.is-on .sk-sort-i { opacity: 1; }
/* the arrow points the way the data is going */
a.sk-sort.is-on.is-asc  .sk-sort-i { transform: scaleY(-1); }

/* --- pager ---------------------------------------------------------------- */
.sk-pager {
	display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
	margin-top: var(--s-3); padding: var(--s-3) var(--s-4);
	border: 1px solid var(--border); border-radius: var(--r-lg);
	background: var(--surface);
}
.sk-pager-info { color: var(--text-soft); font-size: var(--fs-sm); }
.sk-pager-info b { color: var(--text-strong); font-family: var(--font-mono); font-weight: 500; }
.sk-pager-nums { display: flex; align-items: center; gap: 4px; margin-left: auto; flex-wrap: wrap; }
.sk-pager-nums a,
.sk-pager-nums .is-current {
	display: grid; place-items: center;
	min-width: 32px; height: 32px; padding: 0 9px;
	border: 1px solid var(--border); border-radius: var(--r);
	background: var(--surface); color: var(--text);
	font-size: var(--fs-sm); text-decoration: none;
	transition: background var(--t), border-color var(--t), color var(--t);
}
.sk-pager-nums a:hover { background: var(--blue-50); border-color: var(--blue-400); color: var(--blue-700); text-decoration: none; }
.sk-pager-nums .is-current {
	border-color: transparent;
	background: linear-gradient(180deg, var(--blue-500), var(--blue-600));
	color: #fff; font-weight: 600;
}

/* --- filter box in the toolbar -------------------------------------------- */
.sk-rowfilter {
	position: relative; display: inline-flex; align-items: center;
	height: 34px; padding: 0 var(--s-2) 0 30px;
	border: 1px solid var(--border-strong); border-radius: var(--r);
	background: var(--surface); box-shadow: var(--sh-xs);
	transition: border-color var(--t), box-shadow var(--t);
}
.sk-rowfilter.is-on, .sk-rowfilter:focus-within { border-color: var(--blue-500); box-shadow: var(--ring); }
.sk-rowfilter .ico { position: absolute; left: 9px; width: 14px; height: 14px; color: var(--n-400); }
.sk-rowfilter input {
	height: 30px !important; width: 190px;
	border: 0 !important; background: none !important; box-shadow: none !important;
	padding: 0 !important; font-size: var(--fs-sm) !important;
}
.sk-rowfilter input:focus { box-shadow: none !important; border: 0 !important; }
.sk-rowfilter-n { color: var(--text-soft); font-size: var(--fs-xs); font-family: var(--font-mono); padding-left: 6px; }

/* --- row action menu ------------------------------------------------------ */
.sk-rowmenu-wrap { display: inline-flex; }
.sk-rowmenu-btn { width: 30px; height: 30px; }
.sk-rowmenu {
	right: 0; left: auto; min-width: 178px;
	max-height: none;
}
.sk-rowmenu.is-up { top: auto; bottom: calc(100% + 6px); }
/* the legacy controls become plain menu rows; their handlers are untouched */
.sk-rowmenu a, .sk-rowmenu button, .sk-rowmenu input {
	display: flex !important; align-items: center; gap: var(--s-2);
	width: 100%; height: auto !important; min-height: 34px;
	padding: 7px var(--s-3) !important; margin: 0 !important;
	border: 0 !important; border-radius: var(--r);
	background: none !important; box-shadow: none !important;
	color: var(--text) !important;
	font-size: var(--fs-sm) !important; font-weight: 500 !important;
	text-align: left; text-decoration: none; cursor: pointer;
	white-space: nowrap;
}
.sk-rowmenu a:hover, .sk-rowmenu button:hover, .sk-rowmenu input:hover {
	background: var(--blue-50) !important; color: var(--blue-700) !important;
}
.sk-rowmenu .is-danger { color: var(--danger) !important; }
.sk-rowmenu .is-danger:hover { background: var(--danger-bg) !important; color: var(--danger) !important; }

/* the frozen column only has to hold one button now */
table.listTable td.actionLink {
	min-width: 56px !important;
	text-align: center;
}

/* ==========================================================================
   55. RAIL CAPTIONS — icon + tiny label, per direct feedback
   A bare column of icons with no text is faster to scan wrong: nothing
   distinguishes Alerts from Spare Master except memorising silhouettes.
   .sk-rail-cap duplicates the section's own label (hidden everywhere except
   the 64px collapsed rail) so the icon always carries its name under it.
   ========================================================================== */
.sk-rail-cap { display: none; }
body.is-rail .sk-nav-title,
body.is-rail .sk-nav-group:not(:has(> .sk-nav-title)) > .sk-nav-items a.linkCss {
	flex-direction: column;
	gap: 3px;
	height: auto;
	padding-top: 8px !important;
	padding-bottom: 7px !important;
}
/* !important: .sk-rail-cap is itself a <span>, and an existing broader rule
   ("body.is-rail .sk-nav-title span { display:none }") hides every span
   inside the title button when collapsed -- including this one, since it
   has one more type-selector and so a higher plain specificity. */
body.is-rail .sk-rail-cap {
	display: block !important;
	max-width: 100%;
	/* wrap onto a second line instead of ellipsis-truncating mid-word --
	   "Calls Man..." / "Spare Mas..." read as broken, not abbreviated */
	overflow: visible; white-space: normal; word-break: normal;
	color: inherit; opacity: .85;
	font-size: 9px; font-weight: 600; letter-spacing: .01em; line-height: 1.15;
	text-align: center; text-transform: none;
	/* reserve room for 2 lines always, whether this label wraps or not --
	   otherwise a 1-line caption (Dashboard, Alerts) makes its item ~14px
	   shorter than a 2-line one (Calls Manager, Spare Master), so the icons
	   fall out of a regular rhythm down the rail instead of lining up */
	min-height: calc(1.15em * 2);
}
/* the flyout already shows the full label inline -- no caption duplicate there.
   Scoped to groups WITH a title (the ones that become a flyout); the
   title-less Dashboard group's .sk-nav-items stays normal rail flow and
   keeps its caption. */
body.is-rail .sk-nav-group:has(> .sk-nav-title) .sk-nav-items .sk-rail-cap { display: none; }

/* ==========================================================================
   56. BULK ACTION BAR
   Was a bare "N selected" text wedged into the toolbar and a bulk action
   button that stayed visible whether or not anything was selected. Now a
   real contextual bar that only appears once a row is checked.
   ========================================================================== */
.sk-bulkbar {
	display: none;
	align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4);
	border: 1px solid var(--info-br); border-top: 0;
	background: var(--info-bg);
	font-size: var(--fs-sm);
}
.sk-bulkbar.is-on { display: flex; animation: fade .15s ease both; }
.sk-bulkbar-n { color: var(--blue-700); font-weight: 500; }
.sk-bulkbar-n b { font-family: var(--font-mono); }

/* the old inline "N selected" text in the toolbar is now redundant --
   the bulk bar shows the same count more prominently right below it */
#skSelCount { display: none !important; }

/* ==========================================================================
   57. FORM SECTION DIVIDERS
   Call Registration (and, going forward, other long forms) is one flat
   table of 20+ fields with no visual grouping at all -- Customer, product,
   assignment and billing information all read as one undifferentiated
   list. Section marker rows split it into named groups, using the same
   icon-tile + label language as the record drawer's own cards, so editing
   a call and VIEWING one (the drawer) now read as the same design rather
   than two different eras of the app.
   ========================================================================== */
table.formClass tr.sk-form-sec > td {
	padding: 0 !important;
	border: 0 !important;
	/* override the label-cell heuristic just above -- a section marker's
	   td has no input/select either, so it would otherwise be treated as a
	   narrow, nowrap label cell instead of a full-width divider */
	width: auto !important;
	white-space: normal !important;
	color: inherit;
	font-size: inherit;
	font-weight: inherit;
}
.sk-form-sec-head {
	display: flex; align-items: center; gap: var(--s-2);
	margin: var(--s-5) 0 var(--s-3);
	padding-top: var(--s-4);
	border-top: 1px solid var(--border);
	color: var(--text-soft);
	font-size: var(--fs-xs); font-weight: 600;
	letter-spacing: .06em; text-transform: uppercase;
}
table.formClass tr.sk-form-sec:first-child .sk-form-sec-head {
	margin-top: 0; padding-top: 0; border-top: 0;
}
.sk-form-sec-head .ico { width: 14px; height: 14px; flex: 0 0 14px; color: var(--blue-500); }

/* required-field marker: a plain inline red asterisk read as an afterthought */
table.formClass span[style*="FF0000"] {
	color: var(--danger) !important;
	font-weight: 700;
	margin-left: 2px;
}

/* callUpdation.php: the "jump to another docket" box above the form, and
   the current docket number readout once a record is loaded */
.sk-searchdocket { margin-bottom: var(--s-4); }
.sk-searchdocket input.textbox { width: 160px; margin: 0 var(--s-2); }
.sk-docketno { margin-bottom: var(--s-4); font-size: var(--fs-md); }

/* ==========================================================================
   58. MOBILE ROW CARDS
   --------------------------------------------------------------------------
   Same list pages, same markup, same data -- wireMobileCards() (js/skyled.js)
   reads each table's own header row once and classifies each row's cells:
   the first real column is the row's identity (title), a Status-labelled
   column becomes a chip, the next column is one line of context, a
   phone/mobile-labelled column becomes tap-to-call, and everything else is
   real detail tucked behind a "N more details" toggle instead of dumped as
   a wall of label/value lines. This is what turns "the data, shrunk" into
   something that reads like an actual app's list. Nothing above this width
   changes -- the classification classes are inert there.
   ========================================================================== */
@media (max-width: 680px) {
	.sk-tablewrap { overflow-x: visible; }
	table.listTable, table.listTable > tbody { display: block; width: 100%; }
	table.listTable tr.borderTitle { display: none; }
	table.listTable > tbody > tr, table.listTable > tr:not(.borderTitle) {
		display: grid; position: relative;
		grid-template-columns: 1fr auto;
		grid-template-areas: "title chip" "sub sub";
		column-gap: var(--s-2); row-gap: 2px;
		margin-bottom: var(--s-3); padding: var(--s-3) var(--s-3) var(--s-2);
		border: 1px solid var(--border); border-radius: var(--r-lg);
		background: var(--surface); box-shadow: var(--sh-xs);
		overflow: hidden;
	}
	table.listTable > tbody > tr:has(> td.sk-td-check),
	table.listTable > tbody > tr:has(> td.actionLink),
	table.listTable > tr:not(.borderTitle):has(> td.sk-td-check),
	table.listTable > tr:not(.borderTitle):has(> td.actionLink) { padding-top: 36px; }

	/* the whole card opens the record now (wireDockets, skyled.js) when it
	   has one -- give it the same tappable feel as any other card-shaped
	   control instead of looking identical to a row with nothing to tap. */
	table.listTable > tbody > tr:has(.sk-docket),
	table.listTable > tr:not(.borderTitle):has(.sk-docket) { cursor: pointer; }
	table.listTable > tbody > tr:has(.sk-docket):active,
	table.listTable > tr:not(.borderTitle):has(.sk-docket):active { background: var(--surface-sub); }

	/* the two lines every card always shows: a title and one line of
	   context under it -- not a label, just the fact itself */
	table.listTable td.sk-td-primary {
		grid-area: title; align-self: center;
		font-size: 16px; font-weight: 600; color: var(--text-strong); line-height: 1.3;
		overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	}
	table.listTable td.sk-td-primary .sk-docket { font-size: inherit; }
	table.listTable td.sk-td-secondary {
		grid-area: sub; align-self: start;
		font-size: var(--fs-sm); color: var(--text-soft); line-height: 1.35;
		overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	}
	/* [FIX] the Status column's content is already a real pill
	   (.sk-pill/.sk-pill--*, built earlier this session -- colour-coded,
	   the active ones pulse) -- this only positions it. Giving the <td>
	   ITSELF a second chip background/radius on top of that produced a
	   pill inside a pill, two mismatched rounded edges overlapping. */
	table.listTable td.sk-td-status {
		grid-area: chip; align-self: center; justify-self: end;
		margin-right: 26px; max-width: 100%; overflow: hidden;
		min-width: 0;
	}
	/* [FIX] a long status ("Verified and Accepted by ASP") next to a
	   docket number has no room to spare on a phone -- overflow:hidden
	   above used to just hard-clip the pill mid-word with no ellipsis,
	   a flat cut edge with no rounded corner where it happened to end.
	   wireChipTruncate() (skyled.js) wraps the pill's own text in .txt
	   once so THIS can ellipsis it while the status dot (the pill's own
	   ::before, untouched) stays fully visible. min-width:0 is required
	   on both the flex child and its ancestor chain or a nowrap span
	   simply refuses to shrink below its natural text width at all. */
	table.listTable td.sk-td-status .sk-pill { max-width: 100%; min-width: 0; }
	table.listTable td.sk-td-status .sk-pill .txt {
		overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
	}

	/* tap-to-call: a real affordance a table of text can never give you */
	a.sk-td-tel {
		display: inline-flex; align-items: center; gap: 5px;
		color: var(--blue-600); font-weight: 500; text-decoration: none;
	}
	a.sk-td-tel::before {
		content: ""; width: 12px; height: 12px; flex: 0 0 12px;
		background: currentColor;
		-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.9v3a2 2 0 0 1-2.2 2A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .3 1.8.6 2.7a2 2 0 0 1-.5 2.1L8.1 9.6a16 16 0 0 0 6 6l1.1-1.1a2 2 0 0 1 2.1-.5c.9.3 1.8.5 2.7.6a2 2 0 0 1 1.7 2z'/%3E%3C/svg%3E") center / contain no-repeat;
		mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.9v3a2 2 0 0 1-2.2 2A19.8 19.8 0 0 1 2.1 4.2 2 2 0 0 1 4.1 2h3a2 2 0 0 1 2 1.7c.1 1 .3 1.8.6 2.7a2 2 0 0 1-.5 2.1L8.1 9.6a16 16 0 0 0 6 6l1.1-1.1a2 2 0 0 1 2.1-.5c.9.3 1.8.5 2.7.6a2 2 0 0 1 1.7 2z'/%3E%3C/svg%3E") center / contain no-repeat;
	}

	/* [FIX] used to hide behind a "N more details" tap -- one extra
	   interaction per row before you could see a field you actually
	   needed, on a list people scan repeatedly through a shift. Shown
	   directly, no toggle: less visual weight than the title/status/
	   context lines above (smaller, a hairline divider before the group),
	   but never an extra click away. */
	/* [FIX] right-aligned label:value rows read fine for a short value
	   (a phone number, a PIN) but turn unreadable the moment the value is
	   a real sentence -- Customer List's Address field wraps to 2-3 lines
	   of right-ragged text with no fixed left edge to track down. flex-wrap
	   keeps a short value inline after its label (compact, same as before)
	   and only drops a long one to its own left-aligned line underneath --
	   one rule for both cases, no length-sniffing in JS. */
	/* [FIX] a hairline divider before every field read fine when it meant
	   "new section starts here" against a wall of a dozen rows -- with
	   the docket cards now down to two or three of these (stage, a
	   phone), it just added visual noise between lines that already read
	   as a group. Tighter padding for the same reason: fewer, shorter
	   rows do not need as much breathing room to stay legible. */
	table.listTable td.sk-td-more {
		display: flex; flex-wrap: wrap;
		grid-column: 1 / -1;
		align-items: baseline; gap: 3px var(--s-2);
		padding: 4px 0;
		text-align: left; white-space: normal; word-break: break-word;
	}
	/* [FIX] ":first-of-type" only counts by TAG NAME ("td"), not class --
	   the checkbox/docket/status/date cells before this one are also
	   <td>s, so ".sk-td-more:first-of-type" never matched anything and
	   the divider never rendered at all. "~" (any .sk-td-more preceded by
	   another one) correctly targets every one AFTER the first instead. */
	table.listTable td.sk-td-more { padding-top: 8px; border-top: 1px solid var(--border); }
	table.listTable td.sk-td-more ~ td.sk-td-more { padding-top: 4px; border-top: 0; }
	table.listTable td.sk-td-more[data-label]::before {
		content: attr(data-label) ":";
		flex: 0 0 auto;
		font-size: var(--fs-xs); font-weight: 600; letter-spacing: .02em; text-transform: uppercase;
		color: var(--text-soft);
	}

	/* row-select checkbox: a small pin top-left of the card, not a labelled row */
	table.listTable td.sk-td-check {
		position: absolute !important; top: 10px; left: 10px; z-index: 2;
		border-bottom: 0 !important; padding: 0 !important; background: none;
		display: block;
	}

	/* row actions: the same ⋮ menu as desktop, pinned top-right of the card */
	table.listTable td.actionLink {
		position: absolute !important; top: 6px; right: 6px; z-index: 2;
		border-bottom: 0 !important; padding: 0 !important; background: none;
		min-width: 0 !important; display: block;
	}

	/* [FIX] a cell with no value (a blank column for this particular row)
	   never gets classified by wireMobileCards() -- it's not the title,
	   not the one line of context, not worth a "N more details" slot. Left
	   unstyled it still became a grid item with no named area, and the row
	   silently gained an extra empty ~30px track per blank column -- one
	   card had six of these stacked, a dead gap before "17 more details".
	   Never rendered at all now, exactly like the check/action cells that
	   already get their own explicit treatment above. */
	table.listTable > tbody > tr > td:not(.sk-td-primary):not(.sk-td-secondary):not(.sk-td-status):not(.sk-td-more):not(.sk-td-check):not(.actionLink),
	table.listTable > tr:not(.borderTitle) > td:not(.sk-td-primary):not(.sk-td-secondary):not(.sk-td-status):not(.sk-td-more):not(.sk-td-check):not(.actionLink) {
		display: none;
	}

	/* --- search card: a real single column, not a wide row wrapping mid-sentence.
	   The old ".flex-wrap:wrap" (line ~1996) just let each piece wrap wherever
	   it happened to run out of room -- the toggle button, the Search button
	   and "Per page" all landing at different widths, different alignments,
	   on whatever row they fell on. Every piece here is full width instead,
	   in the order that actually makes sense to use one-handed: search field,
	   then the two actions together, then the one setting nobody needs first. */
	.sk-searchbar {
		flex-direction: column; align-items: stretch; gap: var(--s-2);
		padding: var(--s-3) !important;
	}
	.sk-searchbar-spacer { display: none; }
	/* [FIX] .find carries "flex: 1 1 340px" for the desktop ROW layout,
	   where flex-basis sets WIDTH. In this column layout flex-basis sets
	   HEIGHT instead -- the same bug class found earlier this session in
	   the advanced-filter fields -- so .find rendered as a 340px-TALL box
	   with everything else pushed down off screen. flex-basis reset to
	   auto so height comes from its own content again. */
	.sk-searchbar .find { flex: 0 1 auto; width: 100%; max-width: none; height: auto; }
	.sk-searchbar .find input { height: 46px !important; font-size: var(--fs-md) !important; }
	.sk-searchbar .sk-filtertoggle {
		width: 100%; justify-content: space-between; height: 44px !important; font-size: var(--fs-sm) !important;
	}
	.sk-searchbar .sk-btn--primary { width: 100%; justify-content: center; height: 46px !important; }
	.sk-searchbar .sk-pp {
		width: 100%; justify-content: space-between;
		padding-top: var(--s-2); border-top: 1px solid var(--border);
	}
	.sk-searchbar .sk-pp select { height: 38px !important; }
	.sk-adv-inner .sk-filters { grid-template-columns: 1fr; }
	.sk-adv-inner .sk-actions { flex-direction: column; }
	.sk-adv-inner .sk-actions .sk-btn { width: 100%; justify-content: center; }

	/* --- table toolbar: ONE clear primary action, not five equal-weight
	   buttons. Row density (Cosy/Compact) is a table concept and has
	   nothing to switch between once rows are cards, so it's gone here
	   rather than taking up a whole row for a setting with nothing to do.
	   Export/Refresh are secondary -- smaller, side by side, not full-width
	   blocks competing with "Add record" for the thumb's attention. */
	.sk-tabletools {
		display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2);
		padding: var(--s-3);
	}
	.sk-tabletools > .sk-count { grid-column: 1 / -1; text-align: center; font-size: var(--fs-xs); color: var(--text-soft); }
	.sk-tabletools .sk-btn--primary { grid-column: 1 / -1; justify-content: center; height: 46px; }
	.sk-tabletools > a.sk-btn:not(.sk-btn--primary),
	.sk-tabletools > button.sk-btn:not(.sk-btn--primary) {
		justify-content: center; height: 40px;
		background: var(--surface-sub); border-color: var(--border); color: var(--text-soft); font-size: var(--fs-xs);
	}
	.sk-tabletools > .sk-seg { display: none; }
	.sk-rowfilter { grid-column: 1 / -1; width: 100%; }
	.sk-rowfilter input { width: 100% !important; }
}

/* ==========================================================================
   58. CALL UPDATION -- SCOPED FORM REDESIGN (callUpdation.php only)
   table.formClass / fieldset.cFielSets are shared by every add/edit form in
   the app (dealerEdit.php, productEdit.php, TCRMasterAddEdit.php, ...), so
   nothing below touches those bare selectors. .sk-callform is a class added
   only to this one page's <fieldset> -- nothing here can regress another
   form page.

   What this fixes: block 37 zeroed fieldset.cFielSets's own padding to turn
   the legend into a card header, which is right for short forms but left
   this ~30-field form's cells flush against the card edge with only 7px of
   vertical rhythm and no horizontal gap between one row's field and the
   next label -- read as "left adjusted, no padding" on a form this long.
   Section headers (already added for Call Registration, block 57) also
   read as a thin caption; stretched across 6 sections and ~30 fields they
   need to look like real breaks, not footnotes -- so they're heavier here
   and double as a collapse toggle (JS in callUpdation.php) so a section
   nobody needs right now (Documents, Repair & Status) can be closed
   instead of just scrolled past. */
fieldset.cFielSets.sk-callform > *:not(legend) {
	padding-left: var(--s-6);
	padding-right: var(--s-6);
}
fieldset.cFielSets.sk-callform table.formClass > tbody > tr > td {
	padding: 11px 0;
}
fieldset.cFielSets.sk-callform table.formClass > tbody > tr > td:not(:has(input, select, textarea)) {
	padding-right: var(--s-5);
}
fieldset.cFielSets.sk-callform table.formClass > tbody > tr > td:has(input, select, textarea) {
	padding-right: var(--s-6);
}

.sk-callform .sk-form-sec-head {
	display: flex; align-items: center; gap: var(--s-2);
	margin: var(--s-6) 0 var(--s-4);
	padding: var(--s-3) var(--s-4);
	background: var(--surface-sub);
	border: 1px solid var(--border);
	border-left: 3px solid var(--blue-500);
	border-radius: var(--r-sm);
	font-size: var(--fs-sm);
	cursor: pointer;
	user-select: none;
}
.sk-callform .sk-form-sec-head span { flex: 1 1 auto; }
.sk-callform table.formClass tr.sk-form-sec:first-child .sk-form-sec-head {
	margin-top: 0;
}
.sk-callform .sk-form-sec-head::after {
	content: '';
	width: 7px; height: 7px; flex: 0 0 7px;
	border-right: 2px solid var(--text-soft);
	border-bottom: 2px solid var(--text-soft);
	transform: rotate(45deg);
	transition: transform .15s;
}
.sk-callform tr.sk-form-sec.sk-sec-collapsed .sk-form-sec-head::after,
.sk-callform .sk-form-sec-head.sk-sec-collapsed::after {
	transform: rotate(-45deg);
}
.sk-callform tr.sk-sec-hide { display: none; }

/* WhatsApp buttons -- brand green + the real glyph, not the generic outline
   speech-bubble every other .sk-btn uses. New class, not an override of an
   existing one: safe anywhere, this is the only page using it today. */
.sk-btn--whatsapp {
	background: #25D366;
	border-color: #1ebe5a;
	color: #fff;
	box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 2px 8px rgba(37,211,102,.35);
}
.sk-btn--whatsapp:hover {
	background: #1ebe5a;
	border-color: #189a4a;
	color: #fff;
}
.sk-btn--whatsapp .ico { color: #fff; }

@media (max-width: 760px) {
	fieldset.cFielSets.sk-callform > *:not(legend) {
		padding-left: var(--s-4);
		padding-right: var(--s-4);
	}
}
.sk-docketno span { color: var(--danger); font-size: var(--fs-2xl); font-weight: 700; }

/* ==========================================================================
   59. EMPLOYEE PERMISSIONS (admin.php / adminEdit.php)
   admin.php used to dump all 18 permission checkboxes as raw inputs with
   <br/> between them, and adminEdit.php the same, both under a fieldset
   class of "cFielSet" -- missing the 's' every other form page uses, so
   neither ever got the card treatment block 37 gives fieldset.cFielSets.
   Fixed the typo and gave the checklist real structure: grouped under the
   same section-head language as callUpdation.php's redesign, laid out in
   a grid instead of one long vertical list.
   ========================================================================== */
.sk-permgrid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: var(--s-2) var(--s-4);
	margin-bottom: var(--s-5);
}
.sk-permitem {
	display: flex; align-items: center; gap: var(--s-2);
	font-size: var(--fs-sm); color: var(--text);
	cursor: pointer;
}
.sk-permitem .sk-check { flex: 0 0 auto; }

/* read-only permission summary for the admin.php list -- a wall of 18
   checkboxes crammed into one narrow table cell was unreadable at a
   glance and wasn't even editable there (that's what the Edit popup is
   for), so this shows only what's actually granted, as chips. */
.sk-permsummary { display: flex; flex-wrap: wrap; gap: 4px; max-width: 280px; }
.sk-permsummary .sk-chip { font-size: 10.5px; padding: 2px 8px; animation: none; }
.sk-permsummary-empty { color: var(--text-soft); font-size: var(--fs-xs); font-style: italic; }
