/* Shared responsive layer - one place for the rules that must hold on every
   page of MyDesk, whichever of this app's five stylesheets that page
   happens to link. Must stay first: @import is only honoured before any
   other rule. */
@import url("/System/tl-responsive.css");

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');

/* ===== Theme changer ===== =============================================
 * CSS custom properties, overridden per theme via a `theme-*` class on
 * <body> (set by Global.js's yyapplyMyDeskTheme() from the MyDeskTheme
 * cookie - see that file - since there's no single shared <head> include
 * every page goes through to set a data-theme attribute server-side
 * before first paint). :root's own values ARE the "Classic Blue/White"
 * theme (the app's existing, unchanged default look) - Classic needs no
 * override block of its own, only the other three do.
 *
 * Deliberately a small, high-impact variable set (page background, card/
 * fieldset surface, text, borders, the button gradient, links, list
 * headers) covering the elements that dominate what a page actually
 * looks like - not every single colour in this stylesheet. A future pass
 * extending more rules to reference these same variables will pick up
 * theming for free.
 */
:root
{
	--tl-bg: #eef3f4;
	--tl-surface: #ffffff;
	--tl-surface-border: #d7e2e5;
	--tl-text: #08121a;
	--tl-text-muted: #5a6d7a;
	--tl-heading: #18353d;
	--tl-accent: #0c5560;
	--tl-accent-2: #00a7ad;
	--tl-btn-grad-top: #0db2b8;
	--tl-btn-grad-bottom: #0a8b92;
	--tl-btn-grad-top-hover: #10c3ca;
	--tl-btn-grad-bottom-hover: #0b99a0;
	--tl-btn-text: #ffffff;
	--tl-link: #0b6670;
	--tl-link-hover: #084d55;
	--tl-listheader-grad-top: #f6fafb;
	--tl-listheader-grad-bottom: #eaf2f4;
	--tl-input-border: #b9ccd1;
	--tl-input-bg: #ffffff;
	--tl-card-shadow: rgba(8, 18, 26, .08);
	/* Recessed surface, for legacy panels that hardcode bgcolor="#dddddd".
	   Classic keeps the exact legacy grey, so mapping those panels to this
	   token changes nothing at all on the default theme - it only gives the
	   other three somewhere sensible to send them. */
	--tl-bg-recessed: #dddddd;
}

/* Navy/Gold - from the 2026 company profile's cover/section design
   (dark navy field, gold headline accent, existing teal kept as the
   interactive/accent colour so links and focus states stay recognisably
   "Techlight" rather than becoming a wholesale new palette). */
body.theme-navy-gold
{
	--tl-bg: #0a1e26;
	--tl-surface: #0f2932;
	--tl-surface-border: #1c3f4a;
	--tl-text: #e8eef0;
	--tl-text-muted: #9fb4bb;
	--tl-heading: #f4d998;
	--tl-accent: #c9a355;
	--tl-accent-2: #00a7ad;
	--tl-btn-grad-top: #d9bb73;
	--tl-btn-grad-bottom: #c9a355;
	--tl-btn-grad-top-hover: #e6c988;
	--tl-btn-grad-bottom-hover: #d4af63;
	--tl-btn-text: #0a1e26;
	--tl-link: #4fd6dc;
	--tl-link-hover: #7ee6ea;
	--tl-listheader-grad-top: #16323c;
	--tl-listheader-grad-bottom: #0f2932;
	--tl-input-border: #2c4a54;
	--tl-input-bg: #0a1e26;
	--tl-card-shadow: rgba(0, 0, 0, .35);
	--tl-bg-recessed: #081a21;
}

/* Dark - the company profile's full-bleed dark variant, same navy/gold
   family as above but darker still and without the gold heading tint, so
   it reads as a genuine low-light mode rather than Navy/Gold's branded
   cover-page look. */
body.theme-dark
{
	--tl-bg: #0b1418;
	--tl-surface: #131e23;
	--tl-surface-border: #223038;
	--tl-text: #dbe4e7;
	--tl-text-muted: #8a9ba1;
	--tl-heading: #eef3f4;
	--tl-accent: #00a7ad;
	--tl-accent-2: #0db2b8;
	--tl-btn-grad-top: #0db2b8;
	--tl-btn-grad-bottom: #0a8b92;
	--tl-btn-grad-top-hover: #10c3ca;
	--tl-btn-grad-bottom-hover: #0b99a0;
	--tl-btn-text: #ffffff;
	--tl-link: #4fd6dc;
	--tl-link-hover: #7ee6ea;
	--tl-listheader-grad-top: #182228;
	--tl-listheader-grad-bottom: #131e23;
	--tl-input-border: #2a3a41;
	--tl-input-bg: #0b1418;
	--tl-card-shadow: rgba(0, 0, 0, .4);
	--tl-bg-recessed: #090f12;
}

/* Light - an airier variant of Classic: white/near-white throughout,
   softer borders, same teal accent - for anyone who finds Classic's
   pale-teal page background too much colour. */
body.theme-light
{
	--tl-bg: #fbfcfc;
	--tl-surface: #ffffff;
	--tl-surface-border: #e7edef;
	--tl-text: #223138;
	--tl-text-muted: #71838a;
	--tl-heading: #18353d;
	--tl-accent: #0c5560;
	--tl-accent-2: #00a7ad;
	--tl-btn-grad-top: #0db2b8;
	--tl-btn-grad-bottom: #0a8b92;
	--tl-btn-grad-top-hover: #10c3ca;
	--tl-btn-grad-bottom-hover: #0b99a0;
	--tl-btn-text: #ffffff;
	--tl-link: #0b6670;
	--tl-link-hover: #084d55;
	--tl-listheader-grad-top: #fbfdfd;
	--tl-listheader-grad-bottom: #f3f7f8;
	--tl-input-border: #dce6e8;
	--tl-input-bg: #ffffff;
	--tl-card-shadow: rgba(8, 18, 26, .05);
	--tl-bg-recessed: #eef1f2;
}

body
{
	margin: 0;
	background: var(--tl-bg);
	color: var(--tl-text);
	font-family: 'Inter', 'Segoe UI', Arial, sans-serif;
	font-size: 13px;
	line-height: 1.45;
}

#pageLabel, .pageLabelTD
{
	color: #08121a;
}

body, p, td, th, input, select, textarea, button
{
	font-family: 'Inter', 'Segoe UI', Arial, sans-serif;
	font-size: 13px;
	color: var(--tl-text);
}

body > center,
body > form,
body > table,
body > div
{
	width: 100%;
	box-sizing: border-box;
}

body > center > table[align="center"],
body > form > table[align="center"],
body > table[align="center"]
{
	width: 100% !important;
	margin: 0;
}

table
{
	border-collapse: separate;
	border-spacing: 0;
}

table[bgcolor="#ffffff"],
table[bgcolor="white"],
table[bgcolor="#FFF"],
table[bgcolor="#fff"]
{
	background: var(--tl-surface);
	border: 1px solid var(--tl-surface-border);
	border-radius: 14px;
	box-shadow: 0 14px 34px var(--tl-card-shadow);
	overflow: hidden;
}

/* ===== Legacy bgcolor attributes, mapped to theme tokens ===================
 * An HTML bgcolor attribute is a "presentational hint": any author CSS rule
 * beats it. That is why <body bgcolor="#dddddd"> on 107 pages already loses
 * to the body rule above and needs nothing here. Tables, rows and cells had
 * no such rule, so their hardcoded colours won by default - which is why the
 * Dark and Navy/Gold themes showed white and beige patches on every older
 * page while the rest of the app went dark.
 *
 * The rule for table[bgcolor="#ffffff"] above already covered 51 of those.
 * These cover the remaining ~72, which is the whole of the rest: the counts
 * come from a scan of every .asp in the app, so this is not a sample.
 *
 * Attribute selectors rather than 166 page edits, deliberately - AGENTS.md's
 * guidance for exactly this class of legacy markup is to strengthen the
 * shared rules instead of patching pages one at a time.
 */
tr[bgcolor="#ffffff"], tr[bgcolor="white"],
td[bgcolor="#ffffff"], td[bgcolor="white"]
{
	background-color: var(--tl-surface);
}

table[bgcolor="#dddddd"], tr[bgcolor="#dddddd"], td[bgcolor="#dddddd"],
body[bgcolor="#eeeeee"] table[bgcolor="#eeeeee"]
{
	background-color: var(--tl-bg-recessed);
}

/* The legacy list-header beige. Same colour the home page dashboard already
   moved off, so this brings every other list that still uses it onto the one
   header treatment rather than leaving two competing looks in the app. */
table[bgcolor="#ebeadb"], tr[bgcolor="#ebeadb"], td[bgcolor="#ebeadb"]
{
	background: linear-gradient(180deg, var(--tl-listheader-grad-top) 0%, var(--tl-listheader-grad-bottom) 100%);
	color: var(--tl-heading);
}

/* Hairline rules built the old way: a black <td> holding a 994px-wide 1px
   Black.gif. Two problems, not one - the black never themed, and the fixed
   994px pushed Report pages into horizontal scroll on a phone. The cell's
   own background becomes the rule; the image keeps its layout box (so the
   rule stays exactly 1px tall) but stops painting and stops setting width. */
td[bgcolor="#000000"], table[bgcolor="#000000"],
table[bgcolor="#555555"], table[bgcolor="#666666"], table[bgcolor="#cccccc"]
{
	background-color: var(--tl-surface-border);
}

td[bgcolor="#000000"]
{
	line-height: 0;
	font-size: 0;
}

td[bgcolor="#000000"] > img
{
	width: 100% !important;
	height: 1px !important;
	visibility: hidden;
}

/* Shared breadcrumb. Setup > Ask MyDesk AI, Docs and the MYOB pages each
   carried their own page-local copy with hardcoded greys, so the trail did
   not follow the theme and there were several near-identical definitions to
   keep in step. This is the one to use from here on; the existing local
   copies still render and are listed in todo.md for migration.
   Separators come from CSS rather than the markup, so the trail cannot end
   up with a stray slash when a page omits its last crumb. */
.tl-breadcrumb
{
	font-size: 12px;
	font-weight: 600;
	color: var(--tl-text-muted);
	margin: 0 0 18px;
}

.tl-breadcrumb a
{
	color: var(--tl-text-muted);
	text-decoration: none;
}

.tl-breadcrumb a:hover
{
	color: var(--tl-accent);
	text-decoration: underline;
}

.tl-breadcrumb a + a::before,
.tl-breadcrumb a + span::before
{
	content: "/";
	margin: 0 7px;
	color: var(--tl-surface-border);
}

fieldset
{
	border: 1px solid var(--tl-surface-border);
	border-radius: 10px;
	background: var(--tl-surface);
	padding: 10px 12px 12px;
	box-shadow: 0 6px 18px var(--tl-card-shadow);
	color: var(--tl-text);
	margin-bottom: 10px;
}

legend
{
	display: none;
}

strong
{
	font-size: inherit;
	font-weight: 700;
}

.Header
{
	font-size: 28px;
	font-weight: 800;
	line-height: 1.2;
	color: var(--tl-heading);
}

.Header2, A.Header2, A:Link.Header2, A:Visited.Header2, A:Active.Header2, A:Hover.Header2
{
	font-size: 12px;
	color: var(--tl-text-muted);
	font-weight: 700;
	text-decoration: none;
}

span.Header2, SPAN.Header2
{
	display: none;
}

.Header3
{
	font-size: 11px;
	font-weight: 700;
	color: #607278;
	text-transform: uppercase;
	letter-spacing: .05em;
}

A.Header3, A:Link.Header3, A:Visited.Header3, A:Active.Header3
{
	font-size: 20px;
	font-weight: 800;
	color: #08121a;
	text-decoration: none;
}

.ButtonLink, A.ButtonLink, A:Hover.ButtonLink, A:Link.ButtonLink, A:Visited.ButtonLink, A:Active.ButtonLink
{
	font-size: 11px;
	font-weight: 700;
	color: #ffffff;
	text-decoration: none;
}

.Link2, A.Link2, A:Hover.Link2, A:Link.Link2, A:Visited.Link2, A:Active.Link2
{
	color: #0d6f78;
	text-decoration: none;
}

A, A:Link, A:Visited, A:Active
{
	color: var(--tl-link);
	font-weight: 700;
	text-decoration: none;
}

A:hover, A:Hover
{
	color: var(--tl-link-hover);
	text-decoration: underline;
}

.Error
{
	margin: 0 0 18px;
	padding: 12px 14px;
	text-align: left;
	color: #8f1d1d;
	font-weight: 700;
	background: #fff1f1;
	border: 1px solid #f3c4c4;
	border-radius: 10px;
}

.Req
{
	font-size: 14px;
	color: #cc3a32;
	font-weight: 800;
}

input, select, textarea
{
	border: 1px solid var(--tl-input-border);
	border-radius: 6px;
	background: var(--tl-input-bg);
	color: var(--tl-text);
	padding: 4px 8px;
	box-sizing: border-box;
	transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
	font-size: 12px;
}

input
{
	min-height: 28px;
}

select
{
	min-height: 30px;
	padding-right: 24px;
}

textarea
{
	width: 280px;
	min-height: 92px;
	resize: vertical;
}

input:focus, select:focus, textarea:focus
{
	outline: none;
	border-color: var(--tl-accent-2);
	box-shadow: 0 0 0 4px rgba(0, 167, 173, .12);
}

input[readonly]
{
	background: var(--tl-bg);
	color: var(--tl-text-muted);
}

input[type="button"], input[type="submit"], input[type="reset"], button
{
	/* Setup's button: solid accent, 13px semibold, 8px corners */
	min-height: 32px;
	padding: 7px 14px;
	border: 1px solid #0c5560;
	border-radius: 8px;
	background: #0c5560;
	color: #fff;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0;
	box-shadow: none;
	cursor: pointer;
	line-height: 1.2;
}

input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover, button:hover
{
	background: #094048;
	border-color: #094048;
}

/* Row actions (View, Edit, Delete) are the outline variant, as in Style2.css */
input.grid-btn
{
	background: #fff;
	color: #0c5560;
	padding: 4px 12px;
	font-size: 12.5px;
	min-height: 28px;
}
input.grid-btn:hover
{
	background: #eef3f4;
	border-color: #0c5560;
}

input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active, button:active
{
	transform: translateY(1px);
}

/* Keyboard-focus ring, matching the input/select/textarea focus style above -
   buttons previously had no visible focus indicator for keyboard/screen-reader
   users. :focus-visible skips it for a mouse click, keeps it for Tab. */
input[type="button"]:focus-visible, input[type="submit"]:focus-visible, input[type="reset"]:focus-visible, button:focus-visible,
a:focus-visible
{
	outline: none;
	box-shadow: 0 0 0 4px rgba(0, 167, 173, .35);
}

input[type="button"] + input[type="button"],
input[type="button"] + input[type="submit"],
input[type="submit"] + input[type="button"],
input[type="submit"] + input[type="submit"]
{
	margin-left: 4px;
}

/* View page headers */
.Header4
{
	font-family: 'Inter', Arial, sans-serif;
	font-size: 18px;
	font-weight: 700;
	color: #08121a;
	letter-spacing: -.01em;
}

/* Navbar action button bars on View pages */
.tl-navbar
{
	background: linear-gradient(180deg, #f6fafb 0%, #eef3f4 100%);
	border-bottom: 1px solid #d7e2e5;
}

.tl-navbar td
{
	padding: 10px 12px;
}

/* Toolbar actions on one line; a phone scrolls them sideways rather than
   wrapping them into a three-row block above the record. */
.tl-navbar td:has(input[type="button"])
{
	display: flex;
	flex-wrap: nowrap;
	gap: 6px;
	overflow-x: auto;
	scrollbar-width: none;
	align-items: center;
}

.tl-navbar td input[type="button"],
.tl-navbar td input[type="submit"]
{
	flex: 0 0 auto;
	margin: 0;
	white-space: nowrap;
}

img
{
	max-width: 100%;
}

td
{
	vertical-align: top;
}

td[align="right"]
{
	text-align: right;
}

.FormTopTD, .FormBtmTD
{
	padding: 12px 0 16px;
}

.TDAReq,
td[style*="font-weight:bold"],
td b
{
	color: var(--tl-heading);
	font-weight: 700;
}

.ListHeaderRow
{
	padding: 6px 10px;
	font-weight: 800;
	border-bottom: 1px solid var(--tl-surface-border);
	background: linear-gradient(180deg, var(--tl-listheader-grad-top) 0%, var(--tl-listheader-grad-bottom) 100%);
	color: var(--tl-heading);
	font-size: 11px;
	text-transform: uppercase;
	letter-spacing: .03em;
	position: sticky;
	top: 0;
}

tr td.ListHeaderRow:first-child
{
	border-top-left-radius: 12px;
}

tr td.ListHeaderRow:last-child
{
	border-top-right-radius: 12px;
}

.ListRow td
{
	padding: 5px 10px;
	font-size: 12px;
	background: var(--tl-surface);
	/* Slightly bolder/darker than --tl-surface-border on purpose - that
	   variable is shared by card/fieldset borders too, and darkening it
	   there as well wasn't asked for. color-mix keeps this in step with
	   the active theme instead of a flat hardcoded colour. */
	border-bottom: 1px solid color-mix(in srgb, var(--tl-text) 22%, var(--tl-surface-border));
	vertical-align: middle;
}

.ListRow:nth-child(even) td
{
	background: var(--tl-bg);
}

.ListRow:hover td
{
	background: color-mix(in srgb, var(--tl-accent-2) 12%, var(--tl-surface));
}

table tr td
{
	padding: 4px 8px;
}

table tr + tr td
{
	border-top: 1px solid rgba(151, 172, 180, .75);
}

/* An empty <td> (e.g. a <td colspan=2></td> spacer used only to align a
   button under the right desktop column) still picked up the row-divider
   border-top above, plus this stylesheet's own padding - with no content
   to fill, that rendered as a stray blank line rather than just... not
   being there. Reported live: several thin empty horizontal lines
   stacked above a filter's action buttons (PurchaseOrders, and any other
   filter fieldset using the same colspan-spacer pattern). An empty cell
   should never be visible at all. */
table tr td:empty
{
	border: 0 !important;
	padding: 0 !important;
}

table tr td[colspan]
{
	padding-top: 8px;
	padding-bottom: 8px;
}

hr
{
	border: 0;
	height: 1px;
	background: #d7e2e5;
}

li
{
	margin-bottom: 6px;
}

iframe
{
	border: 0;
	border-radius: 10px;
	background: #ffffff;
	box-shadow: 0 6px 18px rgba(8, 18, 26, .06);
}

/* ===== Compact filter fieldset with expand/collapse ===== */
fieldset.tl-filter
{
	padding: 0;
	overflow: hidden;
	transition: box-shadow .2s ease;
}
fieldset.tl-filter.collapsed
{
	box-shadow: 0 2px 8px rgba(8, 18, 26, .04);
}
fieldset.tl-filter .tl-filter__bar
{
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 8px 12px;
	background: linear-gradient(180deg, #f6fafb 0%, #eaf2f4 100%);
	border-bottom: 1px solid #d7e2e5;
	cursor: pointer;
	user-select: none;
}
fieldset.tl-filter.collapsed .tl-filter__bar
{
	border-bottom: 0;
}
fieldset.tl-filter .tl-filter__title
{
	font-size: 11px;
	font-weight: 800;
	color: #18353d;
	text-transform: uppercase;
	letter-spacing: .04em;
}
fieldset.tl-filter .tl-filter__toggle
{
	font-size: 11px;
	color: #0b6670;
	font-weight: 700;
	margin-left: auto;
}
fieldset.tl-filter .tl-filter__body
{
	padding: 10px 12px;
	transition: max-height .25s ease, opacity .2s ease, padding .2s ease;
	max-height: 800px;
	opacity: 1;
	overflow: hidden;
}
fieldset.tl-filter.collapsed .tl-filter__body
{
	max-height: 0;
	padding-top: 0;
	padding-bottom: 0;
	opacity: 0;
}
fieldset.tl-filter table
{
	width: 100%;
}
fieldset.tl-filter table tr td
{
	padding: 3px 6px;
	vertical-align: middle;
	white-space: nowrap;
}
fieldset.tl-filter input,
fieldset.tl-filter select
{
	min-height: 26px;
	padding: 3px 6px;
	font-size: 12px;
	width: auto;
}
fieldset.tl-filter td[colspan]
{
	padding-top: 6px;
	padding-bottom: 4px;
}

/* ===== Swoosh decorations ===== */
.tl-swoosh-top
{
	position: relative;
}
.tl-swoosh-top::before
{
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	background: linear-gradient(90deg, #00a7ad, #0db2b8, #00a7ad);
	border-radius: 0 0 2px 2px;
}
.tl-swoosh-bar
{
	position: relative;
	overflow: hidden;
}
.tl-swoosh-bar::after
{
	content: '';
	position: absolute;
	bottom: 0;
	left: -10%;
	width: 120%;
	height: 60px;
	background: radial-gradient(ellipse at center, rgba(0, 167, 173, .08) 0%, transparent 70%);
	pointer-events: none;
}

/* ===== Responsive ===== */
@media (max-width: 1024px)
{
	fieldset.tl-filter table tr td
	{
		white-space: normal;
	}
}

@media (max-width: 768px)
{
	/* Safety net: this app is built from decades of fixed pixel-width
	   nested tables that no single selector can all catch. Rather than
	   guess at every layout and risk squeezing a data grid unreadable,
	   let the page pan horizontally so nothing gets silently clipped
	   off-screen. Pages that manage their own scroll region (the
	   ActiveWidgets grid in IFrame.asp) set body { overflow: hidden }
	   inline, which - being more specific - still wins over this. */
	body
	{
		overflow-x: auto;
	}

	body > center > table[align="center"],
	body > form > table[align="center"],
	body > table[align="center"],
	body > center > table[align="center"] table[align="center"],
	body > form > table[align="center"] table[align="center"],
	body > table[align="center"] table[align="center"]
	{
		width: 100% !important;
	}

	/* Broader net: list/filter pages also nest plain `<table width=NNN>`
	   layout tables (no align="center") that the rule above can't reach -
	   e.g. a filter fieldset wrapped in `<table width=760>`. Style2.css
	   (linked by IFrame.asp grid pages, not this stylesheet) is unaffected,
	   so this can't touch the ActiveWidgets grid's own column widths.
	   Deliberately NO max-width cap here (there used to be one): a table
	   whose columns' real minimum content width exceeds the phone screen
	   (e.g. Setup > Users' 8 columns, or an Edit form whose label column is
	   a fixed pixel width via inline style rather than the width=
	   attribute) still has to go SOMEWHERE - capped at max-width:100%, the
	   browser was squeezing such columns below their own minimum width,
	   and word-break below then wrapped their text one character per line
	   instead of the table just growing past the viewport and letting the
	   body{overflow-x:auto} safety net above scroll it horizontally, which
	   is what this stylesheet already intends for exactly this legacy
	   fixed-width-table pattern. A table whose content DOES fit in 100%
	   still renders at 100% either way - auto table layout only grows past
	   the specified width when content forces it to. */
	table[width]
	{
		width: 100% !important;
	}

	/* The two remaining fixed-width elements a scan of every .asp turned up
	   that table[width] above does not reach. Both are small in number but
	   both force the whole page into horizontal scroll on a phone, which is
	   the failure this media query exists to prevent.

	   <hr width=950> on Report pages: four of them, each wider than any
	   phone. Only the width attribute is cleared, so the rule keeps whatever
	   height and colour it had.

	   img[width]: constrains only the width, never the height. A 1px-tall
	   spacer gif is load-bearing layout on these pages, so adding the usual
	   companion height:auto would collapse the gap it exists to hold open -
	   the image simply stops being able to exceed its container. */
	hr[width]
	{
		width: 100% !important;
	}

	img[width]
	{
		max-width: 100%;
	}

	/* Fixed-pixel <td width=NNN> attributes (common on older list pages
	   built like Setup > Expense Types: width=130 + width=350 + width=75
	   alone total more than a whole phone screen) fight the table[width]
	   rule above - forced to 100% table width, the browser then squeezes
	   whichever column was left with NO explicit width down to near-zero,
	   and the word-break rule below wraps its text one character per line
	   instead of the column just taking its fair share. Clearing the
	   attribute-set hint lets auto table layout size columns from actual
	   content instead. */
	table[width] td[width]
	{
		width: auto !important;
	}

	/* Add/Edit form pages (Invoices/Quotes/PurchaseOrders/etc Edit.asp)
	   lay label/value pairs out side-by-side in <td width=NN%> pairs sized
	   for a ~700-770px desktop table (e.g. "Delivery Address" next to
	   "Invoice Address"). table[width] above forces the table to 100% of
	   the phone width, but the percentage widths on td[width] survive as
	   percentages OF that new 100% - still packing two label/value column
	   pairs into one phone-width row, so each column is still too narrow
	   for its own label text and word-break above wraps it one letter per
	   line (e.g. "Invoiced By" rendering as a vertical single-letter
	   column). Worse, that also squeezes OTHER rows in the same table that
	   have no width at all (e.g. "Invoiced By" itself), because plain HTML
	   tables share one column grid across all rows. Stack every %-width
	   cell as its own full-width block instead - same technique already
	   used for fieldset.tl-filter below - which both fixes that row and
	   removes it from the shared column grid so unrelated rows above/below
	   it size themselves from their own content again. */
	table[width] td[width$="%"]
	{
		display: block;
		width: 100% !important;
	}
	table[width] tr:has(td[width$="%"])
	{
		display: block;
	}

	/* Same problem, different pattern: a plain pixel-width label column -
	   <td width=100><b>User Role</b></td> next to an unwidthed value cell
	   (<td><select>...) - used throughout Add/Edit pages app-wide (Users,
	   UserRoles, most other modules' Edit.asp). Not caught by the
	   width$="%" rule above (no % suffix), so it fell through to the
	   `table[width] td[width] { width:auto }` rule several lines up -
	   which clears the pixel width but doesn't stack the row, so the
	   150px-ish label column still had to share the table's column grid
	   with every other row's first cell and got crushed to a
	   one-letter-per-line vertical strip (confirmed live on Setup > Users
	   > Edit). Stack the whole row instead, same technique as the %-width
	   case: label above, value below, full width. Scoped to the specific
	   <td width=NN><b>Label</b></td> shape (direct-child <b>) so it
	   doesn't catch a wider content/description column that happens to
	   contain bold text deeper inside.
	   NOTE: this rule's specificity beats the plain `table[width]
	   td[width]` rule above (extra :has()/> selectors), so it correctly
	   wins for label cells while that older rule still applies to every
	   other unrelated td[width]. */
	table[width] tr:has(> td[width] > b) > td
	{
		display: block;
		width: 100% !important;
	}

	/* Same shape again, third variant: a pixel-width label cell bolded via
	   inline style instead of a <b> child - <td width=170
	   style="font-weight:bold;">First Name</td> (Contacts Add/Edit and
	   others). Not caught by the <b>-child rule above, so it fell through
	   to the same one-letter-per-line crush (confirmed live: "First
	   Name" wrapped to "First"/"Name" stacked vertically in a ~70px
	   column). Stacking the row also frees the value cell from sharing
	   that narrow column grid, so its input/select can actually use the
	   row's full width instead of whatever was left over. */
	table[width] tr:has(> td[width][style*="font-weight:bold"]) > td,
	table[width] tr:has(> td[width][style*="font-weight: bold"]) > td
	{
		display: block;
		width: 100% !important;
	}
	fieldset[style*="width"]
	{
		width: 100% !important;
		max-width: 100% !important;
		box-sizing: border-box;
	}

	/* Fixed-pixel form fields (size=NN, style="width:NNNpx") are common
	   throughout Add/Edit pages and are the single biggest cause of
	   horizontal overflow on a phone-width viewport. */
	input[type="text"], input[type="email"], input[type="tel"],
	input[type="number"], input[type="password"], input[type="url"],
	select, textarea
	{
		max-width: 100%;
		box-sizing: border-box;
	}

	/* Long unbroken strings (emails, part codes, URLs) in a plain <td>
	   otherwise force the row - and the overflow-x:auto safety net above -
	   to scroll for content that could just wrap instead. */
	td
	{
		word-break: break-word;
	}

	fieldset.tl-filter table tr,
	fieldset.tl-filter table td
	{
		display: block;
		width: 100% !important;
		box-sizing: border-box;
	}
	/* input[type=button/submit/reset] get padding:3px 13px from the
	   site-wide button rule; without border-box that padding adds to the
	   100% width instead of being absorbed by it, overflowing the
	   viewport by a few px - exactly the sliver of horizontal scroll a
	   live phone test caught on the filter's action buttons. */
	fieldset.tl-filter input:not([type="button"]):not([type="submit"]):not([type="reset"]),
	fieldset.tl-filter select
	{
		width: 100% !important;
		box-sizing: border-box;
	}


	/* Action-button cells (a td holding 2-3 buttons side by side, e.g. a
	   filter's Invoices/Generate Report/Filter row) got caught by the
	   block-stacking rule above too, forcing each button onto its own
	   100%-wide line - three stacked full-width buttons under a filter
	   that's already six fields tall. Lay them out as a wrapping row
	   instead, same as they'd sit on desktop. */
	fieldset.tl-filter td:has(> input[type="button"]),
	fieldset.tl-filter td:has(> input[type="submit"])
	{
		display: flex !important;
		flex-wrap: wrap;
		gap: 6px;
		justify-content: flex-start;
	}
	fieldset.tl-filter td:has(> input[type="button"]) input,
	fieldset.tl-filter td:has(> input[type="submit"]) input
	{
		width: auto !important;
		flex: 1 1 auto;
	}

	/* A date field's <a><img></a> calendar-picker icon (e.g. Invoices/
	   Default.asp: <input readonly> followed by a calendar-icon link in
	   the same td) got pushed onto its own line under the same
	   block-stacking rule above, since the 100%-wide input left no room
	   beside it. Lay the cell out as a row instead - the input takes the
	   remaining space, the icon keeps its natural size next to it.

	   The `table` and `[src]` in these selectors are load-bearing, not
	   decoration. The standardised-form rule
	   `table[width] tr:has(> td[style*="font-weight:bold"]) > td`
	   also sets `display:block !important` on this same cell, because the
	   row's first cell is the bold "Date From" label. Both declarations are
	   !important, so specificity decides, and that rule is (0,2,3) against
	   the (0,1,5) this one used to be - so block won and the icon dropped
	   to its own line again (reported live on Purchase Orders, after the
	   original fix here had been working). Adding `table` and `[src]` takes
	   this to (0,2,6): same class count, more element/attribute weight, so
	   it wins. Keep both selectors at or above that if either is edited. */
	fieldset.tl-filter table td:has(> input):has(> a > img[src])
	{
		display: flex !important;
		align-items: center;
		gap: 6px;
	}
	fieldset.tl-filter table td:has(> input):has(> a > img[src]) input
	{
		width: auto !important;
		flex: 1 1 auto;
		min-width: 0;
	}
	.ListHeaderRow
	{
		font-size: 10px;
		padding: 4px 6px;
	}
	table tr td
	{
		padding: 3px 5px;
		font-size: 12px;
	}
	/* Same .grid-btn mobile card treatment as Style2.css (IFrame.asp grid
	   pages), needed here too because not every .grid-btn list is an
	   IFrame.asp page - e.g. Setup > Users renders its own plain <table>
	   directly and only links this stylesheet, so it never picked up the
	   card layout and instead got squeezed into an 8-column table with
	   headers wrapping one letter per line (confirmed live). See
	   Style2.css's own comment on this same rule for the full reasoning;
	   kept identical here so both stylesheets' grid-btn tables behave the
	   same way. */
	table:has(.grid-btn) tr:first-child
	{
		display: none;
	}
	table tr:has(.grid-btn)
	{
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		/* No column-gap: see Style2.css's copy of this rule for why -
		   a grid gap shows the table's background instead of the row's,
		   leaving a white seam through striped/hover rows. Cell padding
		   gives the columns their spacing instead. */
		column-gap: 0;
	}
	table tr:has(.grid-btn) > td
	{
		width: auto;
		min-width: 0;
		padding-left: 12px;
		padding-right: 12px;
	}
	table tr:has(.grid-btn) > td:has(.grid-btn)
	{
		grid-column: 1 / -1;
		white-space: nowrap;
		order: 99;
	}
	/* Truncate a long value to one line so every card row stays the same
	   height; Global.js's tap-to-expand toggles .tl-cell-expanded to reveal
	   the rest. These two rules and the filler below existed only in
	   Style2.css - this stylesheet's copy of the grid-card block was added
	   first and never picked them up, so pages that link Style.css (e.g.
	   Setup > Users) got ragged row heights and, worse, the JS-injected
	   filler cells rendered as genuinely empty unstyled holes. */
	table tr:has(.grid-btn) > td[data-label]
	{
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
		cursor: pointer;
	}
	table tr:has(.grid-btn) > td[data-label].tl-cell-expanded
	{
		overflow: visible;
		text-overflow: clip;
		white-space: normal;
		cursor: default;
	}
	table tr:has(.grid-btn) > td[data-label]::before
	{
		content: attr(data-label);
		display: block;
		font-size: 10px;
		font-weight: 700;
		text-transform: uppercase;
		letter-spacing: .03em;
		color: #5a6d7a;
		margin-bottom: 2px;
	}

	/* Global.js's labelGridBtnTables() pads a row out to a multiple of 3
	   with these when its field count doesn't divide evenly, so the last
	   line of the card reads as a deliberately blank cell instead of a hole
	   in the grid. Hidden outside this breakpoint (see the rule after this
	   media query) - desktop's plain table layout would otherwise show it
	   as a genuine extra empty column. */
	.tl-grid-filler
	{
		display: block;
		background: #f8fbfc;
		border: 1px dashed #d7e2e5;
		border-radius: 4px;
	}

	/* --- Standardised input forms (mobile) --- */

	/* Mobile label/value stacking for the modernised form-label pattern. The
	   rules above already stack rows whose label cell is either a %-width cell
	   (tr:has(> td[width$="%"])) or a pixel-width cell wrapping a <b>
	   (tr:has(> td[width] > b)) - the <td width=100><b>Label</b></td> shape used
	   on Users/UserRoles etc. But ~half of all Add/Edit forms use the modernised
	   <td valign=top style="font-weight:bold;">Label</td> shape (no width
	   attribute, no <b>) - not matched by either rule, so on a phone those
	   forms left the label and its input side by side, half-crushed. Stack
	   them the same way: every cell in the row becomes full-width so the
	   asterisk + label + value each sit on their own line. This signature
	   only matches form label cells and filter-field labels - filter tables
	   are already block-laid-out by the fieldset.tl-filter rules above (so
	   there it is a harmless redundancy), and it never matches a list DATA
	   row, which uses th/ListHeaderRow/ListRow classes instead. */
	table[width] tr:has(> td[style*="font-weight:bold"]) > td
	{
		display: block !important;
		width: 100% !important;
	}

	/* Same stacking, minus the table[width] requirement, for any table that
	   has opted into the form-card look. The rule above only matches a table
	   carrying a width ATTRIBUTE, which silently excluded the document
	   step-1 forms (Quotes/PurchaseOrders/RFQ Add.asp) - their inner table
	   is a bare <table cellpadding=5>, so on a phone their label and input
	   stayed side by side while every other form stacked. Keying off the
	   card class instead means opting a form in gives it BOTH the desktop
	   surface and the mobile behaviour, rather than the two depending on
	   unrelated markup details. */
	.tl-form-card tr:has(> td[style*="font-weight:bold"]) > td
	{
		display: block !important;
		width: 100% !important;
	}

	/* Those same legacy rows often carry a spacer cell between the label
	   and the value (<td>&nbsp;&nbsp;</td>). Stacking the row turns it
	   into a blank bordered line BETWEEN a label and its own value, so the
	   two read as unrelated fields with an empty one in between - reported
	   live on Contacts > View Contact. CSS can't match on content, so
	   Global.js tags content-empty cells with data-tl-spacer; hide them
	   here, mobile only, where the row is stacked and the gap they create
	   is meaningless. The extra attribute selector keeps this above the
	   two display:block rules right above - specificity decides this, not
	   source order, and both sides carry !important. */
	table[width] tr:has(> td[style*="font-weight:bold"]) > td[data-tl-spacer],
	.tl-form-card tr:has(> td[style*="font-weight:bold"]) > td[data-tl-spacer]
	{
		display: none !important;
	}

	/* Form action buttons: stack full-width on mobile instead of sitting side
	   by side in the right-aligned action row. Same row-as-block technique as
	   the label stacking above - we re-lay the <tr> and its single colspan <td>
	   out as blocks (NOT display:flex on the <td>, which would void colspan and
	   break the table grid beneath it). */
	tr:has(> td.tl-form-actions)
	{
		display: block !important;
		width: 100% !important;
	}
	tr:has(> td.tl-form-actions) > td
	{
		display: block !important;
		width: 100% !important;
	}
	td.tl-form-actions input[type="button"],
	td.tl-form-actions input[type="submit"]
	{
		display: block;
		width: 100%;
		margin-right: 0;
		margin-bottom: 8px;
		box-sizing: border-box;
	}
	td.tl-form-actions input[type="submit"]
	{
		margin-bottom: 0;
	}
}

/* Grid action buttons (used in IFrame.asp list pages) */
.grid-btn
{
	display: inline-block;
	padding: 3px 10px;
	border: 1px solid #00a7ad;
	border-radius: 5px;
	background: linear-gradient(180deg, #00c8c8 0%, #00a7ad 100%);
	color: #fff;
	font-family: 'Inter', Arial, sans-serif;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.3;
	cursor: pointer;
	transition: transform .05s, box-shadow .1s;
	box-shadow: 0 2px 6px rgba(0, 167, 173, .25);
	margin: 0 2px;
}

.grid-btn:hover
{
	background: linear-gradient(180deg, #00d8d8 0%, #00b8be 100%);
	box-shadow: 0 3px 10px rgba(0, 167, 173, .35);
}

.grid-btn:active
{
	transform: translateY(1px);
}

.grid-btn--danger
{
	background: linear-gradient(180deg, #e8625a 0%, #c94a42 100%);
	border-color: #c94a42;
	box-shadow: 0 2px 6px rgba(201, 74, 66, .25);
}

.grid-btn--danger:hover
{
	background: linear-gradient(180deg, #f0726a 0%, #d95a52 100%);
	box-shadow: 0 3px 10px rgba(201, 74, 66, .35);
}

.grid-btn--neutral
{
	background: linear-gradient(180deg, #f6fafb 0%, #e3ecee 100%);
	border-color: #c8d7db;
	color: #18353d;
	box-shadow: 0 1px 4px rgba(8, 18, 26, .08);
}

.grid-btn--neutral:hover
{
	background: linear-gradient(180deg, #ffffff 0%, #eef3f4 100%);
	box-shadow: 0 2px 6px rgba(8, 18, 26, .12);
}

/* IFrame grid table improvements */
iframe[name="MyIFrame"] table,
iframe[name="MyIFrame"] table td,
iframe[name="MyIFrame"] table th
{
	border-collapse: collapse;
}

iframe[name="MyIFrame"] .header
{
	background: linear-gradient(180deg, #eef3f4 0%, #e3ecee 100%);
	color: #18353d;
	font-weight: 700;
	font-size: 11px;
	padding: 6px 10px;
	border-bottom: 2px solid #c8d7db;
	text-align: left;
}

iframe[name="MyIFrame"] table td
{
	padding: 5px 10px;
	font-size: 12px;
	border-bottom: 1px solid #e3ecee;
	background: #ffffff;
	vertical-align: middle;
}

iframe[name="MyIFrame"] table tr:nth-child(even) td
{
	background: #f8fbfc;
}

iframe[name="MyIFrame"] table tr:hover td
{
	background: #e7f7f8;
}

input[type="radio"],
input[type="checkbox"]
{
	min-height: auto;
	width: 16px;
	height: 16px;
	margin: 2px 4px 2px 0;
	padding: 0;
	cursor: pointer;
	accent-color: #0c5560;
	vertical-align: middle;
}

label
{
	display: inline-flex;
	align-items: center;
	cursor: pointer;
	font-size: 13px;
	color: #08121a;
}

.form-group
{
	margin-bottom: 12px;
}

.form-options
{
	display: flex;
	gap: 16px;
	align-items: center;
	flex-wrap: wrap;
}

/* ===== Standardised input forms ===== =====================================
 * Add/Edit input screens across every module share an almost-identical
 * 3-column table/form layout (Req asterisk | bold label | value) but had
 * never been given a shared visual surface - each form table was just a bare
 * borderless table sitting on the page background. `.tl-form-card` is the
 * opt-in class a form adds to its table, `.tl-form-actions` to its
 * submit/cancel row. Applied to the simple CRUD master forms and ready to
 * drop onto any other form module. The mobile label/value stacking rule in
 * the 768px block below is GLOBAL, so every input form is standardised for
 * mobile whether or not it opts into the card classes.
 */
.tl-form-card
{
	background: var(--tl-surface);
	border: 1px solid var(--tl-surface-border);
	border-radius: 12px;
	box-shadow: 0 6px 18px var(--tl-card-shadow);
}

/* Section-divider rows (<td colspan=N><br><b>Section</b></td>) inside a form
   card get a consistent uppercase header instead of a bare bold line. */
.tl-form-card td[colspan] > b,
.tl-form-card td[colspan] > strong
{
	display: inline-block;
	margin: 8px 0 4px;
	padding: 0 8px;
	font-size: 10.5px;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--tl-text-muted);
	background: var(--tl-listheader-grad-top);
}

/* Primary action row. Kept as inline content (NOT display:flex on the <td>,
   which would void its colspan and break the table grid) - the global button
   rule already paints a consistent teal primary / outline secondary look,
   so here we only add even spacing and a touch of top breathing room. The
   768px block below re-stacks these buttons full-width on a phone. */
.tl-form-actions
{
	padding-top: 14px;
}
.tl-form-actions input[type="button"],
.tl-form-actions input[type="submit"]
{
	margin-right: 6px;
	margin-bottom: 0;
}
.tl-form-actions input[type="submit"]
{
	margin-right: 0;
}

@media (max-width: 480px)
{
	.Header2
	{
		font-size: 11px;
	}
	table tr td
	{
		padding: 2px 4px;
		font-size: 11px;
	}
}

/* Hide the JS-injected filler cells on desktop, where the plain table
   layout would show them as a stray extra empty column.
   Scoped to min-width:769px so it is mutually exclusive with the
   max-width:768px block that shows them. It cannot simply sit outside
   every media query: `table:has(.grid-btn) .tl-grid-filler` (0,2,1) is
   more specific than the `.tl-grid-filler` (0,1,0) rule that shows them,
   and specificity beats media queries - so the "desktop" rule won at every
   width and the fillers never appeared at all. Confirmed live: on
   Setup > Users the cells were injected (12 of them) but computed to
   display:none on a phone. */
@media (min-width: 769px)
{
	table:has(.grid-btn) .tl-grid-filler
	{
		display: none;
	}
}
