body{margin:0;}

.page {
	width: 100%;
}
.page > h1 {
	font-weight: 300 !important;
	color: #fff;
	font-size: 34px;
	margin: 0;
}
.circles-container {
	min-height: 400px;
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-around;
}
.loader {
	position: relative;
	user-select: none;
	box-sizing: border-box;
	width: 150px;
	height: 150px;
}
.loader-bg {
	width: 100%;
	height: 100%;
	border-radius: 50%;
	box-sizing: border-box;
	border: 5px solid #eeeeee;
	display: flex;
	align-items: center;
	justify-content: center;
}
.spinner-holder-one {
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	width: 50%;
	height: 50%;
	background: transparent;
	box-sizing: border-box;
}
.spinner-holder-two {
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	width: 100%;
	height: 100%;
	background: transparent;
	box-sizing: border-box;
}
.loader-spinner {
	width: 200%;
	height: 200%;
	border-radius: 50%;
	border: 5px solid rgb(135, 206, 235);
	box-sizing: border-box;
}
.animate-0-25-a {
	transform: rotate(90deg);
	transform-origin: 100% 100%;
}
.animate-0-25-b {
	transform: rotate(-90deg);
	transform-origin: 100% 100%;
}
.animate-25-50-a {
	transform: rotate(180deg);
	transform-origin: 100% 100%;
}
.animate-25-50-b {
	transform: rotate(-90deg);
	transform-origin: 100% 100%;
}
.animate-50-75-a {
	transform: rotate(270deg);
	transform-origin: 100% 100%;
}
.animate-50-75-b {
	transform: rotate(-90deg);
	transform-origin: 100% 100%;
}
.animate-75-100-a {
	transform: rotate(0deg);
	transform-origin: 100% 100%;
}
.animate-75-100-b {
	transform: rotate(-90deg);
	transform-origin: 100% 100%;
}
.text {
	text-align: center;
	font-size: 20px;
	color: rgb(135, 206, 235);
	font-weight: bold;
}
.blue .loader-bg {
	border-color: rgba(255, 255, 255, 0.1);
	/*box-shadow: inset 2px 2px 20px 0 rgba(0, 0, 0, 0.1) !important;*/
}
.blue .text {
	font-size: 20px;
	color: #3ba8b6 !important;
}
.blue .loader-spinner {
	border-color: #3ba8b6;
}
.blue.circle-loaded-75 .text {
	color: #57a3d8 !important;
}
.blue.circle-loaded-75 .loader-spinner {
	border-color: #57a3d8;
}
.cobalt .loader-bg {
	border-color: #ccc;
	/*box-shadow: inset 2px 2px 20px 0 rgba(0,0,0,0.4) !important;*/
}
.cobalt .text {
	font-size: 20px;
	color: #333 !important;
}
.cobalt .loader-spinner {
	border-color: #333;
}
.fire .loader {
}
.fire .loader-bg {
	border-color: #333;
	/*box-shadow: inset 2px 2px 20px 0 rgba(0, 0, 0, 0.4);*/
}
.fire .text {
	font-size: 20px;
	color: #ee4230 !important;
}
.fire .loader-spinner {
	border-color: #ee4230;
}
.fire.circle-loaded-75 .text {
	color: #c6594e !important;
}
.fire.circle-loaded-75 .loader-spinner {
	border-color: #c6594e;
}
.matte .loader-bg {
	border-color: rgba(255, 255, 255, 0.4);
	/*box-shadow: 2px 2px 20px 0 rgba(0, 0, 0, 0.6);*/
}
.matte .text {
	color: rgba(20, 20, 20) !important;
	font-weight: bold;
}
.matte .loader-spinner {
	border-color: rgba(20, 20, 20);
}
.purple .loader-bg {
	border-color: rgba(255, 255, 255, 0.1);
	/*box-shadow: inset 2px 2px 20px 0 rgba(0, 0, 0, 0.1) !important;*/
}
.purple .text {
	font-size: 20px;
	color: #7b708d !important;
}
.purple .loader-spinner {
	border-color: #7b708d;
}
.purple.circle-loaded-75 .text {
	color: #a186ce !important;
}
.purple.circle-loaded-75 .loader-spinner {
	border-color: #a186ce;
}
.loader-bg {
	border-color: rgba(255, 255, 255, 0.4);
	/*box-shadow: 2px 2px 20px 0 rgba(0, 0, 0, 0.6);*/
}
.text {
	color: rgb(135, 206, 235) !important;
	font-weight: bold;
}
.loader-spinner {
	border-color: rgb(135, 206, 235);
}
.white .loader-bg {
	border-color: rgba(255, 255, 255, 0.1);
	/*box-shadow: inset 2px 2px 20px 0 rgba(0, 0, 0, 0.1) !important;*/
}
.white .text {
	font-size: 20px;
	color: #fff !important;
}
.white .loader-spinner {
	border-color: #fff;
}
.white.circle-loaded-75 .text {
	color: #ddd !important;
}
.white.circle-loaded-75 .loader-spinner {
	border-color: #ddd;
}

}
.page > h1 {
  font-weight: 300 !important;
  color: #fff;
  font-size:34px;
  margin:0;
}
.circles-container {
  min-height: 400px;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-around;
}
.loader {
    position: relative;
    user-select: none;
    box-sizing: border-box;
    width: 150px;
    height: 150px;
}
.loader-bg {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    box-sizing: border-box;
    border: 5px solid #eeeeee;
    display: flex;
    align-items: center;
    justify-content: center;
}
.spinner-holder-one {
    position: absolute;
    top:0;
    left:0;
    overflow: hidden;
    width: 50%;
    height: 50%;
    background: transparent;
    box-sizing: border-box;
}
.spinner-holder-two {
    position: absolute;
    top:0;
    left:0;
    overflow: hidden;
    width: 100%;
    height: 100%;
    background: transparent;
    box-sizing: border-box;
}
.loader-spinner {
    width: 200%;
    height: 200%;
    border-radius: 50%;
    border: 5px solid rgb(135, 206, 235);
    box-sizing: border-box;
}  
.animate-0-25-a {
    transform: rotate(90deg);
    transform-origin: 100% 100%;
}
.animate-0-25-b {
    transform: rotate(-90deg);
    transform-origin: 100% 100%;
}
.animate-25-50-a {
    transform: rotate(180deg);
    transform-origin: 100% 100%;
}
.animate-25-50-b {
    transform: rotate(-90deg);
    transform-origin: 100% 100%;
}
.animate-50-75-a {
    transform: rotate(270deg);
    transform-origin: 100% 100%;
}
.animate-50-75-b {
    transform: rotate(-90deg);
    transform-origin:100% 100%;
}
.animate-75-100-a {
    transform: rotate(0deg);
    transform-origin: 100% 100%;
}
.animate-75-100-b {
    transform: rotate(-90deg);
    transform-origin: 100% 100%;
}
.text {
    text-align: center;
    font-size: 20px;
    color: rgb(135, 206, 235);
    font-weight: bold;  
}
.blue .loader-bg {
  border-color: rgba(255,255,255,0.1);
  /*box-shadow: inset 2px 2px 20px 0 rgba(0,0,0,0.1) !important;*/
}
.blue .text {
  font-size: 20px;
  color: #3ba8b6 !important;
}
.blue .loader-spinner {
  border-color: #3ba8b6;
}
.blue.circle-loaded-75 .text {
  color: #57a3d8 !important;
}
.blue.circle-loaded-75 .loader-spinner {
  border-color: #57a3d8;
}
.cobalt .loader-bg {
  border-color: #ccc;
  /*box-shadow: inset 2px 2px 20px 0 rgba(0,0,0,0.4) !important;*/
}
.cobalt .text {
  font-size: 20px;
  color: #333 !important;
}
.cobalt .loader-spinner {
  border-color: #333;
}
.fire .loader {
}
.fire .loader-bg {
  border-color: #333;
  /*box-shadow: inset 2px 2px 20px 0 rgba(0,0,0,0.4);*/
}
.fire .text {
  font-size: 20px;
  color: #ee4230 !important;
}
.fire .loader-spinner {
  border-color: #ee4230;
}
.fire.circle-loaded-75 .text {
  color: #c6594e !important;
}
.fire.circle-loaded-75 .loader-spinner {
  border-color: #c6594e;
}
.matte .loader-bg {
  border-color: rgba(255,255,255,0.4);
  /*box-shadow: 2px 2px 20px 0 rgba(0,0,0,0.6);*/
}
.matte .text {
  color: rgba(20, 20, 20) !important;
  font-weight: bold;
}
.matte .loader-spinner {
  border-color: rgba(20, 20, 20);
}
.purple .loader-bg {
  border-color: rgba(255,255,255,0.1);
  /*box-shadow: inset 2px 2px 20px 0 rgba(0,0,0,0.1) !important;*/
}
.purple .text {
  font-size: 20px;
  color: #7b708d !important;
}
.purple .loader-spinner {
  border-color: #7b708d;
}
.purple.circle-loaded-75 .text {
  color: #a186ce !important;
}
.purple.circle-loaded-75 .loader-spinner {
  border-color: #a186ce;
}
.loader-bg {
  border-color: rgba(255,255,255,0.4);
  /*box-shadow: 2px 2px 20px 0 rgba(0,0,0,0.6);*/
}
.text {
  color: rgb(135, 206, 235) !important;
  font-weight: bold;
}
.loader-spinner {
  border-color: rgb(135, 206, 235);
}
.white .loader-bg {
  border-color: rgba(255,255,255,0.1);
  /*box-shadow: inset 2px 2px 20px 0 rgba(0,0,0,0.1) !important;*/
}
.white .text {
  font-size: 20px;
  color: #fff !important;
}
.white .loader-spinner {
  border-color: #fff;
}
.white.circle-loaded-75 .text {
  color: #ddd !important;
}
.white.circle-loaded-75 .loader-spinner {
  border-color: #ddd;
}



.yellow .loader-bg {
	border-color: rgba(255, 255, 255, 0.1);
	/*box-shadow: inset 2px 2px 20px 0 rgba(0, 0, 0, 0.1) !important;*/
}

.yellow .text {
	font-size: 20px;
	color: #d2c315 !important;
}

.yellow .loader-spinner {
	border-color: #d2c315;
}

.yellow.circle-loaded-75 .text {
	color: #ffeb3b !important;
}

.yellow.circle-loaded-75 .loader-spinner {
	border-color: #ffeb3b;
}

.yellow .loader-bg {
  border-color: rgba(255,255,255,0.1);
  /*box-shadow: inset 2px 2px 20px 0 rgba(0,0,0,0.1) !important;*/
}
.yellow .text {
  font-size: 20px;
  color: #d2c315 !important;
}
.yellow .loader-spinner {
  border-color: #d2c315;
}
.yellow.circle-loaded-75 .text {
  color: #ffeb3b !important;
}
.yellow.circle-loaded-75 .loader-spinner {
  border-color: #ffeb3b;
}




.dkgray .loader-bg {
	border-color: rgba(255, 255, 255, 0.1);
}

.dkgray .text {
	font-size: 20px;
	color: #333333 !important;
}

.dkgray .loader-spinner {
	border-color: #333333;
}

.dkgray.circle-loaded-75 .text {
	color: #333333 !important;
}

.dkgray.circle-loaded-75 .loader-spinner {
	border-color: #333333;
}

.dkgray .loader-bg {
	border-color: rgba(255,255,255,0.1);
	/*box-shadow: inset 2px 2px 20px 0 rgba(0,0,0,0.1) !important;*/
}

.dkgray .text {
	font-size: 20px;
	color: #333333 !important;
}

.dkgray .loader-spinner {
	border-color: #333333;
}

.dkgray.circle-loaded-75 .text {
	color: #333333 !important;
}

.dkgray.circle-loaded-75 .loader-spinner {
	border-color: #333333;
}
/* CSS custom properties — default skin values.
   Override these in Content/skins/st-*.css files only. */
:root {
    /* ---- brand / accent ---- */
    --st-accent:            #6366f1;
    --st-accent-hover:      #ebebff;
    --st-accent-text:       #ffffff;

    /* ---- backgrounds ---- */
    --st-bg-body:           whitesmoke;
    --st-bg-ribbon:         whitesmoke;
    --st-bg-toolbar:        #E8E8E8;
    --st-bg-footer:         gray;
    --st-bg-dialog-overlay: rgb(50, 50, 70);
    --st-border-color:      #dee2e6;

    /* ---- text ---- */
    --st-text-body:         #212529;
    --st-text-muted:        color-mix(in srgb, var(--st-text-body) 60%, transparent);
    --st-text-footer:       whitesmoke;
    --st-text-search-sel:   blue;
    --st-text-search-cur:   orange;
    --st-text-autofilter:   #b45f06;

    /* ---- grid / report tables ---- */
    --st-grid-header-bg:   color-mix(in srgb, var(--st-accent) 15%, white);
    --st-grid-header-text: color-mix(in srgb, var(--st-accent) 60%, #000);
    --st-grid-alt-row-bg:  color-mix(in srgb, var(--st-accent)  4%, var(--st-bg-body));
    --st-grid-hover-bg:    color-mix(in srgb, var(--st-accent) 10%, white);
    --st-grid-hover-text:  var(--st-text-body);   /* pairs with --st-grid-hover-bg; override together if a skin's hover-bg goes light/saturated enough that body text loses contrast on it */
    --st-grid-border:      var(--st-border-color);
    --st-grid-edited-bg:   #fff3cd;   /* StGrid "edited but not yet saved" yellow flag (.editedgridcell) */
    --st-grid-edited-text: #000000;   /* pairs with --st-grid-edited-bg; override together if a skin's edited-bg goes dark */

    /* ---- grid density (row height / font size) ---- */
    /* Derived from --st-font-size-base so a density-only skin (e.g. Compact) shrinks the grid just by  */
    /* overriding that one var. Font-size and cell-padding-y are a paired lever: bumping one up shifts   */
    /* the other down to hold row height (line-height + 2*padding-y + 1px border) roughly constant -     */
    /* see td.st-grid-cell in standardtime-gridengine.css. Currently ~30px rows at a typical desktop      */
    /* viewport width.                                                                                    */
    --st-grid-font-size:              calc(var(--st-font-size-base) + 0.25vw);
    --st-grid-line-height:            normal;   /* browser default; a density skin can tighten this independently of font-size */
    --st-grid-cell-padding-y:         3px;   /* paired with the font-size bump above to hold ~30px row height */
    --st-grid-header-padding-y:       4px;
    --st-grid-cell-editor-min-height: 22px;

    /* ---- property grid density (row height) ---- */
    /* Separate from the grid density vars above - StPropertyGrid (the property panel) is a different  */
    /* engine/stylesheet from StGrid (the content grid) and is not affected by the vars above. Defaults */
    /* match today's previously-hardcoded values exactly, so only a skin that explicitly overrides these */
    /* (e.g. Compact) changes property panel row height. */
    --st-propgrid-row-min-height:     26px;
    --st-propgrid-cell-padding-y:     1px;
    --st-propgrid-header-padding-y:   4px;

    /* .reporttable* (stdata.Globals.DataTableToHtml() plain HTML report tables) - NOT consumed by StGrid */
    --st-reporttable-col1-bg: color-mix(in srgb, var(--st-accent) 10%, var(--st-bg-body));

    /* ---- tabs ---- */
    --st-tab-bg:             #888888;
    --st-tab-hover-bg:       #466291;
    --st-tab-active-bg:      #293955;
    --st-tab-text:           #ffffff;
    --st-tab-border:         #4897aa;

    /* ---- timesheet cells ---- */
    --st-ts-cell-bg:        #f0f0ff;
    --st-ts-cell-bg-alt:    #E0E0ff;
    --st-ts-cell-bg-sel:    #A0A0ff;

    /* ---- gantt ---- */
    --st-gantt-bar-bg:          lightsteelblue;
    --st-gantt-summary-bg:      orange;
    --st-gantt-summary-triangle: darkorange;
    --st-gantt-percent-bg:      rgba(0, 0, 0, 0.35);
    --st-gantt-milestone-color: slateblue;
    --st-gantt-milestone-bg:    yellow;
    --st-gantt-scale-border:    white;
    --st-gantt-gridline:        lightgray;
    --st-gantt-drag-bg:         blue;
    --st-gantt-link-color:      blue;

    /* ---- gantt critical path ---- */
    --st-gantt-critical-bar-start:    #dc2626;
    --st-gantt-critical-bar-end:      #ef4444;
    --st-gantt-noncritical-bar-start: #2563eb;
    --st-gantt-noncritical-bar-end:   #3b82f6;
    --st-gantt-float-bar-bg:          rgba(30, 58, 95, 0.30);
    --st-gantt-float-bar-stroke:      #3b82f6;
    --st-gantt-float-bar-text:        #60a5fa;
    --st-gantt-critical-arrow:        #ef4444;
    --st-gantt-noncritical-arrow:     #3b82f6;
    --st-gantt-today-color:           #c2580a;
    --st-gantt-weekend-bg:            rgba(0, 0, 0, 0.06);
    --st-gantt-weekend-scale-bg:      rgba(0, 0, 0, 0.12);
    --st-gantt-baseline-bar:          #888888;

    /* ---- dock manager ---- */
    --st-dock-header-bg:    rgba(41, 57, 85, 1.0);
    --st-dock-text:         rgba(255, 255, 255, 1.0);
    --st-dock-border:       #212121;
    --st-dock-pane-bg:      #F5F5F5;
    --st-dock-splitter:     steelblue;
    --st-dock-active-tab:   #212121;
    --st-new-tab-flash:     yellow;

    /* ---- ai chat bubbles ---- */
    --st-ai-bubble-text:    #ffffff;
    --st-ai-bubble-you-bg:  #00469f;
    --st-ai-bubble-ai-bg:   #1e6b3c;
    --st-ai-bubble-app-bg:  #505050;

    /* ---- toasts ---- */
    --st-toast-bg:      color-mix(in srgb, var(--st-bg-body) 92%, var(--st-accent));
    --st-toast-text:    var(--st-text-body);
    --st-toast-border:  var(--st-border-color);
    --st-toast-shadow:  0 6px 18px rgba(0, 0, 0, 0.22), 0 1px 3px rgba(0, 0, 0, 0.14);
    --st-toast-success: #16a34a;
    --st-toast-danger:  #dc2626;
    --st-toast-warning: #d97706;
    --st-toast-info:    #2563eb;

    /* ---- text selection ---- */
    --st-selection-bg:      #6366f1;
    --st-selection-text:    #ffffff;

    /* ---- typography ---- */
    --st-font-family:       inherit;
    --st-font-size-base:    10pt;
    --st-font-weight:       normal;
    --st-border-radius:     4px;
}

/* ------------------------------------------------------------------------- */
/* StPropertyGrid engine - structural + themed base styles                   */
/* Companion to standardtime-propertygridengine.js.                          */
/*                                                                           */
/* Renders a two-level property grid: collapsible category headers, each     */
/* holding name/value property rows. General-purpose: no app-specific rules. */
/* Colors use the --st-* skin variables so every skin themes consistently.   */
/* ------------------------------------------------------------------------- */


/* Root fills the width of its scrolling pane and never overflows horizontally: */
/* the fixed-ish name column plus a flexible value column always add up to the  */
/* pane width, so the editor dropdown buttons on the right stay reachable        */
/* without a horizontal scrollbar. Long names ellipsize and value editors shrink */
/* to fit rather than pushing the row wider than the pane.                       */
.st-propgrid {
    width: 100%;
    color: var(--st-text-body, #212529);
}

/* Hide the grid until the host has applied the saved collapsed-category state, so the */
/* user never sees every category flash open and then collapse (the server renders all */
/* categories expanded). The host must remove this class from a code path that cannot  */
/* be skipped by a JS error: Standard Time removes it in the loader img's inline       */
/* onload try/finally (with an onerror fallback), NOT inside the setup function - a    */
/* missing or stale engine script would prevent that function from ever running and    */
/* leave the grid permanently hidden.                                                  */
.st-propgrid.st-propgrid-initializing {
    visibility: hidden;
}

/* Message the host shows instead of a grid when there is nothing to edit (no          */
/* properties, access denied, build error). Rendered outside the .st-propgrid root.    */
.st-propgrid-caption {
    padding: 12px;
    color: var(--st-text-body, #212529);
}


/* ---- Category ---------------------------------------------------------- */

.st-propgrid-category {
    border-bottom: 1px solid var(--st-border-color, #dee2e6);
}

/* Clickable header row: caret + label. Spans the full width. */
.st-propgrid-category-header {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: var(--st-propgrid-header-padding-y, 4px) 6px;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    background-color: var(--st-grid-header-bg, #f1f3f5);
    color: var(--st-grid-header-text, #212529);
    font-weight: 600;
}

.st-propgrid-category-header:hover {
    background-color: var(--st-grid-hover-bg, #e9ecef);
    color: var(--st-grid-hover-text, inherit);
}

/* Focus ring for keyboard users toggling with Enter / Space. Uses the skin accent   */
/* (--st-accent exists in standardtime-skin-variables.css; there is no --st-focus-ring) */
/* so the ring re-themes per skin instead of being pinned to a hardcoded colour.        */
.st-propgrid-category-header:focus-visible {
    outline: 2px solid var(--st-accent, #6366f1);
    outline-offset: -2px;
}

.st-propgrid-category-label {
    flex: 0 0 auto;
    white-space: nowrap;
}


/* Expand/collapse caret. Drawn as a CSS border-triangle rather than a Unicode  */
/* glyph (e.g. "\25B6") - on some Windows font configurations the browser        */
/* substitutes a colored icon font for that character that ignores `color` and  */
/* always renders solid blue. A border-triangle cannot be hijacked by font       */
/* substitution since it is not text. (Same rationale as the StTree caret.)     */
.st-propgrid-toggle {
    display: inline-block;
    position: relative;
    width: 14px;
    height: 14px;
    flex: 0 0 14px;
    user-select: none;
}

.st-propgrid-toggle::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 4px 0 4px 6px;
    border-color: transparent transparent transparent var(--st-text-muted, gray);
    transform: translate(-50%, -50%);
    transition: transform 0.1s ease;
}

/* Rotate the caret to point down when the category is open */
.st-propgrid-category.st-open > .st-propgrid-category-header > .st-propgrid-toggle::before {
    transform: translate(-50%, -50%) rotate(90deg);
}


/* ---- Category body (property rows) ------------------------------------- */

/* Hidden until the category is expanded */
.st-propgrid-category-body {
    display: none;
}

.st-propgrid-category.st-open > .st-propgrid-category-body {
    display: block;
}


/* ---- Property row ------------------------------------------------------ */

/* Two columns: name | value. The value column flexes; the name column is a    */
/* fixed share so editors line up down the grid.                              */
/* The 24px left padding indents property rows under their category label      */
/* (6px header padding + 14px caret + 4px gap), preserving the indented        */
/* parent/child look of the old IG grid (which used Indentation="15%" - a      */
/* fixed indent is used here so it does not drift with pane width).            */
.st-propgrid-row {
    display: flex;
    align-items: center;
    min-height: var(--st-propgrid-row-min-height, 26px);
    padding: var(--st-propgrid-cell-padding-y, 1px) 6px var(--st-propgrid-cell-padding-y, 1px) 24px;
    white-space: nowrap;
    border-bottom: 1px solid var(--st-border-color, #dee2e6);
}

.st-propgrid-row:hover {
    background-color: var(--st-grid-hover-bg, #e9ecef);
    color: var(--st-grid-hover-text, inherit);
}

/* Property name cell. Marked searchableitem so standardtime-search.js can       */
/* highlight it (adds searchselected / searchcurrent).                          */
/* Pixel basis (not a %) so every editor lines up down the grid regardless of    */
/* the widest value. flex-grow:0 caps it at 200px on wide panels; flex-shrink:1  */
/* with a 120px floor lets it give room back to the value column (and its        */
/* dropdown button) on narrow panels instead of forcing a horizontal scrollbar.  */
/* All rows share the same basis + container width, so they stay aligned even    */
/* while shrinking.                                                              */
.st-propgrid-cell-name {
    flex: 0 1 200px;
    max-width: 200px;
    min-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-right: 6px;
    color: var(--st-text-body, #212529);
}

/* Value cell hosts the server-built editor HTML (input / select / dropdown).   */
/*                                                                              */
/* flex-basis MUST be 0 (flex: 1 1 0), NOT auto. With flex-basis:auto the cell's */
/* base size is its content's max-content - for a native <select> that is its    */
/* widest <option> - which varies per row (long client/project lists vs short    */
/* Yes/No). On rows with a wide dropdown that large basis pulled flex-shrink out  */
/* of the sibling name cell (which is shrinkable), collapsing the name column     */
/* toward its 120px floor, so the editor's LEFT edge protruded farther left than  */
/* the other rows. A 0 basis is content-independent: every row splits the row     */
/* width identically, so the name column stays a constant 200px down the grid.    */
/*                                                                              */
/* overflow:hidden keeps a stray over-wide editor from spilling out and from      */
/* propagating its intrinsic width upward. Safe for the dropdown-panel editors    */
/* (Folder / Attachments / Assign users): their .custom-dropdown-panel is         */
/* position:fixed (see standardtime-main.css), out of flow, so it is not clipped. */
.st-propgrid-cell-value {
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
}

/* Each editor's inner .propertycontainer is display:flex (Bootstrap d-flex), so */
/* the <select>/<input>/<textarea> inside it are flex items. A flex item's       */
/* default min-width:auto equals its content's min size - for a <select> that is */
/* the widest <option> (long client/project lists) - which overrides the inline  */
/* width:100%, refuses to shrink, and overflows the value column, reintroducing  */
/* a horizontal scrollbar. Pin min-width:0 + max-width:100% down the chain so    */
/* the controls honor width:100% and shrink to the value column instead.         */
.st-propgrid-cell-value .propertycontainer {
    min-width: 0;
    max-width: 100%;
}

.st-propgrid-cell-value select,
.st-propgrid-cell-value input,
.st-propgrid-cell-value textarea {
    min-width: 0;
    max-width: 100%;
}


/* ---- Search highlight ---------------------------------------------------- */
/*                                                                            */
/* Intentionally NOT styled here. standardtime-search.js adds the             */
/* searchselected / searchcurrent classes to the .searchableitem name cell,   */
/* and standardtime-search.css already styles those classes with `!important` */
/* backgrounds themed from --st-text-search-sel / --st-text-search-cur. Any    */
/* rule we added here would be dead (the app-wide !important rule always wins) */
/* AND would reference skin variables that do not exist, so the highlight      */
/* would not re-theme on dark skins. Leave highlighting to the shared          */
/* search stylesheet.                                                         */

/* ------------------------------------------------------------------------- */
/* StTree engine - structural + themed base styles                           */
/* Companion to standardtime-treeengine.js.                                  */
/*                                                                           */
/* Reusable by every StTree instance (Filter, Favorites, Check-list,         */
/* User-assign, Folder). Per-tree appearance (font sizes, exact spacing,     */
/* scoping) is layered on top - e.g. standardtime-filtertree.css.            */
/* Colors use the --st-* skin variables so all skins theme consistently.     */
/* ------------------------------------------------------------------------- */


/* Root list and nested child lists */
ul.st-tree,
ul.st-tree-children {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* The root sizes to its widest row (max-content) but always fills the pane     */
/* (min-width:100%). Long labels are therefore not truncated - the scrolling    */
/* container shows a horizontal scrollbar, matching the previous IG tree. Full- */
/* width rows also let the hover/selection highlight span the scrolled width.   */
ul.st-tree {
    width: max-content;
    min-width: 100%;
}

/* Indent one level per depth; children are hidden until the parent is open */
ul.st-tree-children {
    padding-left: 18px;
    display: none;
}

/* Reveal children when the parent node is expanded */
li.st-tree-node.st-parent.st-open > ul.st-tree-children {
    display: block;
}

li.st-tree-node {
    margin: 0;
    padding: 0;
}


/* One clickable row: caret, optional checkbox, optional icon, then label */
.st-tree-row {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 2px 4px;
    white-space: nowrap;
    cursor: pointer;
    border-radius: var(--st-border-radius, 4px);
    color: var(--st-text-body, #212529);
}

.st-tree-row:hover {
    background-color: var(--st-grid-hover-bg, #eef);
    color: var(--st-grid-hover-text, inherit);
}

/* Selected node highlight */
li.st-tree-node.st-tree-selected > .st-tree-row {
    background-color: var(--st-selection-bg, #6366f1);
    color: var(--st-selection-text, #ffffff);
}


/* Expand/collapse caret. The span reserves width on leaves too, so labels    */
/* line up whether or not a node has children.                               */
.st-tree-toggle {
    display: inline-block;
    position: relative;
    width: 14px;
    height: 14px;
    flex: 0 0 14px;
    -webkit-user-select: none; /* Safari */
    -moz-user-select: none;    /* Firefox */
    -ms-user-select: none;     /* IE 10+ */
    user-select: none;
    -webkit-tap-highlight-color: transparent; /* suppress mobile/touch tap-highlight flash */
}

/* Caret glyph appears only on parent nodes. Drawn as a CSS border-triangle rather */
/* than a Unicode glyph (was "\25B6") - Windows substitutes a colored icon font    */
/* for that character in some configurations, which ignores `color` entirely and  */
/* always renders blue regardless of the CSS below. A border-triangle can't be     */
/* hijacked by font substitution since it isn't text.                             */
li.st-tree-node.st-parent > .st-tree-row > .st-tree-toggle::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 4px 0 4px 6px;
    border-color: transparent transparent transparent var(--st-text-muted, gray);
    transform: translate(-50%, -50%);
    transition: transform 0.1s ease;
}

/* Rotate the caret to point down when the parent is open */
li.st-tree-node.st-parent.st-open > .st-tree-row > .st-tree-toggle::before {
    transform: translate(-50%, -50%) rotate(90deg);
}


/* Node icon (data:image/png;base64 from the model) */
.st-tree-icon {
    width: 16px;
    height: 16px;
    flex: 0 0 16px;
    object-fit: contain;
}


/* Checkbox (checkbox trees only: Favorites, Check-list, User-assign) */
.st-tree-checkbox {
    flex: 0 0 auto;
    margin: 0;
    cursor: pointer;
}


/* Label never wraps or truncates; the container scrolls horizontally instead */
/* (matches the previous Infragistics tree).                                  */
.st-tree-label {
    flex: 0 0 auto;
    white-space: nowrap;
}

/* ------------------------------------------------------------------------- */
/* StToaster engine - structural + themed styles                             */
/* Companion to standardtime-toastengine.js.                                 */
/*                                                                           */
/* Replaces the Bootstrap alert-* classes the old jquery.toaster plugin       */
/* borrowed (alert alert-success / alert-danger / btn-close), which were      */
/* hardcoded light-theme colors and unreadable on the dark skins.            */
/*                                                                           */
/* Every color resolves from an --st-toast-* custom property that falls back  */
/* to an existing --st-* skin variable, so the component themes correctly on  */
/* all skins with NO edit to standardtime-skin-variables.css. A skin that     */
/* wants finer control can declare the --st-toast-* names itself - see the    */
/* "optional skin variables" block in ReplaceToaster.md.                      */
/*                                                                           */
/* Design note: the toast surface is neutral (derived from --st-bg-body) with */
/* a colored left accent bar, colored icon and colored title, rather than a   */
/* fully saturated colored panel. A saturated panel has to pick a text color, */
/* and any choice is wrong on half the skins - the old plugin's pale-green    */
/* alert-success with dark text was illegible on st-dark. A neutral surface   */
/* inherits the skin's own text color and can never lose contrast.            */
/* ------------------------------------------------------------------------- */


/* ------------------------------------------------------------------------- */
/* Container                                                                  */
/* ------------------------------------------------------------------------- */

/* One container holds the whole stack. It spans a screen edge, so it must    */
/* never intercept clicks meant for the app underneath - pointer-events is    */
/* re-enabled per toast below.                                                */
.st-toast-container {
    position: fixed;
    z-index: 2147483000;
    display: flex;
    flex-direction: column;
    /* Spacing lives on the toasts as margin-bottom, NOT as a container `gap`. A gap is not an animatable
       property of the leaving element, so it would survive the collapse and snap away only when the node
       is finally removed - a visible 8px jolt at the end of every dismissal. */
    width: 380px;
    max-width: calc(100vw - 20px);
    max-height: calc(100vh - 20px);
    pointer-events: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    overflow: visible;
    font-family: var(--st-font-family, inherit);
    font-size: var(--st-font-size-base, 10pt);
    /* The container is relocated into the open modal <dialog> when there is one (see the "Top layer"
       section of standardtime-toastengine.js). Everything here is parent-independent - position is
       fixed and therefore viewport-relative either way - so no dialog-scoped variant is needed. */
}

/* Anchoring. Top-anchored stacks grow downward (new toasts appended); bottom-anchored stacks grow  */
/* upward (new toasts prepended) - see the isTopAnchored() branch in standardtime-toastengine.js.   */
.st-toast-container.st-toast-top-right    { top: 10px;    right: 10px; }
.st-toast-container.st-toast-top-left     { top: 10px;    left: 10px; }
.st-toast-container.st-toast-top-center   { top: 10px;    left: 50%; transform: translateX(-50%); }
.st-toast-container.st-toast-bottom-right  { bottom: 10px; right: 10px; }
.st-toast-container.st-toast-bottom-left   { bottom: 10px; left: 10px; }
.st-toast-container.st-toast-bottom-center { bottom: 10px; left: 50%; transform: translateX(-50%); }


/* ------------------------------------------------------------------------- */
/* Toast                                                                      */
/* ------------------------------------------------------------------------- */

.st-toast {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin-bottom: 8px;        /* stack spacing - see the note on .st-toast-container */
    padding: 10px 10px 11px 13px;
    box-sizing: border-box;    /* the inline pixel height removeToast() pins must include padding+border */
    pointer-events: auto;      /* re-enable interaction the container turned off */
    overflow: hidden;          /* clips the accent bar and progress bar to the rounded corners */

    background: var(--st-toast-bg, color-mix(in srgb, var(--st-bg-body, #f5f5f5) 92%, var(--st-accent, #6366f1)));
    color: var(--st-toast-text, var(--st-text-body, #212529));
    border: 1px solid var(--st-toast-border, var(--st-border-color, #dee2e6));
    border-radius: var(--st-border-radius, 4px);
    box-shadow: var(--st-toast-shadow, 0 6px 18px rgba(0, 0, 0, 0.22), 0 1px 3px rgba(0, 0, 0, 0.14));

    animation: st-toast-in 180ms ease-out;
}

/* The colored left accent bar carrying the priority signal. Drawn as a pseudo-element rather than a */
/* border-left so the border-radius clip and the progress bar can coexist with it.                   */
.st-toast::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 4px;
    background: var(--st-toast-accent);
}

/* There is deliberately NO `.st-toast:last-child { margin-bottom: 0 }` rule here. It looks tidier, but
   :last-child re-evaluates the instant a leaving toast's node is finally detached: the toast above it
   becomes the new last child and its margin-bottom drops 8px -> 0 in a single frame. On a bottom-anchored
   stack (the small-app layout) that shifts the entire stack 8px at the very end of every dismissal - the
   exact snap the two-phase leave animation exists to eliminate. The cost of leaving it out is 8px of
   transparent space at the stack's trailing edge, which is invisible and, crucially, constant. */

.st-toast-clickable {
    cursor: pointer;
}


/* ---- priority colors ---- */
/* Fixed hex rather than skin variables: these are semantic status colors that must read the same on */
/* every skin (the same reasoning as --st-gantt-critical-* in standardtime-skin-variables.css). They */
/* are used only for the 4px bar, the icon and the title - never as a background behind body text -  */
/* so they cannot create a contrast failure on a light or a dark skin.                               */

.st-toast-success { --st-toast-accent: var(--st-toast-success, #16a34a); }
.st-toast-danger  { --st-toast-accent: var(--st-toast-danger,  #dc2626); }
.st-toast-warning { --st-toast-accent: var(--st-toast-warning, #d97706); }
.st-toast-info    { --st-toast-accent: var(--st-toast-info,    #2563eb); }


/* ---- icon ---- */

.st-toast-icon {
    flex: 0 0 16px;
    width: 16px;
    height: 16px;
    margin-top: 1px;
    /* The inline SVGs use fill/stroke="currentColor", so this one declaration tints them. */
    color: var(--st-toast-accent);
    display: flex;
    align-items: center;
    justify-content: center;
}

.st-toast-icon svg {
    display: block;
}


/* ---- text ---- */

.st-toast-body {
    flex: 1 1 auto;
    min-width: 0;    /* lets a long unbroken token wrap instead of stretching the flex row */
}

.st-toast-title {
    font-weight: bold;
    color: var(--st-toast-accent);
    margin-bottom: 2px;
    overflow-wrap: anywhere;
}

/* pre-wrap is what makes an embedded "\n" render as a real line break. The old plugin converted     */
/* newlines to "<br />" and injected the result with jQuery .html() - that conversion is gone, and   */
/* with it the HTML-injection path for server error text and record names.                           */
/* A window.onerror toast can carry a very long stack trace, so cap the height and scroll inside the  */
/* toast rather than growing a toast taller than the viewport.                                        */
.st-toast-message {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    max-height: 38vh;
    overflow-y: auto;
    line-height: 1.35;
}


/* ---- duplicate counter ---- */

.st-toast-count {
    flex: 0 0 auto;
    align-self: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    font-size: 0.8em;
    font-weight: bold;
    color: var(--st-toast-accent);
    /* Unlike the bare var(--st-toast-accent) uses elsewhere in this file, --st-toast-accent needs a literal
       fallback INSIDE this color-mix(): an invalid color-mix() argument invalidates the whole function (and
       therefore the whole `background` declaration), not just that one argument, whereas a bare `var()` with
       no fallback merely falls back to the property's own initial value. --st-toast-accent is always set in
       practice (renderToast() always adds one of .st-toast-success/-danger/-warning/-info), but this keeps
       the badge from losing its background entirely if that guarantee is ever broken. */
    background: color-mix(in srgb, var(--st-toast-accent, var(--st-toast-info, #2563eb)) 16%, transparent);
}

/* The engine toggles the `hidden` attribute; the display rule above would otherwise beat the UA's */
/* [hidden] { display: none } and leave an empty badge on every single toast.                      */
.st-toast-count[hidden] {
    display: none;
}


/* ---- controls ---- */

.st-toast-controls {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 2px;
    margin-top: -2px;
    margin-right: -2px;
}

.st-toast-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 0;
    border-radius: 3px;
    background: transparent;
    color: var(--st-text-muted, rgba(0, 0, 0, 0.55));
    cursor: pointer;
    line-height: 1;
}

.st-toast-btn:hover {
    background: color-mix(in srgb, var(--st-toast-text, var(--st-text-body, #212529)) 12%, transparent);
    color: var(--st-toast-text, var(--st-text-body, #212529));
}

.st-toast-btn:focus-visible {
    outline: 2px solid var(--st-accent, #6366f1);
    outline-offset: 1px;
}

/* Copy-to-clipboard result feedback (a short tint, no layout shift). */
.st-toast-copy-ok   { color: var(--st-toast-success, #16a34a); }
.st-toast-copy-fail { color: var(--st-toast-danger,  #dc2626); }


/* ---- progress bar ---- */

/* Duration is set inline by the engine (animationDuration = timeout). The bar is paused in place by  */
/* the st-toast-paused class rather than restarted, so it stays in lockstep with the JS timer across  */
/* hover/unhover. The engine adds and removes that class from ONE place (applyPauseState), which is   */
/* what keeps the bar and the setTimeout agreeing when the pointer and the keyboard disagree - hover  */
/* and focus are two independent holds and either alone keeps the class on.                           */
/*                                                                                                    */
/* `forwards` holds the bar at scaleX(0) once it has drained. That is the intended look for a toast    */
/* about to go, but it is also why the engine grants its end-of-life pause grace only once per toast:  */
/* every extra grace period is time the bar has already claimed is spent (see MIN_REMAINING_ON_PAUSE   */
/* in standardtime-toastengine.js).                                                                    */
.st-toast-progress {
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 100%;
    transform-origin: left center;
    background: var(--st-toast-accent);
    opacity: 0.55;
    animation-name: st-toast-progress;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
}

.st-toast-paused .st-toast-progress {
    animation-play-state: paused;
}


/* ------------------------------------------------------------------------- */
/* Animations                                                                 */
/* ------------------------------------------------------------------------- */

/* Slide in from the right edge the stack is anchored to. */
@keyframes st-toast-in {
    from { opacity: 0; transform: translateX(24px); }
    to   { opacity: 1; transform: translateX(0); }
}

/* The leave keyframes handle ONLY the fade and slide. The height collapse that makes the toasts below   */
/* glide up is a separate `transition` declared on .st-toast-leaving below - see the long comment in     */
/* removeToast() for why the two phases cannot both be keyframes (a keyframe would need the start height */
/* written in the stylesheet, and it is a runtime pixel value).                                          */
@keyframes st-toast-out {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(24px); }
}

@keyframes st-toast-in-left {
    from { opacity: 0; transform: translateX(-24px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes st-toast-out-left {
    from { opacity: 1; transform: translateX(0); }
    to   { opacity: 0; transform: translateX(-24px); }
}

@keyframes st-toast-progress {
    from { transform: scaleX(1); }
    to   { transform: scaleX(0); }
}

/* A short pulse when an identical toast arrives and the count badge increments. */
@keyframes st-toast-bump {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.035); }
    100% { transform: scale(1); }
}


/* Specificity note: every rule below that overrides animation-name is written as a compound          */
/* selector at 0,2,0 or higher and ordered so the later rule wins at equal specificity. The           */
/* left-anchored enter override is 0,2,0, so plain `.st-toast-leaving` (0,1,0) would have lost to it  */
/* and a closing toast on a left-anchored stack would have replayed its ENTER animation instead.      */

/* Left-anchored stacks slide in/out from the left instead of the right. */
.st-toast-top-left .st-toast,
.st-toast-bottom-left .st-toast {
    animation-name: st-toast-in-left;
}

/* Phase 1: the toast itself fades and slides out quickly (150ms), and `forwards` holds it invisible for
   the rest of the move.

   Phase 2: the geometry collapses on a decelerating curve after an 80ms head start, so the toast has
   visibly gone before the gap closes and the toasts below glide up and settle rather than snapping. The
   easing is a standard "ease-out-quint" - it does most of its travel early and eases into rest, which is
   what reads as a glide. Do NOT put this back on `ease-in`: that curve barely moves for the first half of
   its duration and then rushes, which is precisely what made the earlier version look snappy.

   All FIVE collapsing values are set inline by removeToast(), never here. A transition only starts when
   the transition property was already present in the element's "before-change" style. Declaring the zero
   targets in this same rule would land them in the very style recalculation that first applies
   `transition`, so the before-change style would still say `transition: none` and margin/padding/border
   would jump straight to zero while only `height` (set inline afterwards) animated - a collapse that
   loses the toast's padding and border on frame one. removeToast() therefore adds this class, forces a
   reflow to commit the transition, and only then writes the five targets.

   Two numbers below are COUPLED TO THE JS and nothing enforces it: the 80ms delay and the 280ms duration
   sum to 360ms, and `LEAVE_FALLBACK_MS` in standardtime-toastengine.js (600) is the safety net that must
   stay clear of that sum. Raise either one past the net and the net starts firing mid-collapse, deleting
   the node partway through the glide - the same visible snap constraint 3 exists to prevent, reached from
   the other side. Change one, change the other.

   The `ease-in` on the `animation` line below is on the FADE (phase 1) and is correct there. The curve the
   "do not put this back on ease-in" warning above refers to is the one on the five transitioned
   properties, which must stay cubic-bezier(0.22, 0.61, 0.36, 1). */
.st-toast.st-toast-leaving {
    animation: st-toast-out 150ms ease-in forwards;
    transition: height         280ms cubic-bezier(0.22, 0.61, 0.36, 1) 80ms,
                margin-bottom  280ms cubic-bezier(0.22, 0.61, 0.36, 1) 80ms,
                padding-top    280ms cubic-bezier(0.22, 0.61, 0.36, 1) 80ms,
                padding-bottom 280ms cubic-bezier(0.22, 0.61, 0.36, 1) 80ms,
                border-width   280ms cubic-bezier(0.22, 0.61, 0.36, 1) 80ms;
    /* pointer-events: none is load-bearing for the timer logic, not just a cosmetic "do not click a
       toast that is on its way out". It is what stops a pointer moving across the collapsing stack from
       firing mouseenter on a record whose timer has already been torn down. (The engine's pause entry
       points all bail on rec.removed, so the pause would be a no-op even without this - but dropping the
       rule would also make the toast clickable, firing onClick for a toast the user can no longer see.)
       Note the flip side: a pointer already resting on the toast when the class lands gets a synthesized
       mouseleave, which is exactly why the resume path must tolerate an already-removed record. */
    pointer-events: none;
}

/* This class is deliberately never removed by bumpDuplicate() after its 220ms pulse finishes - it stays
   until the NEXT bump retriggers it via the classList remove/reflow/add dance. That is only safe because
   `.st-toast.st-toast-bump` and `.st-toast.st-toast-leaving` are equal-specificity compound selectors that
   both set the `animation` shorthand: at equal specificity the later rule in the stylesheet wins outright
   for an element matching both, which today is this rule. If a toast that was ever bumped is later
   dismissed while still carrying this class, ITS FADE-OUT WOULD SILENTLY BE REPLACED BY THE BUMP PULSE.
   removeToast() therefore strips "st-toast-bump" in the same statement that adds "st-toast-leaving" - see
   the comment there. Do not "clean up" that removal as redundant; it is the only thing keeping these two
   classes from ever coexisting on an element. */
.st-toast.st-toast-bump {
    animation: st-toast-bump 220ms ease-out;
}

.st-toast-top-left .st-toast.st-toast-leaving,
.st-toast-bottom-left .st-toast.st-toast-leaving {
    animation-name: st-toast-out-left;
}


/* ------------------------------------------------------------------------- */
/* Reduced motion                                                             */
/* ------------------------------------------------------------------------- */

/* The engine also skips the leave animation entirely under prefers-reduced-motion (it removes the  */
/* node immediately), so this only has to neutralize the enter/bump animations and the progress bar. */
/* The progress bar is hidden rather than merely un-animated: a bar frozen at 100% width would read  */
/* as "this toast is stuck".                                                                         */
@media (prefers-reduced-motion: reduce) {

    .st-toast,
    .st-toast.st-toast-bump,
    .st-toast.st-toast-leaving {
        animation: none !important;
        transition: none !important;
    }

    .st-toast-progress {
        display: none;
    }
}


/* ------------------------------------------------------------------------- */
/* Narrow screens (the bSmallSizeApp / phone layout)                          */
/* ------------------------------------------------------------------------- */

/* Below this width a 380px fixed column plus margins no longer fits, so the stack goes edge-to-edge. */
/* These selectors repeat the anchor class deliberately: they have to match the 0,2,0 specificity of  */
/* the anchor rules above, otherwise `right: 10px` and the -center `translateX(-50%)` would win and   */
/* push the now-full-width bar off screen.                                                            */
@media (max-width: 600px) {

    .st-toast-container.st-toast-top-right,
    .st-toast-container.st-toast-top-left,
    .st-toast-container.st-toast-top-center,
    .st-toast-container.st-toast-bottom-right,
    .st-toast-container.st-toast-bottom-left,
    .st-toast-container.st-toast-bottom-center {
        width: auto;
        /* The base rule's `max-width: calc(100vw - 20px)` is narrower than the 100vw - 16px this
           left/right pair implies, so without overriding it here the max-width cap wins and the
           browser falls back to its CSS2.1 over-constrained resolution: `left` is honored and `right`
           is silently discarded and recomputed, landing a few pixels short of the 8px this rule states.
           `max-width: none` removes the conflicting cap so both insets are honored exactly as written -
           `left`/`right` alone already fully determine the width, so there is nothing left for
           max-width to usefully bound here. */
        max-width: none;
        left: 8px;
        right: 8px;
        transform: none;
    }

    .st-toast-message {
        max-height: 30vh;
    }
}

/* ------------------------------------------------------------------------- */
/* StGrid engine - structural + themed base styles                           */
/* Companion to standardtime-gridengine.js.                                  */
/*                                                                           */
/* Replacement for the Infragistics igGrid CSS used by RecordsetGridPartial- */
/* View.cshtml. Colors use the --st-* skin variables so every skin themes    */
/* consistently (see Content/standardtime-skin-variables.css). Structural    */
/* rules (sticky header, sticky fixed column, resize grip, inline editor)    */
/* are skin-independent.                                                     */
/* ------------------------------------------------------------------------- */


/* The scrolling viewport. Downstream scroll-persistence code binds to        */
/* #{gridId}_scroll and reads its scrollTop/scrollLeft, so THIS element must   */
/* be the one that scrolls. It fills the content pane the partial view gives   */
/* it (that pane is `height: calc(100% - 48px)` in RecordsetGridPartialView).  */
.st-grid-scroll {
    width: 100%;
    height: 100%;
    overflow: auto;
    position: relative;
    /* Reserve the scrollbar's own width/height up front instead of only carving it out of the content   */
    /* box once a scrollbar actually appears. The old grid's AddRightMostFillerColumn hack existed        */
    /* because Infragistics' internal viewport clipped the rightmost column by the scrollbar's width when */
    /* one appeared; this is the modern CSS equivalent for this engine's plain native scroll container -   */
    /* the layout no longer shifts (and the last column no longer gets clipped) as content grows past the */
    /* point a vertical scrollbar is needed.                                                              */
    /* Browsers without scrollbar-gutter support do NOT fall back to "the same as before this rule        */
    /* existed" - the FILLERCOLUMN hack that used to compensate for this is deleted in the same migration, */
    /* so an unsupported browser would get neither fix. scrollbar-gutter only reached broad support        */
    /* recently (Safari added it in 18.2); the @supports block below restores a plain padding-based        */
    /* reservation for browsers that lack it, so the clipping bug this replaces doesn't quietly come back  */
    /* for exactly the users who can't benefit from the modern property.                                   */
    scrollbar-gutter: stable;
}

/* Fallback for browsers without scrollbar-gutter support (see the corrected comment above). A fixed     */
/* 16px right-padding reservation - the same width AddRightMostFillerColumn used - is a coarser fix than */
/* scrollbar-gutter (it reserves the space even when no scrollbar is actually showing), but that's the   */
/* same trade-off the old DOM-column hack made, just expressed in CSS instead of as a phantom column.    */
@supports not (scrollbar-gutter: stable) {
    .st-grid-scroll {
        padding-right: 16px;
        box-sizing: border-box;
    }
}

/* Single table, fixed layout so <colgroup> widths are authoritative (and so   */
/* resizing one column never reflows the others).                              */
table.st-grid {
    border-collapse: separate;   /* separate: sticky cells keep their own borders */
    border-spacing: 0;
    table-layout: fixed;
    /* The real width is set inline (in px) by StGrid._syncTableWidth = the sum of the column widths.  */
    /* Do NOT use `width: max-content` here: with table-layout:fixed it sizes each column to the       */
    /* greater of its <col> width and its own nowrap content width, so a wide-content column (a long   */
    /* project Name) can never be dragged narrower than its text. `width: auto` is only the pre-JS     */
    /* fallback; the inline pixel width overrides it before first paint.                               */
    width: auto;
    min-width: 100%;             /* fill the pane when the summed width is narrower than it            */
    font-size: var(--st-grid-font-size, calc(10pt + 0.25vw));
    line-height: var(--st-grid-line-height, normal);
    color: var(--st-text-body, #212529);
    background-color: var(--st-bg-body, #ffffff);
}

/* fitCols100Perc grids stretch to exactly the viewport width (no h-scroll).    */
table.st-grid.st-grid-fit {
    width: 100%;
    min-width: 0;
}


/* --------------------------------------------------------------------------- */
/* Header                                                                       */
/* --------------------------------------------------------------------------- */

/* Sticky header stays visible while the body scrolls vertically (the old grid  */
/* used FixedHeaders=true). z-index keeps it above body cells; the fixed corner */
/* cell (sticky header AND sticky column) needs to sit above both, handled      */
/* below.                                                                       */
table.st-grid > thead {
    position: sticky;
    top: 0;
    z-index: 3;
}

th.st-grid-header-cell {
    position: relative;
    box-sizing: border-box;
    /* Extra right padding leaves room for the pin button + resize grip so neither overlaps the header  */
    /* text (padding-right: 8px base + ~12px pin + ~10px resizer, rounded up). Vertical padding is a     */
    /* density var so a compact skin can shrink header row height along with the body rows below.        */
    padding: var(--st-grid-header-padding-y, 4px) 26px var(--st-grid-header-padding-y, 4px) 8px;
    text-align: left;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;                                   /* header click = sort */
    background-color: var(--st-grid-header-bg, #f1f3f5);
    color: var(--st-grid-header-text, #212529);
    border-right: 1px solid var(--st-grid-border, #dee2e6);
    /* Thick accent line under the whole header row (parity with the old Infragistics grid). Matched on   */
    /* the trailing spacer + insert-end header cells below so it runs the full width. Uses the skin accent */
    /* so it adapts per skin.                                                                             */
    border-bottom: 3px solid var(--st-accent, #6366f1);
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.st-grid-header-text {
    pointer-events: none;   /* clicks fall through to the <th> sort handler */
}

/* Sort-direction indicator - rendered only in the one header the server reports as sorted            */
/* (_buildHead), so every other header stays bare. Inline (not absolutely positioned like the pin      */
/* button) so it sits right after the label text and never collides with the pin/resize hit-areas at   */
/* the right edge. Inline SVG with fill=currentColor, same reasoning as the pin button above: a         */
/* Unicode arrow glyph risks Windows font substitution that ignores CSS color (CLAUDE.md's StTree        */
/* caret note). One upward-pointing triangle path covers both directions - .st-grid-sort-desc rotates    */
/* it 180deg instead of shipping a second path.                                                          */
.st-grid-sort-icon {
    display: inline-block;
    width: 10px;
    height: 10px;
    margin-left: 4px;
    vertical-align: middle;
    color: var(--st-accent, #6366f1);
    line-height: 0;
}
.st-grid-sort-icon svg {
    display: block;
    width: 100%;
    height: 100%;
}
.st-grid-sort-icon.st-grid-sort-desc {
    transform: rotate(180deg);
}

/* Pin (fix/unfix) toggle - the only user-facing way to fix a column now that Infragistics'          */
/* ShowFixButtons widget chrome is gone. Sits left of the resize grip so the two hit-areas don't      */
/* overlap. A plain circle keeps this dependency-free (no icon font/image), same spirit as the        */
/* CSS border-triangle StTree caret (see CLAUDE.md "StTree caret must be a CSS border-triangle").      */
.st-grid-pin-btn {
    position: absolute;
    top: 50%;
    right: 10px;
    width: 13px;
    height: 13px;
    margin-top: -6px;
    /* The thumbtack is an inline SVG with fill=currentColor (see _buildHead), so `color` skins it and    */
    /* `opacity` dims it. Muted when unpinned; accent + full opacity when pinned.                          */
    color: var(--st-grid-header-text, #212529);
    opacity: 0.4;
    cursor: pointer;
    box-sizing: border-box;
    line-height: 0;                                    /* no extra inline-box height around the SVG */
}
.st-grid-pin-btn svg {
    display: block;
    width: 100%;
    height: 100%;
    /* Unpinned: the tack leans, as if not pushed in. It straightens ("stuck in") when pinned, below. */
    transform: rotate(-30deg);
}
.st-grid-pin-btn:hover {
    opacity: 0.85;
}
.st-grid-pin-btn.st-grid-pin-fixed {
    color: var(--st-accent, #6366f1);
    opacity: 1;
}
.st-grid-pin-btn.st-grid-pin-fixed svg {
    transform: rotate(0deg);                           /* pinned = tack pushed straight in */
}

/* The pin button now carries tabindex="0" (it's the only user-facing way to fix/unfix a column, so it  */
/* can't be mouse-only - see standardtime-gridengine.js's _buildHead). A default browser focus ring on a  */
/* 9px circle sitting inside a header cell is easy to miss or clip against overflow:hidden; give it an     */
/* explicit, larger outline instead so keyboard focus is actually visible here.                             */
.st-grid-pin-btn:focus {
    outline: 2px solid var(--st-accent, #6366f1);
    outline-offset: 2px;
}

/* Resize grip: a thin hit-area pinned to the right edge of each header cell.   */
.st-grid-col-resizer {
    position: absolute;
    top: 0;
    right: 0;
    width: 10px;
    height: 100%;
    cursor: col-resize;
    /* Wider invisible hit target than the 1px visible border it sits on, so a mouse aiming for the
       column edge is less likely to miss onto the header text and trigger a sort instead. Capped at
       10px (not pushed further, and not shifted with a negative `right` to bite into the neighboring
       cell) because th.st-grid-header-cell has overflow:hidden - anything past right:0 would be
       clipped - and because the pin button sits at right:10px/width:13px; going wider here would start
       overlapping its hit zone. */
}
.st-grid-col-resizer:hover {
    background-color: var(--st-accent, #6366f1);
    opacity: 0.5;
}

/* While a drag-resize is in progress, force the resize cursor everywhere and   */
/* prevent accidental text selection.                                          */
body.st-grid-resizing,
body.st-grid-resizing * {
    cursor: col-resize !important;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}


/* Trailing spacer column (auto width) - absorbs the pane's slack width so the real columns always     */
/* render at their exact <col> widths and drag-resize maps 1:1 (see _buildColgroup in the engine).      */
/* pointer-events:none lets a click in the empty header area fall through to the sort handler, which     */
/* then resolves no column and safely no-ops instead of sorting by the spacer. The td variant inherits  */
/* the row background so a SetGridRowStyles custom row color continues to the pane's right edge.         */
th.st-grid-spacer {
    padding: 0;
    background-color: var(--st-grid-header-bg, #f1f3f5);
    border-bottom: 3px solid var(--st-accent, #6366f1);   /* continue the header accent line to the pane's right edge */
    pointer-events: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
td.st-grid-spacer {
    padding: 0;
    background-color: inherit;
    border-bottom: 1px solid var(--st-grid-border, #dee2e6);
    pointer-events: none;
}


/* Skinny trailing "insert column at the end" column (see _buildHead / _buildColgroup in the engine).    */
/* Right-click the header to open the column context menu, whose Insert items add a column at the end.    */
/* Unlike the spacer it KEEPS pointer-events so the contextmenu handler can resolve its <th> (a           */
/* left-click sort is guarded off in OnGridHeaderClickEvent). Purely a render-time affordance - its body  */
/* cells carry no st-grid-cell class, so it never participates in selection / edit / resize.              */
col.st-grid-insert-end {
    width: 24px;
}
th.st-grid-insert-end {
    padding: 0;
    text-align: center;
    vertical-align: middle;
    cursor: context-menu;
    background-color: var(--st-grid-header-bg, #f1f3f5);
    border-bottom: 3px solid var(--st-accent, #6366f1);   /* match the header accent line */
    border-left: 1px solid var(--st-grid-border, #dee2e6);
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
th.st-grid-insert-end .st-grid-insert-end-plus {
    font-weight: 700;
    color: var(--st-text-muted, #adb5bd);
    opacity: 0.6;
}
th.st-grid-insert-end:hover .st-grid-insert-end-plus {
    opacity: 1;
    color: var(--st-text-body, #212529);
}
td.st-grid-insert-end {
    padding: 0;
    background-color: inherit;
    border-bottom: 1px solid var(--st-grid-border, #dee2e6);
    pointer-events: none;
}


/* --------------------------------------------------------------------------- */
/* Body rows + cells                                                            */
/* --------------------------------------------------------------------------- */

/* Gives every row a real (opaque) stylesheet-level default instead of relying on the browser's         */
/* initial background-color value (transparent). td.st-grid-cell's `background-color: inherit` below    */
/* then always inherits something opaque - either this default, or a SetGridRowStyles-applied inline     */
/* override on this same <tr> (SetGridRowStyles sets it via GridRow.css("background-color", ...) in      */
/* standardtime-grid.js, which beats this stylesheet rule the normal way an element's own inline style    */
/* always does). This is also what keeps the pinned/fixed column opaque - see the "Fixed (pinned) column" */
/* section below, which depends on this rule rather than a hardcoded value of its own.                    */
tr.st-grid-row {
    background-color: var(--st-bg-body, #ffffff);
}

/* Group/summary rows (VG_GROUP == "True") get a slightly heavier default shade than plain rows - but      */
/* ONLY as a stylesheet-level DEFAULT, exactly like tr.st-grid-row's own default above. A SetGridRowStyles  */
/* custom row color (e.g. a "Totals" row's orange, or a per-project summary color) is applied as an INLINE */
/* style on this same <tr> (GridRow.css("background-color", ...) in standardtime-grid.js), and an inline    */
/* style on an element always overrides any stylesheet rule for that same element/property, regardless of   */
/* selector specificity - so declaring the alt shade here (on the <tr>, same as the plain-row default)        */
/* rather than as a literal on td.st-grid-cell (see the note below) lets a custom row color win exactly the   */
/* same way it already does for plain rows. tr.st-grid-group-row and tr.st-grid-row have equal specificity    */
/* and both always match the same <tr> (_buildRowHtml adds group as a SECOND class, not a replacement - see    */
/* standardtime-gridengine.js), so source order decides here: this rule comes after tr.st-grid-row's and      */
/* therefore wins for group rows with no custom color, while still losing to either rule's own inline         */
/* override the normal way.                                                                                    */
tr.st-grid-group-row {
    background-color: var(--st-grid-alt-row-bg, #f8f9fa);
}

td.st-grid-cell {
    box-sizing: border-box;
    /* Vertical padding is a density var (see standardtime-skin-variables.css) so a compact skin can   */
    /* shrink row height; horizontal padding stays fixed since it affects column-width math elsewhere. */
    padding: var(--st-grid-cell-padding-y, 3px) 8px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
    border-right: 1px solid var(--st-grid-border, #dee2e6);
    border-bottom: 1px solid var(--st-grid-border, #dee2e6);
    background-color: inherit;   /* inherit the row background so styling set on  */
                                 /* the <tr> (SetGridRowStyles) shows through     */
}

/* Row hover and cell selection below set an opaque LITERAL background-color directly on td.st-grid-cell   */
/* (not "inherit"), so - unlike the plain-state inherit rule above - neither of these two states can ever   */
/* show a SetGridRowStyles custom row color underneath: the literal value always wins over inheritance for  */
/* the element it's declared on, regardless of what the parent <tr>'s own background resolves to. This is   */
/* intentional here (hover/selection are meant to read as a consistent, theme-driven color so the            */
/* interaction state itself stays legible), not a specificity fight with the row's custom color - there      */
/* isn't one; the td's own literal declaration is used unconditionally, the same way it would be even if the */
/* <tr> had no inline style at all. Group/summary rows are DIFFERENT - see the rule below - a custom row      */
/* color must show through on them (e.g. a "Totals" row), so that state deliberately does NOT follow this     */
/* literal-background pattern.                                                                              */
tr.st-grid-row:hover > td.st-grid-cell {
    background-color: var(--st-grid-hover-bg, #eef);
    color: var(--st-grid-hover-text, inherit);
}

/* Group / summary rows (VG_GROUP == "True"): bold text so the hierarchy reads. The background is NOT      */
/* declared here (unlike hover/selected/edited below) - it comes from td.st-grid-cell's own `inherit` rule    */
/* above, picking up whatever tr.st-grid-group-row resolves to (its own alt-shade default, or a              */
/* SetGridRowStyles inline override - see the tr.st-grid-group-row rule's comment). A literal background      */
/* here would permanently hide any custom row color on every group/summary row (e.g. a "Totals" row's         */
/* orange), which is the bug this comment used to describe as intentional and isn't.                          */
tr.st-grid-group-row > td.st-grid-cell {
    font-weight: 600;
}

/* Selected cell highlight (Mode = Cell selection). */
td.st-grid-cell.st-grid-cell-selected {
    background-color: var(--st-accent, #6366f1);
    color: var(--st-accent-text, #ffffff);
    outline: 1px solid var(--st-accent, #6366f1);
    outline-offset: -1px;
}

/* Selection must stay visible even when the row is also hovered or is a group/summary row. Without       */
/* these, it silently isn't: `tr.st-grid-row:hover > td.st-grid-cell` above is (0,0,3,2) and                */
/* `tr.st-grid-group-row > td.st-grid-cell` is (0,0,2,2), both of which outrank the plain                   */
/* `.st-grid-cell-selected` rule's (0,0,2,1) - so a selected cell loses its highlight the instant the       */
/* pointer sits over its row (the single most likely moment for this to happen, right after clicking to     */
/* select), or whenever the selected cell happens to be in a group/summary row. These compound rules         */
/* out-specificity both cases ((0,0,4,2) and (0,0,3,2) respectively) so selection always wins.               */
tr.st-grid-row:hover > td.st-grid-cell.st-grid-cell-selected,
tr.st-grid-group-row > td.st-grid-cell.st-grid-cell-selected {
    background-color: var(--st-accent, #6366f1);
    color: var(--st-accent-text, #ffffff);
}

/* Every cell now carries tabindex="-1" and is focused programmatically on selection (see             */
/* selectCellElement in standardtime-gridengine.js - needed so F2/Enter has something to bubble from). */
/* Suppress the browser's default focus ring: the selected-cell highlight above already communicates   */
/* this, and a native outline on every clicked cell would be a new, unwanted visual side-effect.        */
td.st-grid-cell:focus {
    outline: none;
}
td.st-grid-cell.st-grid-cell-selected:focus {
    outline: 1px solid var(--st-accent, #6366f1);
    outline-offset: -1px;
}

/* Edited cell: the yellow "changed but not yet reloaded" flag. Class name       */
/* (editedgridcell) is unchanged from the igGrid era so existing JS that adds it */
/* keeps working.                                                               */
td.st-grid-cell.editedgridcell {
    background-color: var(--st-grid-edited-bg, #fff3cd);
    color: var(--st-grid-edited-text, #000000);
}

/* Same specificity fight as the selected-cell rules above (editedgridcell is also (0,0,2,1)) and the     */
/* same fix: keep the "unsaved edit" flag visible over hover/group tinting rather than letting it silently */
/* disappear in exactly the states a user is likely to be in right after editing a cell.                    */
tr.st-grid-row:hover > td.st-grid-cell.editedgridcell,
tr.st-grid-group-row > td.st-grid-cell.editedgridcell {
    background-color: var(--st-grid-edited-bg, #fff3cd);
    color: var(--st-grid-edited-text, #000000);
}


/* --------------------------------------------------------------------------- */
/* Inline editor                                                                */
/* --------------------------------------------------------------------------- */

td.st-grid-cell.st-grid-cell-editing {
    padding: 0;
}

.st-grid-cell-input {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    min-height: var(--st-grid-cell-editor-min-height, 22px);
    padding: 1px 7px;
    border: 2px solid var(--st-accent, #6366f1);
    font: inherit;
    color: var(--st-text-body, #212529);
    background-color: var(--st-bg-body, #ffffff);
    outline: none;
}


/* --------------------------------------------------------------------------- */
/* Fixed (pinned) column - only the "Name" column, matching the old grid        */
/* --------------------------------------------------------------------------- */
/* Horizontal sticky pins the column to the left while the body scrolls right.   */
/* left:0 works because it is the only fixable column; a multi-column fix would  */
/* need cumulative left offsets.                                                 */

.st-grid-col-fixed {
    position: sticky;
    left: 0;
    z-index: 2;                                        /* above normal body cells */
    box-shadow: 1px 0 0 var(--st-grid-border, #dee2e6);
}

/* A literal `background-color` declared directly on td.st-grid-cell.st-grid-col-fixed would stop the      */
/* pinned column being transparent, but it can never reflect a SetGridRowStyles custom row color either -   */
/* unlike every other column in the same row (which gets the color via inherit), the pinned column would    */
/* sit at a fixed value regardless of what color the rest of the row was set to. The fix lives upstream:    */
/* `tr.st-grid-row` (see "Body rows + cells" above) carries its own opaque stylesheet-level default, so      */
/* plain `background-color: inherit` on td.st-grid-cell is *always* opaque - either that default, or        */
/* SetGridRowStyles' inline override on the same <tr> - with no separate rule needed here at all.            */
/* td.st-grid-cell's own inherit rule already covers .st-grid-col-fixed cells (they carry both classes),     */
/* so no override is declared in this section for the plain (non-hover/group/selected) state.                */

/* A fixed HEADER cell is sticky in both axes (the top-left corner), so it must   */
/* out-rank both the sticky header (z-index:3) and a sticky body column (z:2).    */
/* Header rows have no SetGridRowStyles custom coloring, so a literal background is fine here.   */
/* position:sticky + left:0 are RESTATED here (not just inherited from .st-grid-col-fixed) because      */
/* `th.st-grid-header-cell { position: relative }` above is more specific than `.st-grid-col-fixed`, so  */
/* without this the pinned header cell stays `relative` and scrolls away horizontally while the body     */
/* cells (td.st-grid-cell sets no position, so .st-grid-col-fixed's sticky wins there) stay pinned - the */
/* header then appears to scroll "into" the pinned column instead of being clipped by it.                */
th.st-grid-header-cell.st-grid-col-fixed {
    position: sticky;
    left: 0;
    z-index: 4;
    background-color: var(--st-grid-header-bg, #f1f3f5);
}

/* No hover/group/selected overrides needed for .st-grid-col-fixed: those three states (see "Body rows +  */
/* cells" above) already set an opaque LITERAL background directly on td.st-grid-cell, which every fixed-   */
/* column cell also matches (it carries both classes) - a separate .st-grid-col-fixed variant of each        */
/* would just repeat the identical value; they don't use "inherit" in the first place, so the specificity    */
/* problem the plain-state fix above addresses never applies to these three.                                 */


/* --------------------------------------------------------------------------- */
/* Cell content helpers                                                          */
/* --------------------------------------------------------------------------- */

/* The collapse/expand rocker image in hierarchy (group) rows. */
td.st-grid-cell .CollapseExpandImg {
    cursor: pointer;
    flex: 0 0 16px;
    margin-right: 2px;
}

/* Gantt placeholder cell keeps its intrinsic sizing; the gantt renderer         */
/* (standardtime-gantt.js) draws into it after render.                           */
td.st-grid-cell .ganttcelldiv {
    position: relative;
    height: 100%;
    min-height: 20px;
}

/* Shared wrapper for text/image/checkbox/objectHtml cell content (_renderText, _renderImage,           */
/* _renderCheckbox, _renderObjectHtml in standardtime-gridengine.js). white-space:nowrap here matches    */
/* what td.st-grid-cell already declares (white-space is inherited, so this is belt-and-suspenders, not  */
/* load-bearing on its own) - centralizing it here replaces what used to be an identical inline          */
/* style="white-space:nowrap;" string repeated on every single cell of every row.                        */
.st-grid-cell-content {
    white-space: nowrap;
}

/* hAlign modifiers (_renderText) - replace the old per-cell inline text-align. */
.st-grid-cell-content.st-align-center {
    text-align: center;
}
.st-grid-cell-content.st-align-right {
    text-align: right;
}

/* Image cell (_renderImage) - centers the image within its cell, replacing the old per-cell inline
   style="display:block;margin:auto;" on the <img>. */
.st-grid-cell-image > img {
    display: block;
    margin: auto;
}

/* Checkbox cell (_renderCheckbox) - centers the checkbox within its cell, replacing the old per-cell
   inline style="display:block;margin:auto;" on the <input>. */
.st-grid-cell-checkbox > input[type="checkbox"] {
    display: block;
    margin: auto;
}

/* ================================================================================================
   StContextMenu - styles for the vanilla-JS context menu engine (standardtime-contextmenuengine.js).
   Replaces Content/contextmenujs-master/contextmenu.css (+ its light/dark themes).

   Skin-aware: every color/metric resolves from a --st-menu-* custom property that falls back to the
   existing global skin variables in standardtime-skin-variables.css, which in turn fall back to a
   hard default. So the menu themes correctly under every skin (including dark skins, which already
   override --st-bg-body / --st-text-body / --st-border-color) with no skin-file edits required.
   To centrally re-theme just the menu, a skin may optionally define the --st-menu-* vars directly.

   The --st-menu-* DEFAULTS are declared on :root, deliberately NOT on .st-contextmenu-container.
   A custom property set directly on an element always wins over one inherited from :root, no matter
   the source order of the stylesheets - so with the defaults on the container, a skin's own
   `:root { --st-menu-bg: ... }` could never take effect and the "a skin may optionally define the
   --st-menu-* vars directly" promise above would silently be a lie. On :root, ordinary cascade order
   applies instead, and #st-skin-link is rendered AFTER ~/bundles/standardtime-css in
   _HeadScripts.cshtml, so a skin's declaration wins as intended. [review finding #14]

   Note this engine is the only *engine* CSS file in the app that adds a token-indirection layer of
   its own - standardtime-treeengine.css / -gridengine.css / -propertygridengine.css all consume the
   global --st-* skin variables directly. The extra layer is kept here because a context menu is a
   free-floating surface that a skin may reasonably want to theme apart from the body/grid it sits
   over; it is a deliberate deviation, not an oversight. [review finding #14]
   ================================================================================================ */

:root {
    /* --- themeable tokens (override any of these in a skin for menu-specific control) --- */
    --st-menu-bg:            var(--st-bg-body, #ffffff);
    --st-menu-text:          var(--st-text-body, #212529);
    --st-menu-border:        var(--st-border-color, #cccccc);
    --st-menu-hover-bg:      var(--st-grid-hover-bg, var(--st-accent, #6366f1));
    --st-menu-hover-text:    var(--st-grid-hover-text, var(--st-text-body, #212529));
    --st-menu-disabled-text: var(--st-text-muted, #999999);
    --st-menu-divider:       var(--st-border-color, #dddddd);
    --st-menu-radius:        var(--st-border-radius, 4px);
    --st-menu-shadow:        0 4px 16px rgba(0, 0, 0, 0.28);
}

.st-contextmenu-container {
    position: fixed;
    left: 0;
    top: 0;
    z-index: 1000000;

    font-family: var(--st-font-family, inherit);
    font-size: calc(8pt + 0.10vw);
    font-weight: var(--st-font-weight, normal);
    color: var(--st-menu-text);

    /* Appear animation uses OPACITY ONLY - never transform. A transformed ancestor would become the
       containing block for the position:fixed submenu <ul>s and break their viewport positioning. */
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.10s ease-out;
}

.st-contextmenu-container.st-open {
    opacity: 1;
    pointer-events: auto;
}

.st-contextmenu-container,
.st-contextmenu-container * {
    box-sizing: border-box;
}

/* ---- menus (root <ul> and every submenu <ul>) ---- */
.st-contextmenu-menu {
    list-style: none;
    margin: 0;
    padding: 4px 0;
    background-color: var(--st-menu-bg);
    color: var(--st-menu-text);
    border: 1px solid var(--st-menu-border);
    border-radius: var(--st-menu-radius);
    box-shadow: var(--st-menu-shadow);
    min-width: 180px;
}

/* The root <ul> flows inside the fixed container. */
.st-contextmenu-container > .st-contextmenu-menu {
    max-height: 90vh;
    overflow-y: auto;
    overflow-x: hidden;
}

/* Submenus are positioned in JS (fixed, viewport-relative) and hidden until .st-open. Kept as
   visibility/opacity (not display:none) so the engine can measure offsetWidth/offsetHeight before
   showing them, and so the parent<->child DOM nesting drives mouseenter/mouseleave hover intent.
   Deliberately NO max-height here (unlike the root <ul> rule above): positionSubmenu() in the engine
   computes and sets an inline max-height itself, per-submenu, only when the submenu is actually taller
   than the viewport (vh - 2 * VIEWPORT_MARGIN). A static max-height here smaller than that threshold
   (90vh was previously used, copied from the root rule) would cap offsetHeight before the engine ever
   measures it, making that branch of positionSubmenu() unreachable. overflow-y stays as a permanent
   safety net for whichever case applies. [review finding #8] */
.st-contextmenu-menu .st-contextmenu-item > .st-contextmenu-menu {
    position: fixed;
    left: 0;
    top: 0;
    overflow-y: auto;
    overflow-x: hidden;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.10s ease-out;
}

.st-contextmenu-menu .st-contextmenu-item > .st-contextmenu-menu.st-open {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
}

/* ---- item rows ---- */
.st-contextmenu-item {
    position: relative;
    display: flex;
    align-items: center;
    padding: 5px 10px;
    padding-right: 1.9em;   /* room for the submenu arrow */
    cursor: pointer;
    white-space: nowrap;
    user-select: none;
}

/* Hover and keyboard focus share one highlight style. */
.st-contextmenu-item:hover,
.st-contextmenu-item.st-focus,
.st-contextmenu-item.st-contextmenu-open {
    background-color: var(--st-menu-hover-bg);
    color: var(--st-menu-hover-text);
}

/* While keyboard nav is active (an arrow/Enter/etc. key was just handled), suspend pointer interaction on
   every row until the next REAL mouse movement. Without this, a stationary mouse left resting on a row
   keeps matching :hover independently of .st-focus (two rows visibly highlighted at once), and worse:
   scrollIntoView() moving list content under that motionless cursor makes the browser fire a genuine
   mouseenter for whatever row ends up under it, which silently steals focus back - arrow-key navigation
   can never make net progress through a scrolled list. pointer-events:none here means :hover simply cannot
   apply and no further mouseenter can fire until the mouse actually moves. [review finding #10] */
.st-contextmenu-container.st-kbd-nav .st-contextmenu-item {
    pointer-events: none;
}

.st-contextmenu-icon {
    flex: 0 0 auto;
    width: 1.5em;
    min-width: 1.5em;
    margin-right: 8px;
    text-align: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.st-contextmenu-icon img {
    max-width: 16px;
    max-height: 16px;
    vertical-align: middle;
}

/* Checkmark for checkable/radio-style items (e.g. a Gantt Interval submenu's Days/Weeks/Months/Quarters/
   Years choices). Drawn as a CSS border-shape, never a Unicode glyph - same reason as the submenu caret
   below and StTree's caret: some Windows font configs substitute a colored icon font for check/tick
   glyphs that ignores `color`, forcing solid blue regardless of skin. `currentColor` means it follows the
   row's text color automatically through hover, focus, and disabled states with no extra rules needed. */
.st-contextmenu-checkmark {
    display: inline-block;
    width: 5px;
    height: 9px;
    border-style: solid;
    border-color: currentColor;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg) translate(-1px, -1px);
}

.st-contextmenu-text {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Submenu caret. Drawn as a CSS border-triangle (never a Unicode glyph): on some Windows font configs
   the browser substitutes a colored icon font for arrow glyphs that ignores `color`, forcing solid
   blue regardless of skin. This is the same reason StTree's caret is a border-triangle. */
.st-contextmenu-arrow {
    position: absolute;
    right: 0.7em;
    top: 50%;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 4px 0 4px 5px;
    border-color: transparent transparent transparent currentColor;
    opacity: 0;   /* only shown on rows that have a submenu */
    transform: translateY(-50%);
}

.st-contextmenu-item.st-contextmenu-has-sub > .st-contextmenu-arrow {
    opacity: 0.7;
}

/* ---- disabled rows ---- */
.st-contextmenu-disabled {
    color: var(--st-menu-disabled-text);
    cursor: default;
    pointer-events: none;
}

.st-contextmenu-disabled:hover {
    background-color: transparent;
    color: var(--st-menu-disabled-text);
}

/* ---- divider rows ---- */
.st-contextmenu-divider {
    height: 0;
    margin: 5px 8px;
    padding: 0;
    border-bottom: 1px solid var(--st-menu-divider);
    cursor: default;
    pointer-events: none;
}

/* ------------------------------------------------------------------------- */
/* Filter tree - appearance to match the previous Infragistics tree           */
/* Layered on the engine base styles (standardtime-treeengine.css); scoped to */
/* #FilterTree. Load order in the CSS bundle:                                 */
/*   standardtime-skin-variables.css                                         */
/*   -> standardtime-treeengine.css                                          */
/*   -> standardtime-filtertree.css                                          */
/*                                                                           */
/* Colors use --st-* skin variables (not hard-coded) so every skin themes    */
/* correctly; the values below reproduce the light-skin look in the          */
/* reference screenshot.                                                     */
/* ------------------------------------------------------------------------- */


#FilterTree {
    /* Same font size the old FilterTreePartialView used */
    font-size: calc(7pt + 0.25vw);

    /* Small left gutter before the first-level carets, plus top/bottom room */
    padding: 4px 0 6px 6px;

    color: var(--st-text-body, #212529);
}


/* Row height/spacing close to the old tree's rows */
#FilterTree .st-tree-row {
    padding: 4px 6px;
    gap: 6px; /* a touch more space between icon and label than the engine default */
}


/* Indentation step per nested level (the old tree stepped ~22px per level) */
#FilterTree .st-tree-children {
    padding-left: 22px;
}


/* Caret: small, like the IG expander triangle (color comes from the engine base) */
#FilterTree .st-tree-toggle {
    font-size: 9px;
}


/* Entity icon (calendar / project / client, etc.) sits just left of the label */
#FilterTree .st-tree-icon {
    margin-right: 2px;
}


/* The filter tree is not a checkbox tree, so no checkbox rules are needed.    */
/* Search highlighting (.searchselected / .searchcurrent on .searchableitem)   */
/* comes from standardtime-search.css and needs nothing here.                 */


/* ------------------------------------------------------- */
/* Standard Time application styles                        */
/* ------------------------------------------------------- */


/* ------------------------------------------------------- */
/* Main page body                                          */
/* ------------------------------------------------------- */
body {
    padding-top: 0px;
    padding-bottom: 0px;
    height: 100vh;
    overflow: hidden;
    font-weight: var(--st-font-weight);
}

::selection {
    background: var(--st-selection-bg);
    color: var(--st-selection-text);
}

/* ------------------------------------------------------- */
/* Real content areas                                      */
/* ------------------------------------------------------- */
.contentareacolor {
    background-color: var(--st-bg-body);
}


/* ------------------------------------------------------- */
/* The main page controls, under ribbon, above footer      */
/* ------------------------------------------------------- */
.maincontentcontainer {
    height: 80%;
    height: calc(100% - 148px - 24px);
    overflow: hidden;
}


/* ------------------------------------------------------- */
/* Override bootstrap because the max-width was so small   */
/* ------------------------------------------------------- */
.container {
    max-width: 10000px !important;
}


/* ------------------------------------------------------- */
/* Small area at the top for ribbon controls               */
/* ------------------------------------------------------- */
.maincontentribboncontainer {
    height: 4%;
    min-height: 148px;
    width: 100%;
    font-size: var(--st-font-size-base);
    background-color: var(--st-bg-ribbon);
}


/* ------------------------------------------------------- */
/* Bottom of page                                          */
/* ------------------------------------------------------- */
.maincontentfootercontainer {
    height: 2%;
    min-height: 24px;
    position: fixed;
    bottom: 0;
    width: 100%;
    display:inline-table;
    background-color: var(--st-bg-footer);
    color: var(--st-text-footer);
}

.progressbarcontainer {
    height: 100%;
    /*display: inline-block;*/
    display: flex;
    width: fit-content;
    float: right;
}



.lightgrayhover { }
.lightgrayhover:hover { background-color: lightgray !important; }

/* ------------------------------------------------------- */
/* Override excessive tab padding                          */
/* ------------------------------------------------------- */
.ui-tabs-mainribbon .ui-tabs-panel {
    display: block;
    /*padding: 1em 1.4em;*/
    padding: 0 !important;
    overflow: hidden !important;
}

.ui-tabs-panel-mainribbon {
    display: block;
    /*padding: 1em 1.4em;*/
    padding: 0 !important;
    overflow: hidden !important;
}

.ui-corner-all {
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    border-bottom-left-radius: 4px;
    border-bottom-right-radius: 4px;
}







/* ------------------------------------------------------- */
/* Design tools window when editing a report               */
/* ------------------------------------------------------- */


.ui-tabs-reportdesigntools .ui-tabs-panel {
    display: block;
    /*padding: 1em 1.4em;*/
    padding: 0 !important;
    overflow-y: scroll !important;
}

.ui-tabs-panel-reportdesigntools {
    display: block;
    /*padding: 1em 1.4em;*/
    padding: 0 !important;
    overflow-y: scroll !important;
}






/* ------------------------------------------------------- */
/* Tables within a report                                  */
/* See stdata.Globals.DataTableToHtml()                    */
/* ------------------------------------------------------- */

.reporttable, .reporttable th, .reporttable td {
    border: 1px solid var(--st-grid-border);
    border-collapse: collapse;
}

.reporttableheaderrow {
    background-color: var(--st-grid-header-bg);
    color: var(--st-grid-header-text);
    font-weight: 700;
}

.reporttablefooterrow {
    background-color: var(--st-grid-header-bg);
    color: var(--st-grid-header-text);
    font-weight:700;
}

.reporttablerows:nth-child(even) {
    background-color: var(--st-grid-alt-row-bg);
}

.reporttablerows:hover {
    background-color: var(--st-grid-hover-bg);
    color: var(--st-grid-hover-text, inherit);
}

.reporttablecols:nth-child(1) {
    background-color: var(--st-reporttable-col1-bg);
    font-weight: 700;
}






/* ------------------------------------------------------- */
/* Become visible after a preiod of time                   */
/* ------------------------------------------------------- */
.transitiontovisible1 {
    opacity: 0;
    transition: opacity 0.5s ease-in;
}

.transitiontovisible2 {
    opacity: 1;
}








/* ------------------------------------------------------- */
/* JQuery UI modal dialog overlay background color         */
/* ------------------------------------------------------- */
.ui-widget-overlay {
    opacity: .70 !important;
    filter: Alpha(Opacity=50) !important;
    background: var(--st-bg-dialog-overlay) !important;
}


/* --------------------------------------------------------------------- */
/* Dropdown panel for custom properties like Folder, Attachments, etc.   */
/* --------------------------------------------------------------------- */
.custom-dropdown-panel {
    position: fixed;
    z-index: 1001;
    width: 500px;
    height: 400px;
    background-color: white;
    border-width: 1px;
    border-color: darkgray;
    border-style: solid;
    overflow: hidden;
    border-radius: 8px;
}


.whitetextshadow {
    text-shadow: -1px -1px 0px white, 1px -1px 0px white, -1px 1px 0px white, 1px 1px 0px white;
}

/* Timesheet cells where hours are entered*/
.timesheettimeperiodcell {
    border-width: 1px;
    border-color: var(--st-ts-cell-bg-alt);
    border-style: solid;
}

/* Timesheet "today" column helps focus on data entry*/
.timesheettodaycolumncell {
    background-color: var(--st-ts-cell-bg);
    mix-blend-mode: darken;
    border-width: 1px;
    border-color: var(--st-ts-cell-bg-alt);
    border-style: solid;
}

.timesheettimeperiodcell:hover { border-color: var(--st-ts-cell-bg-sel); }
.timesheettodaycolumncell:hover { border-color: var(--st-ts-cell-bg-sel); }



/* Signify that an item is selected by user click */
.clickselected {
    background-color: lightblue !important;
}

.draghandle {
    width: 100%; /* Set equal width and height */
    height: 100%;
    background-color: white; /* Optional: Add a background color */
    border-width:1px;
    border-style:solid;
    border-color:orange;
    border-radius: 50%; /* This makes the square element a circle */
}

.draghandle:hover { background-color: cornflowerblue; border-width:2px; }

.floatingmodelessdiv {
    position: relative;
    z-index: -1;
    background: #888;
    border-top-right-radius: 0;
    border-top-left-radius: 0;
    font-size: calc(8pt + 0.25vw);
    border: 1px solid #777;
    color: #FFF;
    padding: 0.4em 1em;
    white-space: nowrap;
    line-height: 1.2em;
    cursor: move;
    display: block;
    outline: 0px;
}

/* Popup list used to select records or items */
.popuplistdiv {
    position: fixed;
    z-index: 2001;
    width: 400px;
    height: 300px;
    background-color: white;
    border-style: solid;
    border-color: darkgray;
    border-width: 1px;
    overflow: hidden;
    border-radius: 4px;
    white-space: nowrap;
}

.popuplistminihtmltreeviewholder {
    width: 100%;
    height: 100%;
    list-style-type: none;
    overflow: scroll;
    cursor: default;
}


.popuplistul {
    width: 100%;
    height: 100%;
    list-style-type: none;
    overflow: scroll;
    cursor: default;
}

.multilinetextarea {
    font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace !important;
}


/* ------------------------------------------------------- */
/* Ribbon button text color                                */
/* ------------------------------------------------------- */
.ribbonbutton, .ribbonbuttonsmall { color: var(--st-text-body); }


/* ------------------------------------------------------- */
/* jQuery UI tab skin overrides                            */
/* Wires jQUI tab classes to --st-* variables so skin     */
/* files retheme tabs without per-skin class rules.        */
/* ------------------------------------------------------- */

.ui-tabs .ui-tabs-nav {
    background: var(--st-tab-bg) !important;
    border: none !important;
}

.ui-tabs .ui-tabs-tab {
    background: var(--st-tab-bg) !important;
    border: 1px solid transparent !important;
    border-bottom: none !important;
}

.ui-tabs .ui-tabs-anchor {
    color: var(--st-tab-text) !important;
}

.ui-tabs .ui-tabs-tab.ui-state-hover {
    background: var(--st-tab-hover-bg) !important;
}

.ui-tabs .ui-tabs-tab.ui-state-active {
    background: var(--st-tab-active-bg) !important;
    border: 1px solid var(--st-tab-border) !important;
    border-bottom: none !important;
    margin-top: 1px !important;
    margin-bottom: 0 !important;
    padding-bottom: 0 !important;
}

.ui-tabs .ui-tabs-tab.ui-state-active .ui-tabs-anchor {
    color: var(--st-tab-text) !important;
}

.ui-tabs .ui-tabs-panel {
    background: var(--st-bg-body) !important;
    color: var(--st-text-body) !important;
    border: none !important;
}

/* Report design/preview tab panels are a page/paper canvas: report objects (searchableitem divs in    */
/* ReportPartialView.cshtml) render with colors chosen against a white page - rptdata's DisplayObject   */
/* treats a white object background as "transparent", assuming a white canvas underneath - so these two */
/* panels must stay literal white regardless of skin, the same way a document page stays white even in  */
/* a dark-themed app. ID selector + !important to outrank the generic .ui-tabs-panel rule above without  */
/* touching ui-tabs-panel everywhere else (ribbon tabs, report design tools tabs, etc).                  */
/* Deliberately targets #DesignTab/#PreviewTab (sized directly by jQuery UI's heightStyle:"fill") rather  */
/* than the nested #DesignTabReportDiv/#PreviewTabReportDiv - those rely on a height:100% cascade through */
/* the scrolling wrapper div that does not reliably resolve to the tab pane's full height, so painting    */
/* white on them exposes a collapsed box instead of covering the whole pane.                              */
#DesignTab, #PreviewTab {
    background: white !important;
    color: #000000 !important;
}


/* ------------------------------------------------------- */
/* AI chat bubbles                                         */
/* ------------------------------------------------------- */
.ai-bubble {
    width: 78%;
    border-radius: 14px;
    padding: 6px 10px;
    color: var(--st-ai-bubble-text);
    font-size: 9pt;
    font-family: inherit;
    border: none;
    resize: none;
    overflow: hidden;
    word-break: break-word;
    white-space: pre-wrap;
    margin-bottom: 6px;
    display: block;
    box-sizing: border-box;
}

.ai-bubble-you {
    background-color: var(--st-ai-bubble-you-bg);
    margin-left: auto;
}

.ai-bubble-ai {
    background-color: var(--st-ai-bubble-ai-bg);
}

.ai-bubble-app {
    background-color: var(--st-ai-bubble-app-bg);
}

.ai-bubble-error-row {
    position: relative;
    display: block;
    width: 78%;
    margin-bottom: 6px;
}

.ai-bubble-error-row .ai-bubble {
    width: 100%;
    margin-bottom: 0;
}

.ai-error-info-icon {
    position: absolute;
    bottom: 5px;
    right: 6px;
    cursor: pointer;
    font-size: 0.9em;
    color: white;
    background: var(--st-accent);
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1em;
    height: 1em;
    user-select: none;
    transition: transform 0.15s ease;
}

.ai-error-info-icon:hover {
    transform: scale(1.2);
}

/* ------------------------------------------------------------------ */
/* Native <dialog> base                                                  */
/* ------------------------------------------------------------------ */
.st-dialog {
    outline: none;  /* suppress native browser focus ring — dialog is not a focusable interactive element */
    border: 1px solid rgba(0, 0, 0, 0.20);
    border-radius: 6px;
    padding: 0;
    background: var(--st-bg-body, #f5f5f5);
    color: var(--st-text-body, #212529);
    font-size: calc(8pt + 0.25vw);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
    min-width: 320px;
    max-width: 60vw;
    max-height: 90vh;
    /* overflow must be visible so jQuery UI resize handles (injected as
       children at the edges) are not clipped. Scrolling is on .st-dialog-body. */
    overflow: visible;
    /* Explicit top/left centering applied by StDialog.center() via inline style.
       Do NOT set position here — jQuery UI draggable requires position:fixed to
       be set at open time so it can read/write top+left in viewport coords. */
}

/* Apply flex layout only when the dialog is open. The [open] attribute is
   added by showModal()/show() and removed by close(). Without this scope,
   display:flex overrides the browser's default display:none for closed
   <dialog> elements, making all three shells visible on page load. */
dialog[open].st-dialog {
    display: flex;
    flex-direction: column;
}

@keyframes st-titlebar-flash {
    0%   { background: var(--st-dock-header-bg, #293955); }
    15%  { background: var(--st-new-tab-flash, yellow); }
    30%  { background: var(--st-dock-header-bg, #293955); }
    50%  { background: var(--st-new-tab-flash, yellow); }
    100% { background: var(--st-dock-header-bg, #293955); }
}

.st-dialog-titlebar.st-titlebar-flash {
    animation: st-titlebar-flash 0.8s ease-out;
}

.st-dialog::backdrop {
    background: var(--st-bg-dialog-overlay, rgb(50, 50, 70));
    opacity: 0.65;
}

/* ------------------------------------------------------------------ */
/* Title bar — doubles as drag handle                                    */
/* ------------------------------------------------------------------ */
.st-dialog-titlebar {
    background: var(--st-dock-header-bg, #293955);
    color: var(--st-dock-text, #fff);
    padding: 8px 14px;
    font-weight: 600;
    font-size: calc(8pt + 0.3vw);
    display: flex;
    align-items: center;
    justify-content: space-between;
    user-select: none;
    flex-shrink: 0;
    border-radius: 6px 6px 0 0;
    cursor: move;  /* signals drag affordance */
}

/* Window control buttons grouped on the right of the title bar */
.st-dialog-titlebar-buttons {
    display: flex;
    gap: 2px;
    align-items: center;
    flex-shrink: 0;
}

.st-dialog-min-btn,
.st-dialog-max-btn,
.st-dialog-close-btn {
    background: none;
    border: none;
    color: var(--st-dock-text, #fff);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 3px;
    opacity: 0.8;
}
.st-dialog-min-btn:hover,
.st-dialog-max-btn:hover,
.st-dialog-close-btn:hover {
    opacity: 1;
    background: rgba(255, 255, 255, 0.15);
}
.st-dialog-close-btn { font-size: 18px; }  /* close is primary — slightly larger */

/* ------------------------------------------------------------------ */
/* Body                                                                  */
/* ------------------------------------------------------------------ */
.st-dialog-body {
    padding: 20px;
    overflow-y: auto;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
}

/* ------------------------------------------------------------------ */
/* Icon + message row                                                    */
/* ------------------------------------------------------------------ */
.st-dialog-icon-row {
    display: flex;
    gap: 16px;
    align-items: flex-start;
}

.st-dialog-icon {
    width: 64px;
    height: 64px;
    flex-shrink: 0;
}

.st-dialog-message {
    white-space: pre-line;
    overflow-y: auto;
    max-height: 55vh;
    flex: 1;
}

/* ------------------------------------------------------------------ */
/* Prompt textarea (read-only prompt text)                               */
/* ------------------------------------------------------------------ */
.st-dialog-prompt-label {
    width: 100%;
    border: none;
    resize: none;
    background: transparent;
    color: inherit;
    font-size: inherit;
    font-family: inherit;
    overflow-y: auto;  /* show scrollbar if text overflows the fixed row height */
}

/* ------------------------------------------------------------------ */
/* Value input                                                           */
/* ------------------------------------------------------------------ */
.st-dialog-value-input {
    width: 100%;
    margin-top: 8px;
    padding: 4px 6px;
    font-size: inherit;
    border: 1px solid #aaa;
    border-radius: 3px;
    box-sizing: border-box;
    resize: none;  /* single-line default; overridden for multiline via .st-multiline */
}
/* Applied by JS (.toggleClass) only when prompt.bMultiline is true.
   Cannot use [rows] here — rows="1" is always present in the HTML, so [rows]
   would match even for single-line prompts and make them vertically resizable. */
.st-dialog-value-input.st-multiline {
    resize: vertical;
}

/* ------------------------------------------------------------------ */
/* Button row                                                            */
/* ------------------------------------------------------------------ */
.st-dialog-button-row {
    display: flex;
    justify-content: center;
    gap: 12px;
    margin-top: auto;   /* flex: pushes to bottom of body; non-flex parent: resolves to 0 */
    padding-top: 16px;  /* visual gap above buttons in all contexts */
    flex-shrink: 0;
}

.st-dialog-button-row input[type="button"],
.st-dialog-button-row button {
    min-width: 90px;
    padding: 6px 16px;
    font-size: inherit;
    font-family: inherit;
    cursor: pointer;
    border: 1px solid #aaa;
    border-radius: 4px;
    background: var(--st-accent, #6366f1);
    color: var(--st-accent-text, #fff);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.st-dialog-button-row input[type="button"]:hover,
.st-dialog-button-row button:hover {
    background: var(--st-accent-hover, #ebebff);
    color: var(--st-text-body, #212529);
}

/* Cancel / secondary button */
.st-dialog-button-row input[type="button"].st-btn-cancel,
.st-dialog-button-row button.st-btn-cancel {
    background: var(--st-bg-toolbar, #E8E8E8);
    color: var(--st-text-body, #212529);
}
.st-dialog-button-row input[type="button"].st-btn-cancel:hover,
.st-dialog-button-row button.st-btn-cancel:hover {
    background: var(--st-grid-hover-bg, #ccc);
    color: var(--st-grid-hover-text, inherit);
}

/* Disabled state — otherwise .prop("disabled", true) blocks clicks but leaves the button looking identical to enabled */
.st-dialog-button-row input[type="button"]:disabled,
.st-dialog-button-row button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* ------------------------------------------------------------------ */
/* Warn-delete large icon variant                                        */
/* ------------------------------------------------------------------ */
.st-dialog-icon-large {
    display: block;
    width: 60%;
    max-width: 256px;
    margin: 0 auto 12px;
}

/* ------------------------------------------------------------------ */
/* jQuery UI resize handles — override defaults so they sit on top of   */
/* the dialog border and are visible against the skin background.        */
/* ------------------------------------------------------------------ */
.st-dialog .ui-resizable-handle {
    z-index: 10;
}
.st-dialog .ui-resizable-se {
    /* Bottom-right corner grip — keep the default jQuery UI icon */
    width: 14px;
    height: 14px;
    right: 0;
    bottom: 0;
}
.st-dialog .ui-resizable-s,
.st-dialog .ui-resizable-n  { height: 6px; cursor: ns-resize; }
.st-dialog .ui-resizable-e,
.st-dialog .ui-resizable-w  { width: 6px;  cursor: ew-resize; }
.st-dialog .ui-resizable-ne,
.st-dialog .ui-resizable-nw,
.st-dialog .ui-resizable-sw { width: 10px; height: 10px; }

/* ------------------------------------------------------------------ */
/* Minimized state — body hidden, title bar only, drag still active      */
/* ------------------------------------------------------------------ */
.st-dialog.st-dialog-minimized {
    min-height: 0;
    max-height: none;
    overflow: hidden;  /* clips jQuery UI resize handle divs that sit outside the title bar */
}
.st-dialog.st-dialog-minimized .st-dialog-body {
    display: none;
}
.st-dialog.st-dialog-minimized .ui-resizable-handle { display: none; }

/* ------------------------------------------------------------------ */
/* Maximized state — full viewport, drag and resize suppressed           */
/* ------------------------------------------------------------------ */
.st-dialog.st-dialog-maximized {
    top: 0 !important;
    left: 0 !important;
    width: 100vw !important;
    height: 100vh !important;
    max-width: none !important;
    max-height: none !important;
    border-radius: 0;
}
.st-dialog.st-dialog-maximized .st-dialog-body {
    /* flex: 1 1 auto on .st-dialog-body fills remaining height automatically;
       no explicit height needed and no hardcoded title-bar subtraction. */
    max-height: none;
    overflow-y: auto;
}
.st-dialog.st-dialog-maximized .ui-resizable-handle { display: none; }

/* ------------------------------------------------------------------ */
/* Modeless variant — opened with .show(), no ::backdrop                 */
/* Needs stronger visual treatment to stand out from page content        */
/* because the browser does not dim the background for .show() dialogs.  */
/* ------------------------------------------------------------------ */
.st-dialog.st-dialog-modeless {
    z-index: 9999;  /* showModal() uses the top layer; show() does not — explicit z-index required */
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.50);
}


/* ------------------------------------------------------- */
/* Standard Time ribbon styles                             */
/* ------------------------------------------------------- */

/* https://api.jqueryui.com/theming/css-framework/ */
#MainRibbonTabs .ui-state-active                { background-color: var(--st-tab-active-bg); }
#MainRibbonTabs .ui-state-hover                 { background-color: var(--st-tab-hover-bg); }
#MainRibbonTabs .ui-state-active a,
#MainRibbonTabs .ui-state-hover  a              { color: var(--st-tab-text); }

.ribbonbutton {
    font-size: 9pt !important;
    line-height: 90px !important;
    height: 75px !important;
    border: none !important;
    transition-duration: 0.3s;
}

.ribbonbutton:focus-visible {
    outline: 2px solid var(--st-accent);
    outline-offset: -2px;
    border-radius: 10px;
}

/* Enlarge button image slightly during hover*/
.ribbonbutton:hover {
    background-color: var(--st-accent-hover) !important;
    background-size: 34px !important;
    border-radius: 10px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
    transform: translateY(-1px);
}

.ribbonbutton:active {
    box-shadow: none;
    transform: translateY(0);
    filter: brightness(0.95);
}

.ribbonpanelcontainer {
    width: max-content;
    display: grid;
    grid-auto-flow: column;
    overflow-x: auto;
    overflow-y: hidden;
}

.ribbonpanel {
    font-size: 12px;
    color: var(--st-text-muted);
    padding-top: 5px;
    padding-left: 4px;
    padding-right: 4px;
    width: max-content;
    border-right: 1px solid var(--st-grid-border, #dee2e6);
}

.ribbonpanellabel {
    text-align: center;
}


.ribbonbuttonsmall {
    background-color: transparent;
    border: none !important;
    text-align: left;
    transition-duration: 0.3s;
}

.ribbonsmallbuttoncontainer {
    height: 75px !important;
    display: grid;
    grid-template-columns: auto auto auto auto auto;
}


/* ------------------------------------------------------- */
/* Ribbon dropdown button                                   */
/* ------------------------------------------------------- */

.ribbon-dropdown-wrap {
    position: relative;
    display: inline-block;
}

.ribbon-dropdown-menu {
    position: fixed;
    z-index: 9999;
    background-color: var(--st-bg-ribbon);
    border: 1px solid var(--st-border-color);
    border-radius: 4px;
    box-shadow: 0 4px 8px rgba(0,0,0,0.15);
    white-space: nowrap;
    padding: 4px 0;
}

.ribbon-dropdown-item {
    display: block;
    width: 100%;
    text-align: left;
    background-color: transparent;
    border: none !important;
    padding: 6px 16px 6px 28px;
    font-size: 9pt;
    cursor: pointer;
    transition-duration: 0.3s;
    line-height: normal !important;
    height: auto !important;
    background-position: 8px center !important;
    background-size: 16px !important;
}

.ribbon-dropdown-item:hover {
    background-color: var(--st-accent) !important;
    color: var(--st-accent-text) !important;
    background-size: 16px !important;
}




/* ------------------------------------------------------- */
/* Standard Time search bar styles                         */
/* ------------------------------------------------------- */


.searchbutton {
    font-size: 9pt !important;
    line-height: 90px !important;
    width: 32px !important;
    height: 32px !important;
    border: none !important;
    transition-duration: 0.3s;
}

/* Enlarge button image slightly during hover*/
.searchbutton:hover {
    transform: scale(1.1);
}


.searchcontainer {
    margin-left: auto;
    margin-right: 0;
}

/* Collapsed by default (jQuery .animate() opens/closes this on focus). This element - not the
   input - now owns the rounded-pill look: background + border-radius live here, and overflow:hidden
   clips the input and clear button to that same rounded shape (a clipping box follows its own
   border-radius), so the two children read as one continuous box instead of separate pieces. */
.searchinputwrap {
    display: inline-flex;
    align-items: center;
    overflow: hidden;
    width: 0px;
    height: 28px;
    opacity: 0;
    vertical-align: middle;
    background: #fff;
    border-radius: 10px;
}

.searchinputtext {
    border: none;
    outline: none;
    box-shadow: none;
    appearance: none;
    -webkit-appearance: none;
    box-sizing: border-box;
    flex: 1 1 auto;
    min-width: 0;
    height: calc(100% - 6px);
    margin: 3px 0;
    background: transparent;
    padding: 0 4px 0 10px;
}

/* "x" clear button - only shown once there's text, via :placeholder-shown (needs the placeholder attribute).
   No background of its own - it sits on .searchinputwrap's background so it reads as part of the same box. */
.searchclearbtn {
    display: none;
    flex: 0 0 auto;
    cursor: pointer;
    font-size: 16px;
    line-height: 1;
    color: var(--st-text-muted, #888);
    padding: 0 8px;
    user-select: none;
}

.searchclearbtn:hover {
    color: var(--st-text-body, #333);
}

.searchinputtext:not(:placeholder-shown) ~ .searchclearbtn {
    display: inline-block;
}


/* jQuery will search for this class, then set background color to signify that it's selected */
.searchableitem {
    /*color: black !important;*/
    /*background-color: lightgreen !important;*/
}

/* Signify that an item is selected */
.searchselected {
    color: white !important;
    background-color: var(--st-text-search-sel) !important;
}

/* The current search item, F3 to select next */
.searchcurrent {
    color: black !important;
    background-color: var(--st-text-search-cur) !important;
}


/* Go up each parent until a searchable div is found, then search for searchableitem class */
.searchablediv {
}



/* ------------------------------------------------------- */
/* Standard Time toolbar styles                            */
/* ------------------------------------------------------- */

/* ------------------------------------------------------- */
/* Toolbar area above content                              */
/* ------------------------------------------------------- */
.toolbarheadercolor {
    background-color: var(--st-bg-toolbar);
}

/* ------------------------------------------------------- */
/* Toolbar area above views (grids, charts, etc)           */
/* ------------------------------------------------------- */
.maincontenttoolbar {
    height: 4%;
    min-height: 24px;
    width: 100%;
    font-size: 12pt;
    background-color: var(--st-bg-body);
}


.toolbarbutton16 {
    width: 16px !important;
    height: 16px !important;
    border: none !important;
    background-size: contain !important;
    transition-duration: 0.3s;
}

.toolbarbutton20 {
    width: 20px !important;
    height: 20px !important;
    border: none !important;
    background-size: contain !important;
    transition-duration: 0.3s;
}

.toolbarbutton24 {
    width: 24px !important;
    height: 24px !important;
    border: none !important;
    background-size: contain !important;
    transition-duration: 0.3s;
}

.toolbarbutton32 {
    width: 32px !important;
    height: 32px !important;
    border: none !important;
    background-size: contain !important;
    transition-duration: 0.3s;
}

.toolbarbutton48 {
    width: 48px !important;
    height: 48px !important;
    border: none !important;
    background-size: contain !important;
    transition-duration: 0.3s;
}




.toolbarbutton24:hover {
    /*background-size: 105% !important;*/
    transform: scale(1.1) !important;
}

.toolbarbutton16:hover {
    /*background-size: 105% !important;*/
    transform: scale(1.1) !important;
}


/* ------------------------------------------------------- */
/* Auto-filter indicator (grid/report toolbars)             */
/* ------------------------------------------------------- */
.st-autofilter-label {
    color: var(--st-text-autofilter);
    margin-right: 10px;
}

.st-autofilter-glyph {
    width: 16px !important;
    height: 16px !important;
    vertical-align: middle;
    margin-right: 4px;
    animation: st-autofilter-flash 0.6s ease-out 1;
}

@keyframes st-autofilter-flash {
    0%   { opacity: 0; transform: scale(0.4); }
    35%  { opacity: 1; transform: scale(1.3); }
    60%  { transform: scale(0.9); }
    100% { opacity: 1; transform: scale(1); }
}



.homeiconbutton {
    font-size: 0.75vw !important;
    /*line-height: 90% !important;*/
    height: 100%;
    width: 100%;
    border: none !important;
    transition-duration: 0.1s;
    background-size: contain !important;
    background-position-y: 10% !important;
    display: inline-flex;
    align-items: flex-end;
    justify-content: center;
    /*-webkit-text-stroke: 5px black;*/
    text-shadow: -1px -1px 0px white, 1px -1px 0px white, -1px 1px 0px white, 1px 1px 0px white;
    -webkit-print-color-adjust: exact;
}

.smallapphomeicon {
    background-position-y: 50% !important;
    font-size: 2vw !important;
}


/* Lift + shadow + accent underline on hover */
.homeiconbutton {
    position: relative;
    overflow: hidden;
    transition: transform 150ms ease-out,
                box-shadow 150ms ease-out,
                background-color 150ms ease-out;
}
.homeiconbutton:hover {
    transform: translateY(-3px) scale(1.07);
    box-shadow: 0 6px 18px color-mix(in srgb, var(--st-accent, #0d6efd) 20%, transparent);
    background-color: color-mix(in srgb, var(--st-accent, #0d6efd) 9%, transparent) !important;
    border-radius: 10px;
}
.homeiconbutton::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--st-accent, #0d6efd);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 150ms ease-out;
    border-radius: 0 0 4px 4px;
}
.homeiconbutton:hover::after {
    transform: scaleX(1);
}

.ten-column-grid-container {
    display: grid;
    grid-template-columns: 9% 9% 9% 9% 9% 9% 9% 9% 9% 9%;
    gap: 1%;
    padding: 0px 10px 20px 10px;
    width: 100%;
    height: 95%;
}

.five-column-grid-container {
    display: grid;
    grid-template-columns: 19% 19% 19% 19% 19%;
    gap: 1%;
    padding: 10px;
    width: 100%;
    height: 90%;
}

.centered-icon-grid-container {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(25%, 1fr));
    gap: 1%;
    padding: 0px 10px 20px 10px;
    width: 100%;
    height: 95%;
}

.homeiconbuttonrow {
    display: flex;
    flex-direction: row;
    padding-left: 10px;
    padding-right: 10px;
}

/* ---- Home icon layout: Cards ---- */
.icon-cards-container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    padding: 12px;
    align-content: start;
}
.icon-card {
    border: 1px solid color-mix(in srgb, var(--st-accent, #0d6efd) 18%, transparent);
    border-radius: 6px;
    padding: 10px 12px;
    background: color-mix(in srgb, var(--st-accent, #0d6efd) 5%, transparent);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
    transition: border-color 150ms ease-out, box-shadow 150ms ease-out;
    will-change: transform;
    position: relative;
}
@property --card-beam1-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}
@property --card-beam2-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}
/* Shared beam style — masked to border strip only */
.icon-card::before,
.icon-card::after,
.icon-list-section::before,
.icon-list-section::after {
    content: "";
    position: absolute;
    inset: -1px;
    border-radius: 7px;
    padding: 2px;
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    opacity: 0;
    pointer-events: none;
    z-index: 1;
}
/* Beam 1 — clockwise down the right side */
.icon-card::before,
.icon-list-section::before {
    background: conic-gradient(from var(--card-beam1-angle),
        white 0%,
        var(--st-accent, #0d6efd) 3%,
        color-mix(in srgb, var(--st-accent, #0d6efd) 55%, transparent) 10%,
        color-mix(in srgb, var(--st-accent, #0d6efd) 15%, transparent) 22%,
        transparent 28%,
        transparent 100%);
}
/* Beam 2 — counter-clockwise down the left side (angle decreases 0 → -180) */
.icon-card::after,
.icon-list-section::after {
    background: conic-gradient(from var(--card-beam2-angle),
        white 0%,
        var(--st-accent, #0d6efd) 3%,
        color-mix(in srgb, var(--st-accent, #0d6efd) 55%, transparent) 10%,
        color-mix(in srgb, var(--st-accent, #0d6efd) 15%, transparent) 22%,
        transparent 28%,
        transparent 100%);
}
@keyframes card-laser-beam1 {
    from { --card-beam1-angle: 0deg;    opacity: 1; }
    95%  {                              opacity: 1; }
    to   { --card-beam1-angle: 180deg;  opacity: 0; }
}
@keyframes card-laser-beam2 {
    from { --card-beam2-angle: 0deg;    opacity: 1; }
    95%  {                              opacity: 1; }
    to   { --card-beam2-angle: -180deg; opacity: 0; }
}
.icon-card:has(.iconcardwrap:hover)::before,
.icon-list-section:has(.iconlistwrap:hover)::before {
    animation: card-laser-beam1 0.3s linear 1 forwards;
}
.icon-card:has(.iconcardwrap:hover)::after,
.icon-list-section:has(.iconlistwrap:hover)::after {
    animation: card-laser-beam2 0.3s linear 1 forwards;
}
.icon-card:has(.iconcardwrap:hover),
.icon-list-section:has(.iconlistwrap:hover) {
    border-color: var(--st-accent, #0d6efd);
    box-shadow: 0 4px 14px color-mix(in srgb, var(--st-accent, #0d6efd) 12%, transparent);
}
.icon-card-title {
    font-size: calc(7pt + 0.2vw);
    font-weight: bold;
    color: var(--st-text-muted, #666);
    margin-bottom: 8px;
    padding-bottom: 4px;
    border-bottom: 1px solid var(--st-border-color, #eee);
}
.icon-card-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

/* ---- Home icon layout: List ---- */
.icon-list-container {
    columns: 2;
    column-gap: 32px;
    padding: 12px;
}
.icon-list-section {
    break-inside: avoid;
    margin-bottom: 16px;
}
.icon-list-header {
    font-size: calc(7pt + 0.2vw);
    font-weight: bold;
    color: var(--st-text-muted, #666);
    margin-bottom: 4px;
    padding-bottom: 2px;
    border-bottom: 1px solid var(--st-border-color, #eee);
}



/* Cards — icon stacked above label chip, fixed width so buttons tile evenly */
/* Wrapper div so SetupElementImagesInDivByParent can recurse in and set the <img> src */
.iconcardwrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    width: 84px;
    padding: 4px;
    cursor: pointer;
    border-radius: 3px;
    text-align: center;
    font-size: calc(7pt + 0.2vw);
    color: var(--st-text-body, inherit);
    position: relative;
    overflow: hidden;
    transition: transform 150ms ease-out,
                box-shadow 150ms ease-out,
                background-color 150ms ease-out;
}
.iconcardwrap:hover {
    transform: translateY(-3px) scale(1.07);
    box-shadow: 0 6px 18px color-mix(in srgb, var(--st-accent, #0d6efd) 20%, transparent);
    background-color: color-mix(in srgb, var(--st-accent, #0d6efd) 9%, transparent);
    border-radius: 10px;
}
.iconcardwrap::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--st-accent, #0d6efd);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 150ms ease-out;
    border-radius: 0 0 4px 4px;
}
.iconcardwrap:hover::after {
    transform: scaleX(1);
}
.iconcardimg {
    width: 64px;
    height: 64px;
    display: block;
}
.iconcardlabel {
    display: block;
    background: color-mix(in srgb, var(--st-accent, #0d6efd) 12%, transparent);
    color: var(--st-accent, #0d6efd);
    border-radius: 4px;
    padding: 2px 5px;
    line-height: 1.3;
    width: 100%;
    box-sizing: border-box;
    transition: background 150ms ease-out;
}
/* List — section container */
.icon-list-section {
    background: color-mix(in srgb, var(--st-accent, #0d6efd) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--st-accent, #0d6efd) 18%, transparent);
    border-radius: 6px;
    padding: 6px 8px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
    transition: border-color 150ms ease-out, box-shadow 150ms ease-out;
    will-change: transform;
    position: relative;
}
/* List — compact icon+text rows */
.iconlistwrap {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    padding: 3px 4px;
    cursor: pointer;
    border-radius: 3px;
    font-size: calc(7pt + 0.15vw);
    color: var(--st-text-body, inherit);
    transition: background 150ms ease-out;
}
.iconlistwrap:hover {
    background: var(--st-grid-hover-bg, rgba(0,0,0,0.05));
    color: var(--st-grid-hover-text, inherit);
}
.iconlistimg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

/* ---- Home icon layout: Planetary ---- */
@property --planet-beam1-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}
@property --planet-beam2-angle {
    syntax: '<angle>';
    initial-value: 0deg;
    inherits: false;
}
.planet-beam-ring {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    pointer-events: none;
}
.planet-beam-ring::before,
.planet-beam-ring::after {
    content: "";
    position: absolute;
    inset: -1px;
    border-radius: 50%;
    padding: 2px;
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    opacity: 0;
    pointer-events: none;
    z-index: 2;
}
.planet-beam-ring::before {
    background: conic-gradient(from var(--planet-beam1-angle),
        white 0%,
        var(--st-accent, #0d6efd) 3%,
        color-mix(in srgb, var(--st-accent, #0d6efd) 55%, transparent) 10%,
        color-mix(in srgb, var(--st-accent, #0d6efd) 15%, transparent) 22%,
        transparent 28%,
        transparent 100%);
}
.planet-beam-ring::after {
    background: conic-gradient(from var(--planet-beam2-angle),
        white 0%,
        var(--st-accent, #0d6efd) 3%,
        color-mix(in srgb, var(--st-accent, #0d6efd) 55%, transparent) 10%,
        color-mix(in srgb, var(--st-accent, #0d6efd) 15%, transparent) 22%,
        transparent 28%,
        transparent 100%);
}
@keyframes planet-laser-beam1 {
    from { --planet-beam1-angle: 0deg;    opacity: 1; }
    95%  {                                opacity: 1; }
    to   { --planet-beam1-angle: 180deg;  opacity: 0; }
}
@keyframes planet-laser-beam2 {
    from { --planet-beam2-angle: 0deg;    opacity: 1; }
    95%  {                                opacity: 1; }
    to   { --planet-beam2-angle: -180deg; opacity: 0; }
}
.planet:has(.planet-icon:hover) .planet-beam-ring::before {
    animation: planet-laser-beam1 0.3s linear 1 forwards;
}
.planet:has(.planet-icon:hover) .planet-beam-ring::after {
    animation: planet-laser-beam2 0.3s linear 1 forwards;
}
/*
 * Each .planet is a fixed 220x220px square. Icons are absolutely positioned
 * at top:50% left:50% (the center), then pushed to their orbit position via
 * an inline transform: rotate(Adeg) translate(82px) rotate(-Adeg).
 * The negative counter-rotation keeps the icon image upright.
 * The 48x48px button box is offset by -24px so its center sits on the orbit ring.
 * Geometry: orbit 82 + half-button 24 = 106px < container half 110px (4px clearance).
 */
.planetary-container {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 20px;
    padding: 16px;
    align-content: start;
}
.planet {
    position: relative;
    width: 220px;
    height: 220px;
    isolation: isolate;
}
/* Hover ring — z-index:1 keeps it above orbit icons */
.planet::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid transparent;
    pointer-events: none;
    z-index: 1;
    transition: border-color 150ms ease-out, box-shadow 150ms ease-out;
}
.planet:has(.planet-icon:hover)::before {
    border-color: color-mix(in srgb, var(--st-accent, #0d6efd) 50%, transparent);
    box-shadow: 0 0 12px color-mix(in srgb, var(--st-accent, #0d6efd) 20%, transparent);
}
/* Faint background circle — z-index:-1 sits behind all children */
.planet::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: color-mix(in srgb, var(--st-accent, #0d6efd) 5%, transparent);
    border: 1px solid color-mix(in srgb, var(--st-accent, #0d6efd) 18%, transparent);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
    pointer-events: none;
    z-index: -1;
}
@keyframes planet-core-pulse {
    0%   { transform: scale(1);   opacity: 0; }
    15%  { opacity: 0.55; }
    100% { transform: scale(2.4); opacity: 0; }
}
.planet-core {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: var(--st-accent, #0d6efd);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    font-size: calc(6pt + 0.15vw);
    font-weight: bold;
    padding: 4px;
    box-sizing: border-box;
    cursor: default;
    line-height: 1.2;
    transition: transform 250ms ease-out;
}
.planet-core:hover {
    transform: translate(-50%, -50%) scale(1.35);
}
/* Sonar pulse ring — expands from core edge and fades out */
.planet-core::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid var(--st-accent, #0d6efd);
    opacity: 0;
    pointer-events: none;
}
.planet-core:hover::after {
    animation: planet-core-pulse 1.4s ease-out 1;
}
/* Short label (default) / full label (on hover) cross-fade */
.planet-core-short,
.planet-core-full {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    text-align: center;
    line-height: 1.2;
    word-break: break-word;
    transition: opacity 200ms ease-out;
}
.planet-core-short { opacity: 1; }
.planet-core-full  { opacity: 0; font-size: calc(5pt + 0.1vw); }
.planet-core:hover .planet-core-short { opacity: 0; }
.planet-core:hover .planet-core-full  { opacity: 1; }
.planet-icon {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 56px;
    margin: -24px 0 0 -28px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 2px;
    cursor: pointer;
    border-radius: 4px;
    transition: background 150ms ease-out, box-shadow 150ms ease-out,
                translate 150ms ease-out, scale 150ms ease-out;
}
.planet-icon:hover {
    background: color-mix(in srgb, var(--st-accent, #0d6efd) 9%, transparent);
    box-shadow: 0 6px 18px color-mix(in srgb, var(--st-accent, #0d6efd) 20%, transparent);
    border-radius: 10px;
    translate: 0 -3px;
    scale: 1.07;
}
.planet-icon-img {
    width: 36px;
    height: 36px;
    display: block;
    pointer-events: none;
    flex-shrink: 0;
}
.planet-icon-label {
    font-size: 6pt;
    color: var(--st-text-body, inherit);
    text-align: center;
    line-height: 1.2;
    word-break: break-word;
    pointer-events: none;
}

/* ---- Layout toggle buttons: icon-only, 28x28 ---- */
/* AjaxSetButtonBackgroundImage always sets background-position to top center via inline style. */
/* !important overrides the inline position so the icon renders centered in the empty button. */
#divHomeLayoutButtons .btn {
    width: 28px;
    height: 28px;
    padding: 0;
    background-position: center center !important;
    background-repeat: no-repeat !important;
    background-size: 16px 16px !important;
}
#divHomeLayoutButtons .btn.active {
    background-color: var(--st-accent, #0d6efd);
    border-color: var(--st-accent, #0d6efd);
}



/* ------------------------------------------------------- */
/* StDock - vanilla JS/CSS dock layout engine styles       */
/* Replaces the Infragistics igc-dockmanager theme CSS     */
/* (standardtime-dockmanager.css)                          */
/* ------------------------------------------------------- */
/*
   Skin variables consumed (all defined in standardtime-skin-variables.css
   and overridden per skin in Content/skins/st-*.css):

     --st-dock-header-bg     chrome background (tab strips, pane headers, gaps)
     --st-dock-text          chrome text color (tabs, headers, edge tabs)
     --st-dock-border        borders between chrome and content
     --st-dock-pane-bg       pane/tab content background
     --st-dock-splitter      splitter drag bar color
     --st-dock-active-tab    selected tab / active header background
     --st-new-tab-flash      new-tab flash animation color

   Icons are drawn with CSS mask-image + background-color: currentColor so they
   always follow the skin text color. Do NOT replace them with Unicode glyphs:
   on some Windows font configurations the browser substitutes a colored icon
   font that ignores the CSS color property entirely (same problem that forced
   the StTree caret to be a CSS border-triangle).
*/


/* ------------------------------------------------------- */
/* Root and persistent chrome                               */
/* ------------------------------------------------------- */

.st-dock {
    display: flex;
    flex-direction: row;
    width: 100%;
    height: 100%;
    position: relative;
    overflow: hidden;
    background-color: var(--st-dock-header-bg);
    color: var(--st-dock-text);
    font-size: calc(8pt + 0.15vw);
}

/* Hidden parking lot for slot divs not currently shown in a pane.
   display:none (not visibility) so lazy-loader IntersectionObservers
   do not fire until the content actually appears in a pane. */
.st-dock-store {
    display: none;
}

.st-dock-frame {
    display: flex;
    flex-direction: row;
    flex: 1 1 0px;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

/* Top-level branches (one per layout.rootPane.panes[i]) - hidden until they have content */
.st-dock-branch {
    display: none;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

.st-dock-branch.st-dock-visible {
    display: flex;
    flex-direction: column;
}


/* ------------------------------------------------------- */
/* Split containers and splitters                           */
/* ------------------------------------------------------- */

.st-dock-split {
    display: flex;
    flex: 1 1 0px;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

.st-dock-split-h {
    flex-direction: row;
}

.st-dock-split-v {
    flex-direction: column;
}

.st-dock-splitter {
    flex: 0 0 8px;
    background-color: var(--st-dock-splitter);
    touch-action: none;
    z-index: 2;
}

/* Root-frame splitters are hidden until both neighbors are visible */
.st-dock-frame > .st-dock-splitter {
    display: none;
}

.st-dock-frame > .st-dock-splitter.st-dock-visible {
    display: block;
}

.st-dock-splitter-col {
    cursor: ew-resize;
    position: relative;
}

/* Centered "grabber" line hinting the vertical splitter is draggable. Absolutely
   positioned (not flex-centered) so it does not fight the .st-dock-frame > .st-dock-splitter
   display:block/none show-hide rule on root-frame splitters. */
.st-dock-splitter-col::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 2px;
    height: 88px;
    border-radius: 1px;
    background-color: color-mix(in srgb, var(--st-dock-text) 90%, transparent);
    pointer-events: none;
}

.st-dock-splitter-row {
    cursor: ns-resize;
    position: relative;
}

/* Centered horizontal "grabber" line for the horizontal splitter (mirrors the vertical
   splitter's grabber, rotated 90 degrees). Absolutely positioned, same as the column one. */
.st-dock-splitter-row::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 88px;
    height: 2px;
    border-radius: 1px;
    background-color: color-mix(in srgb, var(--st-dock-text) 90%, transparent);
    pointer-events: none;
}

.st-dock-splitter:hover {
    filter: brightness(1.25);
}

/* While dragging a splitter, keep the resize cursor everywhere and stop text selection */
body.st-dock-resizing-col {
    cursor: ew-resize !important;
    user-select: none;
}

body.st-dock-resizing-row {
    cursor: ns-resize !important;
    user-select: none;
}


/* ------------------------------------------------------- */
/* Panes (docked tool panes: Filter / Properties / Settings)*/
/* ------------------------------------------------------- */

.st-dock-pane,
.st-dock-tabgroup {
    display: flex;
    flex-direction: column;
    flex: 1 1 0px;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    background-color: var(--st-dock-pane-bg);
    border: 1px solid var(--st-dock-border);
}

/* The flyout title bar (standardtime-dockengine.js _ensureChrome) carries both
   st-dock-pane-header and st-dock-flyout-header - intentionally no separate rule below for the
   latter, the flyout header is meant to look identical to a docked pane header. */
.st-dock-pane-header {
    display: flex;
    flex-direction: row;
    align-items: center;
    /* Line the Filter/Properties column top-bars up with the document tab strip
       (.st-dock-tabstrip-top, a 39px box). Those tool columns are wrapped in
       .st-dock-pane / .st-dock-tabgroup, which carries a 1px border on ALL sides
       (the document column's .st-dock-docgroup has no border), so the wrapper's 1px
       TOP border sits above this header. 38px header + that 1px top border = 39px,
       matching the document strip; a solid 39px here made the tool top-bars read 1px
       too tall. The border-bottom mirrors the tab strip's own 1px separator. */
    flex: 0 0 38px;
    padding: 0 4px 0 8px;
    background-color: var(--st-dock-header-bg);
    color: var(--st-dock-text);
    border-bottom: 1px solid var(--st-dock-border);
    overflow: hidden;
    user-select: none;
}

.st-dock-pane-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.st-dock-header-spacer {
    flex: 1 1 0px;
}

.st-dock-pane-body {
    flex: 1 1 0px;
    min-height: 0;
    overflow: hidden;
    position: relative;
}

/* Slot divs fill their pane body */
.st-dock-pane-body > [slot],
.st-dock-flyout-body > [slot],
.st-dock-doc-body > [slot] {
    width: 100%;
    height: 100%;
}

/* In shared bodies (document host, tool tab groups) only the active slot shows */
.st-dock-doc-body > [slot],
.st-dock-pane-body > [slot] {
    display: none;
}

.st-dock-doc-body > [slot].st-dock-slot-active,
.st-dock-pane-body > [slot].st-dock-slot-active,
.st-dock-pane-body > [slot]:only-child {
    display: block;
}

.st-dock-flyout-body > [slot] {
    display: block;
}


/* ------------------------------------------------------- */
/* Document host and document tabs                          */
/* ------------------------------------------------------- */

.st-dock-dochost,
.st-dock-docgroup {
    display: flex;
    flex-direction: column;
    flex: 1 1 0px;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
}

.st-dock-tabstrip {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    flex: 0 0 30px;
    background-color: var(--st-dock-header-bg);
    border-bottom: 1px solid var(--st-dock-border);
    overflow: hidden;
    user-select: none;
}

.st-dock-tabstrip-bottom {
    border-bottom: none;
    border-top: 1px solid var(--st-dock-border);
}

/* The document tab strip (standardtime-dockengine.js _buildDocGroup) carries
   st-dock-tabstrip-top. Restore the pre-migration document-tab metrics: a ~32px tab
   with a 6px gap above. Box-sizing is border-box (Bootstrap global), so the 39px basis
   resolves to 6px padding-top + 32px stretched tab + 1px border-bottom - the same 39px
   box the tool-pane headers use. The base 30px basis (which nets 29px tabs and no top
   gap) stays in force for the bottom tool-pane strip. The visible top edge belongs on
   each TAB (see .st-dock-tab border-top), not on the strip. */
.st-dock-tabstrip-top {
    flex: 0 0 39px;
    padding-top: 6px;
}

.st-dock-tabs {
    display: flex;
    flex-direction: row;
    flex: 1 1 0px;
    min-width: 0;
    overflow-x: hidden;
    scroll-behavior: smooth;
    /* positioned so tab offsetLeft is measured against the strip (see StDock._scrollTabIntoView) */
    position: relative;
}

.st-dock-tab {
    display: flex;
    flex-direction: row;
    align-items: center;
    flex: 0 0 auto;
    max-width: 220px;
    padding: 0 6px 0 12px;
    color: var(--st-dock-text);
    background-color: transparent;
    border-right: 1px solid var(--st-dock-border);
    /* Each tab gets its own 1px dark top edge, matching border-right, so the tab reads
       as a subtly outlined cell - the pre-migration Infragistics look. Same
       var(--st-dock-border) as the sides; spans only the tabs, not the full strip. */
    border-top: 1px solid var(--st-dock-border);
    cursor: pointer;
    white-space: nowrap;
}

.st-dock-tab:hover {
    background-color: color-mix(in srgb, var(--st-dock-active-tab) 45%, transparent);
}

.st-dock-tab.st-active {
    background-color: var(--st-dock-active-tab);
    /* Fat accent highlight along the bottom of the selected tab (pre-migration look).
       An inset box-shadow draws it over the tab bg without touching the box model, so
       the selected tab's height and label position stay identical to inactive tabs. */
    box-shadow: inset 0 -3px 0 0 var(--st-accent);
    /* Selected tab text takes on the accent, lightened toward white so it stays legible
       on the dark active-tab background and reads clearly different from the white
       inactive-tab text. */
    color: color-mix(in srgb, var(--st-accent) 70%, white);
}

.st-dock-tab.st-dock-tab-dragging {
    opacity: 0.65;
    cursor: grabbing;
}

/* While a tab reorder drag is in progress, force the grab cursor everywhere (mirrors the
   splitter body-cursor pattern). grabbing - a move/reorder hint, NOT a resize cursor - is
   the right affordance for dragging a tab. */
body.st-dock-dragging-tab,
body.st-dock-dragging-tab * {
    cursor: grabbing !important;
    user-select: none;
}

.st-dock-tab-label {
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
}

.st-dock-doc-body {
    flex: 1 1 0px;
    min-height: 0;
    overflow: hidden;
    position: relative;
    background-color: var(--st-dock-pane-bg);
}

/* New-tab flash - keyframes live here (no shadow DOM anymore, so ordinary page CSS reaches the tab) */
@keyframes st-dock-tab-pulse {
    0%   { background-color: var(--st-dock-active-tab); }
    30%  { background-color: var(--st-new-tab-flash, yellow); }
    100% { background-color: var(--st-dock-active-tab); }
}

.st-dock-tab.st-dock-tab-flash {
    animation: st-dock-tab-pulse 1s ease-out;
}


/* ------------------------------------------------------- */
/* Buttons and icons (CSS mask, colored by currentColor)    */
/* ------------------------------------------------------- */

.st-dock-btn {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin-left: 2px;
    padding: 0;
    border: none;
    border-radius: 3px;
    background-color: transparent;
    color: inherit;
    cursor: pointer;
    position: relative;
}

.st-dock-btn:hover {
    background-color: color-mix(in srgb, currentColor 22%, transparent);
}

.st-dock-btn::before {
    content: "";
    position: absolute;
    inset: 3px;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
}

/* X (close) - two crossing strokes */
.st-dock-btn-close::before,
.st-dock-tab-close::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4 L12 12 M12 4 L4 12' stroke='black' stroke-width='1.8' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4 L12 12 M12 4 L4 12' stroke='black' stroke-width='1.8' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
}

/* Pushpin - head, needle, base line */
.st-dock-btn-pin::before,
.st-dock-btn-unpin::before {
    /* Enlarge the pushpin: the shared .st-dock-btn::before inset is 3px (14px mask box);
       the pin shape only fills part of its viewBox so it read small. A 1px inset grows the
       mask box to 18px. Scoped to pin/unpin only - the pane-header close X keeps 3px. */
    inset: 1px;
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 2 L10 2 L10 7 L12 9 L4 9 L6 7 Z M7.3 9 L8.7 9 L8 14 Z' fill='black'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 2 L10 2 L10 7 L12 9 L4 9 L6 7 Z M7.3 9 L8.7 9 L8 14 Z' fill='black'/%3E%3C/svg%3E");
}

/* Docked pane shows the pin rotated (VS convention: click to unpin / lay the pin down) */
.st-dock-btn-unpin::before {
    transform: rotate(45deg);
}

/* Tab close X - sits inside the tab (sized to match the pre-migration Infragistics X) */
.st-dock-tab-close {
    width: 18px;
    height: 18px;
    margin-left: 6px;
    border: none;
    border-radius: 3px;
    padding: 0;
    background-color: transparent;
    color: inherit;
    cursor: pointer;
    position: relative;
    flex: 0 0 auto;
}

.st-dock-tab-close:hover {
    background-color: color-mix(in srgb, currentColor 22%, transparent);
}

.st-dock-tab-close::before {
    content: "";
    position: absolute;
    inset: 1px;
    background-color: currentColor;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
    /* Tab-close X spans a wider slice of the viewBox (3..13 of 16) than the shared
       .st-dock-btn-close X above (4..12), so the visible glyph reads ~10-11px to match
       the larger, thinner pre-migration Infragistics tab close X. Scoped to the tab
       close only - the pane-header close button keeps the shared narrower X. */
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 3 L13 13 M13 3 L3 13' stroke='black' stroke-width='1.6' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 3 L13 13 M13 3 L3 13' stroke='black' stroke-width='1.6' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
}

/* Overflow ("all tabs") chevron button - hidden until tabs overflow */
.st-dock-tab-more {
    display: none;
    align-self: center;
}

.st-dock-tab-more.st-dock-visible {
    display: block;
}

.st-dock-tab-more::before {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 6 L8 11 L13 6' stroke='black' stroke-width='2' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 6 L8 11 L13 6' stroke='black' stroke-width='2' stroke-linecap='round' fill='none'/%3E%3C/svg%3E");
}


/* ------------------------------------------------------- */
/* Tab overflow menu                                        */
/* ------------------------------------------------------- */

.st-dock-tab-menu {
    position: absolute;
    z-index: 60;
    min-width: 180px;
    max-width: 320px;
    max-height: 60%;
    overflow-y: auto;
    background-color: var(--st-dock-pane-bg);
    color: var(--st-text-body, #000);
    border: 1px solid var(--st-dock-border);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}

.st-dock-tab-menu-item {
    padding: 6px 12px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.st-dock-tab-menu-item:hover {
    background-color: color-mix(in srgb, var(--st-dock-active-tab) 30%, transparent);
}

.st-dock-tab-menu-item.st-active {
    background-color: var(--st-dock-active-tab);
    color: var(--st-dock-text);
}


/* ------------------------------------------------------- */
/* Edge strips (unpinned pane tabs) and flyout              */
/* ------------------------------------------------------- */

.st-dock-edge {
    display: none;
    flex-direction: column;
    flex: 0 0 38px;
    background-color: var(--st-dock-header-bg);
    overflow: hidden;
    user-select: none;
}

.st-dock-edge.st-dock-visible {
    display: flex;
}

.st-dock-edge-left {
    border-right: 1px solid var(--st-dock-border);
}

.st-dock-edge-right {
    border-left: 1px solid var(--st-dock-border);
}

.st-dock-edge-tab {
    writing-mode: vertical-rl;
    /* Horizontal padding centers the vertical text in the ~38px-wide strip (physical
       left/right padding regardless of writing-mode). */
    padding: 12px 11px;
    margin: 2px 0;
    color: var(--st-dock-text);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-height: 200px;
}

.st-dock-edge-tab:hover {
    background-color: color-mix(in srgb, var(--st-dock-active-tab) 45%, transparent);
}

.st-dock-edge-tab.st-active {
    background-color: var(--st-dock-active-tab);
}

.st-dock-flyout {
    display: none;
    flex-direction: column;
    position: absolute;
    top: 0;
    bottom: 0;
    z-index: 50;
    background-color: var(--st-dock-pane-bg);
    border: 1px solid var(--st-dock-border);
    overflow: hidden;
}

.st-dock-flyout.st-dock-open {
    display: flex;
}

.st-dock-flyout-left {
    box-shadow: 6px 0 14px rgba(0, 0, 0, 0.38);
}

.st-dock-flyout-right {
    box-shadow: -6px 0 14px rgba(0, 0, 0, 0.38);
}

.st-dock-flyout-body {
    flex: 1 1 0px;
    min-height: 0;
    overflow: hidden;
    position: relative;
}


/* ------------------------------------------------------- */
/* Slot content classes (carried over unchanged from        */
/* standardtime-dockmanager.css - referenced by             */
/* DockManagerPartialView.cshtml and                        */
/* AddNewDockManagerSlotContentDiv)                         */
/* ------------------------------------------------------- */

.dockManagerContent {
    padding: 0.0rem;
    background-color: var(--st-bg-body);
    color: var(--st-text-body);
    height: 100%;
    overflow: hidden;
}

.dockManagerPartialView {
    height: 100%;
    overflow: hidden;
    background-color: var(--st-bg-body);
    color: var(--st-text-body);
    font-size: calc(8pt + 0.25vw);
}


/* ------------------------------------------------------- */
/* Standard Time Gantt chart styles                        */
/* ------------------------------------------------------- */

/* IG grid sets padding:4px and vertical-align:middle on all <td> cells.
   For gantt cells that combination offsets bars ~8px down (4px padding +
   4px centering when row height > ganttcelldiv height). Override both. */
td:has(.ganttcelldiv) {
    padding: 2px 0 0 0 !important;
    vertical-align: top !important;
}

.ganttitem {
    /*Used to find all gantt items on the entire page used*/
    /*Put actual styles in other classes*/
}

/* ------------------------------------------------------- */
/* Plain Gantt bar                                         */
/* ------------------------------------------------------- */
.ganttbar {
    background-color: var(--st-gantt-bar-bg);
    height: 10px;
    border-radius: 3px;
    cursor: ew-resize;
    transform: translateY(50%);
    -webkit-print-color-adjust: exact;
    color: var(--st-text-body);
    font-size: 8pt;
    font-weight: 700;
    vertical-align: top;
    text-align: center;
    white-space: nowrap;
}

/* Enlarge button image slightly during hover*/
.ganttbar:hover {
    border-width:1px;
    border-style:dotted;
    border-color: var(--st-text-body);
    /*background-color: #ebebff !important;*/
    /*transform: translateY(50%) scale(1.1);*/
}


/* ------------------------------------------------------- */
/* Critical path bar classes                               */
/* ------------------------------------------------------- */
.ganttbar-critical {
    background: linear-gradient(to right,
        var(--st-gantt-critical-bar-start),
        var(--st-gantt-critical-bar-end)) !important;
    color: #ffffff;
}

.ganttbar-noncritical {
    background: linear-gradient(to right,
        var(--st-gantt-noncritical-bar-start),
        var(--st-gantt-noncritical-bar-end)) !important;
    color: #ffffff;
}

.ganttsummarybar.ganttbar-noncritical {
    background: var(--st-gantt-summary-bg) !important;
}


/* ------------------------------------------------------- */
/* Float (slack) indicator bar                             */
/* ------------------------------------------------------- */
.ganttfloatbar {
    background-color: var(--st-gantt-float-bar-bg);
    border: 1.5px dashed var(--st-gantt-float-bar-stroke);
    height: 10px;
    border-radius: 2px;
    position: relative;
    transform: translateY(50%);
    -webkit-print-color-adjust: exact;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.ganttfloatbar-label {
    color: var(--st-gantt-float-bar-text);
    font-size: 9px;
    font-weight: 400;
    white-space: nowrap;
    pointer-events: none;
}


/* ------------------------------------------------------- */
/* Baseline comparison ghost bar                           */
/* ------------------------------------------------------- */
.ganttbar-baseline {
    height: 4px;
    background-color: var(--st-gantt-baseline-bar);
    border: 1px solid var(--st-gantt-baseline-bar);
    border-radius: 2px;
    pointer-events: none;
    opacity: 0.7;
    -webkit-print-color-adjust: exact;
}

/* Baseline milestone ghost diamond — outline only, no fill */
.ganttbarmilestone-baseline {
    height: 12px;
    width: 12px;
    border-radius: 2px;
    transform: translateY(50%) rotate(45deg);
    border: 2px solid var(--st-gantt-baseline-bar);
    background-color: transparent;
    pointer-events: none;
    opacity: 0.7;
}


/* ------------------------------------------------------- */
/* Weekend shading — scale header cells (Days scale only)  */
/* ------------------------------------------------------- */
/* Cell rows use a CSS repeating-linear-gradient set in JS (no extra DOM nodes).
   Scale header cells use a CSS class because they are individual divs. */
.ganttscalecell-weekend {
    background-color: var(--st-gantt-weekend-scale-bg);
}


/* ------------------------------------------------------- */
/* Today marker line                                       */
/* ------------------------------------------------------- */
.gantttoday {
    border-right: 2px solid var(--st-gantt-today-color);
    height: 100%;
    width: 0;
    pointer-events: none;
    -webkit-print-color-adjust: exact;
}

.ganttscalecell-today {
    background-color: var(--st-gantt-today-color);
    color: #ffffff;
    font-weight: bold;
}

.gantttoday-label {
    position: absolute;
    top: 1px;
    left: 3px;
    display: inline-flex;
    align-items: center;
    height: 11px;
    font-size: 7px;
    font-weight: bold;
    color: #ffffff;
    background-color: var(--st-gantt-today-color);
    padding: 0 3px;
    border-radius: 3px;
    white-space: nowrap;
    pointer-events: none;
    line-height: 1;
    -webkit-print-color-adjust: exact;
}


/* ------------------------------------------------------- */
/* Summary Gantt bar                                       */
/* ------------------------------------------------------- */
.ganttsummarybar {
    background-color: var(--st-gantt-summary-bg);
    height: 12px;
    cursor: ew-resize;
    transform: translateY(50%);
    -webkit-print-color-adjust: exact;
    color: var(--st-text-body);
    font-size: 8pt;
    font-weight: 700;
    vertical-align: top;
    text-align: center;
    white-space: nowrap;
}

.ganttsummarybar-sub {
    height: 10px;
}

/* Enlarge button image slightly during hover*/
.ganttsummarybar:hover {
    border-width:1px;
    border-style:dotted;
    border-color: var(--st-text-body);
    /*background-color: #FFD580 !important;*/
    /*transform: translateY(50%) scale(1.1);*/
}

.ganttpercentbar {
    position: absolute;
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    height: 3px;
    background-color: var(--st-gantt-percent-bg);
    border-radius: 3px;
    pointer-events: none;
    -webkit-print-color-adjust: exact;
}

.gantt-bar-resize-handle {
    position: absolute;
    top: 0;
    width: 6px;
    height: 100%;
    cursor: ew-resize;
    z-index: 1;
}



/* ------------------------------------------------------- */
/* Milestone Gantt diamond                                 */
/* ------------------------------------------------------- */
.ganttmilestonediamond {
    width: 0;
    height: 0;
    border: 7px solid transparent;
    border-bottom-color: var(--st-gantt-milestone-color);
    position: relative;
    top: -7px;
    transform: translateY(10%);
    -webkit-print-color-adjust: exact;
}
.ganttmilestonediamond:after {
    content: '';
    position: absolute;
    left: -7px;
    top: 7px;
    width: 0;
    height: 0;
    border: 7px solid transparent;
    border-top-color: var(--st-gantt-milestone-color);
}

.ganttbarmilestone {
    border-width: 1px;
    border-style: solid;
    border-color: var(--st-gantt-milestone-color);
    background-color: var(--st-gantt-milestone-bg);
    height: 12px;
    width: 12px;
    border-radius: 2px;
    cursor: ew-resize;
    transform: translateY(50%) rotate(45deg);
    -webkit-print-color-adjust: exact;
    color: var(--st-text-body);
    font-size: 8pt;
    font-weight: 700;
    vertical-align: top;
    text-align: center;
    white-space: nowrap;
}

.ganttbarmilestone:hover {
    border-width: 2px;
    border-style: dotted;
    border-color: var(--st-text-body);
    /*background-color: #FFD580 !important;*/
    /*transform: translateY(50%) scale(1.1);*/
}


/* ------------------------------------------------------- */
/* Gantt Scale                                             */
/* ------------------------------------------------------- */
.ganttscale {
}

.ganttscalecell {
    /*color: black;*/
    /*background-color: white;*/
    font-size: calc(4pt + 0.25vw);
    border-right: solid;
    border-width: 1px;
    border-collapse: collapse;
    border-color: var(--st-gantt-scale-border);
    text-align: center;
    overflow: hidden;
}

.ganttgridline {
    border-right: solid;
    border-width: 1px;
    border-collapse: collapse;
    border-color: var(--st-gantt-gridline);
    -webkit-print-color-adjust: exact;
}

.ganttscaleheadercell {
    font-size: calc(4pt + 0.25vw);
    border-right: solid;
    border-width: 1px;
    border-collapse: collapse;
    border-color: var(--st-gantt-scale-border);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    overflow: hidden;
    -webkit-print-color-adjust: exact;
}

.ganttscalerowcell {
    font-size: calc(4pt + 0.25vw);
    border-right: solid;
    border-width: 1px;
    border-collapse: collapse;
    border-color: var(--st-gantt-gridline);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    overflow: hidden;
    -webkit-print-color-adjust: exact;
}

.ganttsummarytriangle {
    position: fixed;
    width: 0;
    height: 0;
    padding: 0px;
    margin: 0px;
    top: 0px;
    border: 7px solid transparent;
    border-top: 15px solid var(--st-gantt-summary-triangle);
    border-bottom: 0;
    transform: translateY(20%);
    -webkit-print-color-adjust: exact;
}

/* ------------------------------------------------------- */
/* Summary bar child milestone diamond                     */
/* ------------------------------------------------------- */
.gantt-summary-milestone {
    background-color: #ffffff;
    border: 1.5px solid #000000;
    height: 8px;
    width: 8px;
    border-radius: 1px;
    transform: rotate(45deg);
    cursor: default;
    -webkit-print-color-adjust: exact;
}




/* ------------------------------------------------------- */
/* Plain Gantt bar while dragging                          */
/* ------------------------------------------------------- */
.ganttbardragging {
    background-color: var(--st-gantt-drag-bg);
    color: var(--st-accent-text);
    font-size: 8pt;
    font-weight: 700;
    vertical-align: top;
    text-align: center;
    white-space: nowrap;
    height: 10px;
    border-radius: 3px;
    cursor: ew-resize;
    -webkit-print-color-adjust: exact;
}

.ganttlinkline {
    stroke: var(--st-gantt-link-color);
    stroke-width: 4px;
    opacity: 50%;
    fill: none;
    animation: dash 1s linear forwards;
    stroke-dasharray: 200;
    stroke-dashoffset: 200;
}

.ganttlinkline-critical {
    stroke: var(--st-gantt-critical-arrow);
    opacity: 0.75;
}

.ganttlinkline-noncritical {
    stroke: var(--st-gantt-noncritical-arrow);
    opacity: 0.5;
}

/* Applied to predecessor and successor bar divs while their connecting arrow is hovered. */
/* outline (not box-shadow) so the ring is not clipped by ganttcelldiv's overflow:hidden. */
.ganttbar-link-highlight {
    outline: 2px solid var(--st-accent);
    outline-offset: 1px;
    position: relative;
    z-index: 5;
}

/* Applied to the visible SVG path while its hit area is hovered. */
.ganttlinkline-highlight {
    opacity: 1 !important;
    stroke-width: 6px !important;
}

.fade-in {
    opacity: 1;
    animation-name: fadeInOpacity;
    animation-iteration-count: 1;
    animation-timing-function: ease-in;
    animation-duration: 2s;
}

@keyframes fadeInOpacity {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes dash {
    to {
        stroke-dashoffset: 0;
    }
}


/* ------------------------------------------------------- */
/* Gantt scale hover navigation buttons                    */
/* ------------------------------------------------------- */
.gantt-nav-left,
.gantt-nav-right {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    gap: 1px;
    z-index: 10;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s;
}

.gantt-nav-left  { left: 2px; }
/* left:100% places the group's left edge at the <th> right boundary;
   translateX(-100%-2px) pulls it back by its own width + margin — no JS needed. */
.gantt-nav-right { left: 100%; transform: translate(calc(-100% - 2px), -50%); }

th:has(.ganttscale):hover .gantt-nav-left,
th:has(.ganttscale):hover .gantt-nav-right,
.gantt-nav-left:hover,
.gantt-nav-right:hover {
    opacity: 1;
    pointer-events: auto;
}

.gantt-nav-btn {
    background: rgba(255, 255, 255, 0.85);
    color: #333333;
    border: 1px solid rgba(0, 0, 0, 0.25);
    border-radius: 2px;
    padding: 0 4px;
    font-size: 16px;
    font-weight: bold;
    line-height: 1;
    cursor: pointer;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.gantt-nav-btn-wide {
    width: 34px;
}

.gantt-nav-circle {
    display: inline-block;
    width: 12px;
    height: 12px;
    background: currentColor;
    border-radius: 50%;
    flex-shrink: 0;
}

.gantt-nav-glyph {
    display: flex;
    align-items: center;
    gap: 1px;
    line-height: 1;
}

.gantt-nav-glyph svg {
    width: 20px;
    height: 20px;
    display: block;
}

.gantt-nav-glyph-flip {
    transform: scaleX(-1);
}

.gantt-nav-btn:hover {
    background: rgba(0, 0, 0, 0.55);
    color: #ffffff;
    border-color: rgba(0, 0, 0, 0.4);
}

.gantt-zoom-label {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 9px;
    background: rgba(255, 255, 255, 0.70);
    color: #666666;
    border: 1px solid rgba(0, 0, 0, 0.15);
    border-radius: 3px;
    padding: 1px 5px;
    pointer-events: none;
    white-space: nowrap;
    -webkit-print-color-adjust: exact;
}




.MiniHtmlTreeView {
    list-style-type: none;
    margin: 0;
    padding: 0;
}


.MiniHtmlTreeViewCaret {
    cursor: pointer;
    -webkit-user-select: none; /* Safari 3.1+ */
    -moz-user-select: none; /* Firefox 2+ */
    -ms-user-select: none; /* IE 10+ */
    user-select: none;
}

.MiniHtmlTreeViewCaret::before {
    content: "\25B6";
    color: gray;
    display: inline-block;
    margin-right: 6px;
}

.MiniHtmlTreeViewCaretDown::before {
    -ms-transform: rotate(90deg); /* IE 9 */
    -webkit-transform: rotate(90deg); /* Safari */
    transform: rotate(90deg);
}

.MiniHtmlTreeViewNested {
    display: none;
    list-style-type: none;
}

.MiniHtmlTreeViewActive {
    display: block;
    list-style-type: none;
}

.MiniHtmlTreeViewChild {
    -webkit-user-select: none; /* Safari 3.1+ */
    -moz-user-select: none; /* Firefox 2+ */
    -ms-user-select: none; /* IE 10+ */
    user-select: none;
}

.MiniHtmlTreeViewNoCaret {
    cursor: pointer;
    -webkit-user-select: none; /* Safari 3.1+ */
    -moz-user-select: none; /* Firefox 2+ */
    -ms-user-select: none; /* IE 10+ */
    user-select: none;
}

.MiniHtmlTreeViewNoCaret::before {
    content: " ";
    color: gray;
    display: inline-block;
    margin-right: 6px;
}

