/*
	EIC Project Dashboard

	Renders inside a Hamilton SiteManager page, within <div class="typography">.
	Everything is namespaced under .eic-app; nothing resets or restyles site chrome.

	Two things about the host page drive most of the rules below.

	1. FONTS. site.css sets `body { font-family: "miller-text", serif }`. Inherited
	   into a data grid that gives you a book serif with OLD-STYLE (lowercase)
	   figures, which is unreadable in columns of dates and day counts. Hamilton's
	   own sans is Mallory Compact (Book/Medium/Bold), already loaded on every page
	   by /assets/fonts/fonts.css, so the app uses that plus lining tabular figures.

	   Mallory Book/Medium/Bold are three separate FAMILIES, each registered at
	   weight 400 - so weight is changed by switching family, and font-weight stays
	   400 to stop the browser synthesizing fake bold on an already-bold face.

	2. SPECIFICITY. `.typography a` is (0,1,1) and underlines every link. A bare
	   `.eic-app a` is also (0,1,1) and would only win on source order, so link
	   rules here are (0,2,1) to win outright.

	Sizing is deliberately generous rather than dense: the page gets read on a
	laptop during a committee meeting, by people who are mostly not in EIS.
*/

.eic-app {
	/* Hamilton's sans, with a real fallback stack. */
	--eic-sans:      "Mallory Compact Book", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
	--eic-sans-med:  "Mallory Compact Medium", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
	--eic-sans-bold: "Mallory Compact Bold", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;

	/* Hamilton palette, so the app reads as part of the site. */
	--eic-navy:    #0a2355;
	--eic-blue:    #002f86;
	--eic-ink:     #26292e;
	--eic-muted:   #5c6470;
	--eic-faint:   #a7aeb8;
	--eic-line:    #dfe3e8;
	--eic-line-soft: #edf0f3;
	--eic-bg-soft: #f5f7fa;

	/* Status: a saturated line color and a pale fill for each, so the same
	   status reads the same way whether it is a dot, a pill or a timeline bar. */
	--eic-on-track: #1f7a3d;
	--eic-at-risk:  #9a5b00;
	--eic-off-track:#b32020;
	--eic-on-hold:  #626b78;
	--eic-complete: #1d4ed8;

	--eic-on-track-bg: #e4f3e9;
	--eic-at-risk-bg:  #fdf0d9;
	--eic-off-track-bg:#fce7e7;
	--eic-on-hold-bg:  #ebedf1;
	--eic-complete-bg: #e4ecfb;

	/* Lifecycle stage tints, deliberately paler than the status fills so a
	   category pill never competes with a status color. */
	--eic-stage-pipeline-bg: #fdf6e6;  --eic-stage-pipeline-ink: #7a5b12;
	--eic-stage-hold-bg:     #f2f0f4;  --eic-stage-hold-ink:     #574d63;
	--eic-stage-planned-bg:  #eaf1fc;  --eic-stage-planned-ink:  #1c4a8a;
	--eic-stage-active-bg:   #e2edfa;  --eic-stage-active-ink:   #002f86;
	--eic-stage-done-bg:     #e9f1ec;  --eic-stage-done-ink:     #1f5c33;
	--eic-stage-closed-bg:   #f0f1f3;  --eic-stage-closed-ink:   #5c6470;
	--eic-stage-other-bg:    #f2f3f5;  --eic-stage-other-ink:    #5c6470;

	font-family: var(--eic-sans);
	/* Lining, fixed-width figures. Without this the grid inherits old-style
	   numerals from miller-text and dates do not line up column to column. */
	font-variant-numeric: lining-nums tabular-nums;
	font-feature-settings: "lnum" 1, "tnum" 1;
	color: var(--eic-ink);
	font-size: 1rem;
	line-height: 1.5;
}

.eic-app *,
.eic-app *::before,
.eic-app *::after { box-sizing: border-box; }

/* Inherit the app's font into every control, overriding the serif body. */
.eic-app input,
.eic-app select,
.eic-app button,
.eic-app dl,
.eic-app ul,
.eic-app p { font-family: inherit; font-variant-numeric: inherit; }

/* Beat `.typography a` (0,1,1) outright rather than relying on source order. */
.eic-app a.eic-projlink,
.eic-app .eic-nodates-list a,
.eic-app a.eic-btn {
	text-decoration: none;
	color: var(--eic-blue);
}

.eic-app a.eic-projlink:hover,
.eic-app .eic-nodates-list a:hover { text-decoration: underline; }

/* ------------------------------------------------------------------ header */

/* The page title comes from the SiteManager template, so this header holds only
   the refresh line. No bottom rule - the stat tiles below provide the edge. */
.eic-head { margin: 0 0 .85rem; }

.eic-app .eic-title {
	margin: 0 0 .2rem;
	font-family: var(--eic-sans-med);
	font-weight: 400;
	color: var(--eic-navy);
}

.eic-app .eic-refreshed {
	margin: 0;
	font-size: .9rem;
	color: var(--eic-muted);
}

.eic-app .eic-refreshed strong { font-family: var(--eic-sans-bold); font-weight: 400; }

.eic-muted { color: var(--eic-muted); }

/* ----------------------------------------------------------------- banners */

.eic-app .eic-banner {
	margin: 0 0 1.25rem;
	padding: .8rem 1rem;
	border: 1px solid;
	border-left-width: 4px;
	border-radius: 3px;
	font-size: .92rem;
	line-height: 1.45;
}

.eic-app .eic-banner strong { font-family: var(--eic-sans-bold); font-weight: 400; }

.eic-app .eic-banner-warn {
	background: #fdf8ea;
	border-color: #ead9ae;
	border-left-color: var(--eic-at-risk);
	color: #4a3a12;
}

.eic-app .eic-banner-error {
	background: #fdeeee;
	border-color: #eec4c4;
	border-left-color: var(--eic-off-track);
	color: #5c1a1a;
}

/* ------------------------------------------------------- summary stat tiles */

.eic-app .eic-summary {
	display: flex;
	flex-wrap: wrap;
	gap: 0;
	margin: 0 0 1.5rem;
	padding: 0;
	list-style: none;
	border: 1px solid var(--eic-line);
	border-radius: 4px;
	background: #fff;
	overflow: hidden;
}

.eic-app .eic-summary li {
	flex: 1 1 8rem;
	margin: 0;
	padding: .8rem 1.1rem;
	border-left: 1px solid var(--eic-line-soft);
	font-size: .82rem;
	line-height: 1.3;
	color: var(--eic-muted);
	/* number over label reads far better than a run-on sentence of figures */
	display: flex;
	flex-direction: column;
	gap: .15rem;
}

.eic-app .eic-summary li:first-child { border-left: 0; }

/*
	Tile tint carries meaning: the first two are facts, the last three are gaps
	the committee may need to act on. A colored top edge rather than a filled
	tile, so five tiles in a row do not turn into a paintbox.
*/
.eic-app .eic-summary li { border-top: 3px solid transparent; }
.eic-app .eic-summary li.eic-stat-neutral  { border-top-color: var(--eic-navy); }
.eic-app .eic-summary li.eic-stat-good     { border-top-color: var(--eic-on-track); background: var(--eic-on-track-bg); }
.eic-app .eic-summary li.eic-stat-pipeline { border-top-color: var(--eic-at-risk); background: var(--eic-stage-pipeline-bg); }
/* Amber, not red. These are "someone should look at this", not failures - and
   red is already spoken for by off_track status, which should not have to
   compete with a headline tile. */
.eic-app .eic-summary li.eic-stat-warn     { border-top-color: var(--eic-at-risk); background: var(--eic-at-risk-bg); }

.eic-app .eic-summary li.eic-stat-good     .eic-num { color: #17572b; }
.eic-app .eic-summary li.eic-stat-pipeline .eic-num { color: #7a5b12; }
.eic-app .eic-summary li.eic-stat-warn     .eic-num { color: #7d4a00; }

.eic-app .eic-summary li.eic-stat-done {
	border-top-color: var(--eic-on-hold);
	background: #fff;
}
.eic-app .eic-summary li.eic-stat-done .eic-num { color: var(--eic-stage-done-ink); }

/* A gap of zero is good news, so it should not be alarming. */
.eic-app .eic-summary li.eic-stat-warn.is-zero,
.eic-app .eic-summary li.eic-stat-pipeline.is-zero { background: #fff; border-top-color: var(--eic-line); }
.eic-app .eic-summary li.eic-stat-warn.is-zero .eic-num,
.eic-app .eic-summary li.eic-stat-pipeline.is-zero .eic-num { color: var(--eic-muted); }

/* ------------------------------------------------------- lifecycle pills */

.eic-pill {
	display: inline-block;
	padding: .1rem .5rem;
	border-radius: 11px;
	font-family: var(--eic-sans-med);
	font-size: .8rem;
	line-height: 1.5;
	white-space: nowrap;
	background: var(--eic-stage-other-bg);
	color: var(--eic-stage-other-ink);
}

/*
	Same four buckets as the timeline's left axis, same tints as its row bands, so
	a project reads identically in either view. See eic-tgroup-* further down.
*/
.eic-pill.eic-cat-approved  { background: var(--eic-stage-active-bg);   color: var(--eic-stage-active-ink); }
.eic-pill.eic-cat-review    { background: var(--eic-stage-pipeline-bg); color: var(--eic-stage-pipeline-ink); }
/* Declined is gray, not red: it is out of play, and red is already status
   off_track. A decision should not read as an alarm. */
.eic-pill.eic-cat-declined  { background: var(--eic-stage-closed-bg);   color: var(--eic-stage-closed-ink); }
.eic-pill.eic-cat-completed { background: var(--eic-stage-done-bg);     color: var(--eic-stage-done-ink); }

.eic-app .eic-num {
	display: block;
	font-family: var(--eic-sans-bold);
	font-weight: 400;
	font-size: 1.7rem;
	line-height: 1.05;
	color: var(--eic-navy);
}

/* -------------------------------------------------------------------- tabs */

/*
	Segmented buttons, not underlined text. As text links the inactive tab read as
	a caption and people missed that "Project list" was clickable at all - so these
	now have a border, a hover state and a filled active state.
*/
.eic-app .eic-views {
	display: flex;
	align-items: center;
	gap: .4rem;
	margin: 0 0 1.1rem;
}

.eic-views-lead {
	margin-right: .35rem;
	font-family: var(--eic-sans-med);
	font-size: .72rem;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--eic-muted);
}

.eic-app .eic-tab {
	padding: .5rem 1.15rem;
	border: 1px solid #c7cdd5;
	border-radius: 4px;
	background: #fff;
	font-family: var(--eic-sans-med);
	font-size: .95rem;
	font-weight: 400;
	color: var(--eic-blue);
	cursor: pointer;
}

.eic-app .eic-tab:hover {
	border-color: var(--eic-blue);
	background: #eef3fb;
}

.eic-app .eic-tab.is-active {
	font-family: var(--eic-sans-bold);
	background: var(--eic-navy);
	border-color: var(--eic-navy);
	color: #fff;
}

.eic-app .eic-tab:focus-visible { outline: 2px solid var(--eic-blue); outline-offset: 2px; }

/* ----------------------------------------------------------------- filters */

/*
	Grid, not flex. With flex the last row stretched two selects to half the page
	each, and a label that wrapped to two lines ("LITS Workflow Category") pushed
	its own select out of line with its neighbours.
*/
.eic-app .eic-filters {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
	gap: .55rem .65rem;
	align-items: end;
	margin: 0 0 .7rem;
	/* Tight and pale: the filters are a tool, not the subject of the page. */
	padding: .6rem .75rem;
	background: #fafbfc;
	border: 1px solid #e8ecf0;
	border-radius: 4px;
}

/*
	At full width, explicit columns rather than auto-fit. Each is sized so its
	label fits on ONE line - "LITS WORKFLOW CATEGORY" is the widest at roughly
	154px - which is what keeps the whole bar to a single row. Auto-fit gave
	every control the same width, so the bar was as tall as its longest label.
*/
/*
	The breakpoint is on the VIEWPORT but the constraint is the SiteManager content
	column, which is ~200px narrower. With four controls the minimums plus gaps plus
	the button need only ~780px of inner width, so ~1000px of viewport is enough;
	1080 leaves headroom. (It was 1280 when there were six controls.)

	Below this the auto-fit rule above takes over and the bar wraps cleanly.
*/
@media (min-width: 1080px) {
	.eic-app .eic-filters {
		/*
			minmax, not fixed widths: the minimum is what keeps each label on one
			line, and the fr share lets the controls absorb the slack evenly. A
			plain `auto` last track made the Clear filters button swallow all the
			leftover width and turned it into the biggest thing in the bar.
		*/
		grid-template-columns:
			minmax(10rem, 1.2fr)     /* Search              */
			minmax(8rem, 0.9fr)      /* Project Size        */
			minmax(8.5rem, 1fr)      /* IT Category         */
			minmax(10.5rem, 1.15fr)  /* Resource Constraint */
			max-content;             /* Clear filters       */
	}
}

.eic-filter {
	display: flex;
	flex-direction: column;
	gap: .15rem;
	min-width: 0;
}

.eic-app .eic-filter label {
	/* One line, never wrapping - the column widths above are set to guarantee
	   it. A wrapping label was what made the bar two rows tall. */
	display: block;
	margin: 0;
	white-space: nowrap;
	font-family: var(--eic-sans-med);
	font-size: .68rem;
	font-weight: 400;
	line-height: 1.4;
	text-transform: uppercase;
	letter-spacing: .03em;
	color: var(--eic-muted);
}

.eic-app .eic-filter select,
.eic-app .eic-filter input[type="search"] {
	width: 100%;
	max-width: 100%;
	height: 2.1rem;
	padding: .25rem .45rem;
	border: 1px solid #c7cdd5;
	border-radius: 3px;
	background: #fff;
	font-family: var(--eic-sans);
	font-size: .88rem;
	color: var(--eic-ink);
}

.eic-app .eic-filter select:focus,
.eic-app .eic-filter input[type="search"]:focus {
	outline: 2px solid var(--eic-blue);
	outline-offset: 1px;
}

.eic-filter-reset { justify-content: flex-end; }

.eic-app .eic-btn {
	height: 2.1rem;
	padding: 0 1rem;
	border: 1px solid var(--eic-blue);
	border-radius: 3px;
	background: #fff;
	font-family: var(--eic-sans-med);
	font-size: .88rem;
	font-weight: 400;
	color: var(--eic-blue);
	cursor: pointer;
	white-space: nowrap;
}

.eic-app .eic-btn:hover { background: var(--eic-blue); color: #fff; }

.eic-app .eic-btn-small { height: auto; padding: .2rem .6rem; font-size: .82rem; }

.eic-app .eic-resultcount {
	margin: 0 0 .6rem;
	font-size: .88rem;
	color: var(--eic-muted);
}

.eic-app .eic-note {
	margin: .7rem 0 0;
	font-size: .87rem;
	line-height: 1.5;
	color: var(--eic-muted);
}

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

.eic-grid { margin: 0; }

.eic-app .tabulator {
	border: 1px solid var(--eic-line);
	border-radius: 4px;
	background: #fff;
	font-family: var(--eic-sans);
	font-variant-numeric: lining-nums tabular-nums;
	font-size: .92rem;
}

/* Header: two tiers deep because of the date column groups, so it needs to be
   compact and clearly separated from the body. */
.eic-app .tabulator .tabulator-header {
	background: var(--eic-bg-soft);
	border-bottom: 2px solid #c3cad4;
	color: var(--eic-navy);
	font-family: var(--eic-sans-med);
	font-weight: 400;
	font-size: .78rem;
}

.eic-app .tabulator .tabulator-col {
	background: var(--eic-bg-soft);
	border-right: 1px solid #e3e7ec;
}

/*
	Uppercase the GROUP title only. A descendant selector here also caught the
	group's own child columns, which turned "Completion" into "COMPLE..." and
	"Start" into "STA..." - the letter-spacing pushed them past their width. The
	direct-child chain stops at the group's own title cell.
*/
.eic-app .tabulator .tabulator-col-group > .tabulator-col-content .tabulator-col-title {
	text-transform: uppercase;
	letter-spacing: .05em;
	font-family: var(--eic-sans-bold);
	color: var(--eic-navy);
}

.eic-app .tabulator .tabulator-col-title {
	font-weight: 400;
	white-space: normal;
	line-height: 1.25;
}

.eic-app .tabulator .tabulator-row { border-bottom: 1px solid var(--eic-line-soft); }
.eic-app .tabulator .tabulator-row.tabulator-row-even { background: #fbfcfd; }
.eic-app .tabulator .tabulator-row:hover { background: #eef3fa; }
.eic-app .tabulator .tabulator-row.tabulator-selected { background: #e3ecf8; }

.eic-app .tabulator .tabulator-cell {
	padding: .55rem .65rem;
	border-right: 1px solid var(--eic-line-soft);
}

/*
	Tabulator sets `white-space: nowrap` + ellipsis on every cell, which truncated
	the two columns that must stay readable: the project name
	("BI-EndowCustodyBank: Endowment Custody B...") and the status age
	("On hold 2.4 years ..."). These columns opt into wrapping and pair it with
	variableHeight so the row grows instead.
*/
.eic-app .tabulator .tabulator-cell.eic-cell-wrap {
	white-space: normal;
	text-overflow: clip;
	line-height: 1.35;
}

/* Frozen first column needs a hard edge so it reads as pinned while the rest
   of the grid scrolls horizontally under it. */
.eic-app .tabulator .tabulator-frozen {
	border-right: 1px solid #c3cad4;
	background: inherit;
}

.eic-app .tabulator .tabulator-row .tabulator-cell.tabulator-frozen { background: #fff; }
.eic-app .tabulator .tabulator-row.tabulator-row-even .tabulator-cell.tabulator-frozen { background: #fbfcfd; }
.eic-app .tabulator .tabulator-row:hover .tabulator-cell.tabulator-frozen { background: #eef3fa; }

.eic-app a.eic-projlink {
	font-family: var(--eic-sans-med);
	font-weight: 400;
}

.eic-code {
	display: block;
	font-size: .78rem;
	color: var(--eic-muted);
	letter-spacing: .01em;
}

.eic-flag { cursor: help; color: var(--eic-at-risk); }

/* The empty-today columns are mostly em-dashes. Keep them present, per the
   spec, but let them recede instead of dominating the grid. */
.eic-app .tabulator .eic-muted { color: var(--eic-faint); }

/* ------------------------------------------------------------------ status */

.eic-status {
	display: inline-flex;
	align-items: center;
	gap: .38rem;
	white-space: nowrap;
	font-family: var(--eic-sans-med);
	font-weight: 400;
}

.eic-dot {
	width: .6rem;
	height: .6rem;
	border-radius: 50%;
	background: currentColor;
	flex: 0 0 auto;
}

.eic-status-on_track  { color: var(--eic-on-track); }
.eic-status-at_risk   { color: var(--eic-at-risk); }
.eic-status-off_track { color: var(--eic-off-track); }
.eic-status-on_hold   { color: var(--eic-on-hold); }
.eic-status-complete  { color: var(--eic-complete); }

/* "No update" is a governance signal for this committee, so it is a deliberate
   neutral outline rather than blank. */
.eic-status-none,
.eic-status- {
	color: var(--eic-muted);
	font-family: var(--eic-sans);
}

.eic-status-none .eic-dot,
.eic-status- .eic-dot {
	background: transparent;
	border: 2px solid var(--eic-faint);
}

/* Own line under the status label - see statusFormatter(). */
.eic-age {
	display: block;
	font-family: var(--eic-sans);
	font-size: .8rem;
	line-height: 1.3;
	color: var(--eic-muted);
}

/* ---------------------------------------------------------------- variance */

.eic-var-late,
.eic-var-early { font-family: var(--eic-sans-bold); font-weight: 400; }
.eic-var-late  { color: var(--eic-off-track); }
.eic-var-early { color: var(--eic-on-track); }
.eic-var-same  { color: var(--eic-muted); }

/* ---------------------------------------------------------------- timeline */

.eic-app .eic-tlcontrols {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: .45rem .9rem;
	margin: 0 0 .7rem;
	font-size: .87rem;
	color: var(--eic-muted);
}

.eic-app .eic-legend {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: .45rem .9rem;
	margin: 0 0 .7rem;
	font-size: .87rem;
	color: var(--eic-muted);
}

.eic-key {
	display: inline-block;
	width: 1.6rem;
	height: .8rem;
	border-radius: 2px;
	vertical-align: middle;
	margin-right: -.35rem;
}

.eic-legend-lead {
	font-family: var(--eic-sans-med);
	color: var(--eic-ink);
}

/* Status swatches, matching the timeline fills exactly. */
.eic-key-on_track  { background: var(--eic-on-track-bg);  border: 1px solid var(--eic-on-track);  border-left: 4px solid var(--eic-on-track); }
.eic-key-at_risk   { background: var(--eic-at-risk-bg);   border: 1px solid var(--eic-at-risk);   border-left: 4px solid var(--eic-at-risk); }
.eic-key-off_track { background: var(--eic-off-track-bg); border: 1px solid var(--eic-off-track); border-left: 4px solid var(--eic-off-track); }
.eic-key-on_hold   { background: var(--eic-on-hold-bg);   border: 1px solid var(--eic-on-hold);   border-left: 4px solid var(--eic-on-hold); }
.eic-key-complete  { background: var(--eic-complete-bg);  border: 1px solid var(--eic-complete);  border-left: 4px solid var(--eic-complete); }
.eic-key-noupdate  { background: #fbfbfc; border: 1px dashed var(--eic-faint); border-left: 4px dotted var(--eic-faint); }

.eic-timeline {
	border: 1px solid var(--eic-line);
	border-radius: 4px;
	background: #fff;
}

.eic-app .vis-timeline {
	border: 0;
	font-family: var(--eic-sans);
	font-variant-numeric: lining-nums tabular-nums;
	font-size: .85rem;
}

.eic-app .vis-labelset .vis-label {
	padding: .3rem .6rem;
	font-family: var(--eic-sans-med);
	font-weight: 400;
	color: var(--eic-navy);
}

/*
	The three approval-state rows. Committed work reads as solid and present,
	the requester's queue as provisional, finished work as receded.
*/
.eic-app .vis-labelset .vis-label.eic-tgroup-approved {
	background: var(--eic-stage-active-bg);
	color: var(--eic-stage-active-ink);
	border-left: 4px solid var(--eic-blue);
}

.eic-app .vis-labelset .vis-label.eic-tgroup-review {
	background: var(--eic-stage-pipeline-bg);
	color: var(--eic-stage-pipeline-ink);
	border-left: 4px dashed var(--eic-at-risk);
}

.eic-app .vis-labelset .vis-label.eic-tgroup-declined {
	background: var(--eic-stage-closed-bg);
	color: var(--eic-stage-closed-ink);
	border-left: 4px solid var(--eic-on-hold);
}

.eic-app .vis-labelset .vis-label.eic-tgroup-completed {
	background: var(--eic-stage-done-bg);
	color: var(--eic-stage-done-ink);
	border-left: 4px solid var(--eic-on-track);
}

/* -------------------------------------------------------- timeline nav */

.eic-nav {
	display: inline-flex;
	gap: .3rem;
	margin-left: .25rem;
}

.eic-app .eic-nav .eic-btn { min-width: 4.5rem; }

.eic-app .vis-item {
	border-radius: 3px;
	border-width: 1px;
}

/*
	Approved bars are filled by STATUS, not one uniform blue.

	Status was previously only a 5px stripe on the left edge, which made the one
	thing this page exists to surface the least visible thing on it - a screen of
	identical blue bars. The whole bar now carries the status fill, with the
	saturated color on the border and a heavier left edge still anchoring it.
	Status is never color alone: the grid shows a labeled dot, and every bar's
	tooltip names the status in words.
*/
.eic-app .vis-item.eic-bar-approved {
	background-color: #dfe7f2;
	border-color: #8fa6c4;
	color: var(--eic-ink);
}

.eic-app .vis-item.eic-bar-approved.eic-status-on_track  { background-color: var(--eic-on-track-bg);  border-color: var(--eic-on-track); }
.eic-app .vis-item.eic-bar-approved.eic-status-at_risk   { background-color: var(--eic-at-risk-bg);   border-color: var(--eic-at-risk); }
.eic-app .vis-item.eic-bar-approved.eic-status-off_track { background-color: var(--eic-off-track-bg); border-color: var(--eic-off-track); }
.eic-app .vis-item.eic-bar-approved.eic-status-on_hold   { background-color: var(--eic-on-hold-bg);   border-color: var(--eic-on-hold); }
.eic-app .vis-item.eic-bar-approved.eic-status-complete  { background-color: var(--eic-complete-bg);  border-color: var(--eic-complete); }

/* Status color also anchors the bar's left edge. */
.eic-app .vis-item.eic-status-on_track  { border-left: 5px solid var(--eic-on-track); }
.eic-app .vis-item.eic-status-at_risk   { border-left: 5px solid var(--eic-at-risk); }
.eic-app .vis-item.eic-status-off_track { border-left: 5px solid var(--eic-off-track); }
.eic-app .vis-item.eic-status-on_hold   { border-left: 5px solid var(--eic-on-hold); }
.eic-app .vis-item.eic-status-complete  { border-left: 5px solid var(--eic-complete); }

/* No update stays deliberately pale and dashed - it is an absence, and it should
   look like one next to the projects that do report. */
.eic-app .vis-item.eic-bar-approved.eic-status-none {
	background-color: #fbfbfc;
	border: 1px dashed var(--eic-faint);
	border-left: 5px dotted var(--eic-faint);
	color: var(--eic-muted);
}

/*
	Requested but not scheduled. Muted and hatched so it can never be mistaken
	for work the committee has committed to.
*/
.eic-app .vis-item.eic-bar-proposed {
	background-color: transparent;
	background-image: repeating-linear-gradient(
		45deg, transparent, transparent 3px, #d6dae0 3px, #d6dae0 6px
	);
	border: 1px dashed var(--eic-muted);
	color: var(--eic-muted);
}

.eic-bar-tag {
	margin-left: .4rem;
	padding: 0 .3rem;
	border: 1px solid var(--eic-muted);
	border-radius: 2px;
	font-size: .72rem;
	text-transform: uppercase;
	letter-spacing: .03em;
	white-space: nowrap;
}

.eic-app .vis-item.eic-bar-partial.vis-point .vis-dot {
	border-color: var(--eic-at-risk);
	border-width: 6px;
}

/*
	Single-day approved projects are drawn as points rather than a sub-pixel bar
	(see buildTimelineItem). The status color moves from the bar's left edge to
	the dot so the color coding still reads.
*/
.eic-app .vis-item.eic-bar-approved.vis-point .vis-dot {
	border-color: var(--eic-blue);
	border-width: 6px;
}

.eic-app .vis-item.eic-bar-approved.vis-point.eic-status-on_track  .vis-dot { border-color: var(--eic-on-track); }
.eic-app .vis-item.eic-bar-approved.vis-point.eic-status-at_risk   .vis-dot { border-color: var(--eic-at-risk); }
.eic-app .vis-item.eic-bar-approved.vis-point.eic-status-off_track .vis-dot { border-color: var(--eic-off-track); }
.eic-app .vis-item.eic-bar-approved.vis-point.eic-status-on_hold   .vis-dot { border-color: var(--eic-on-hold); }
.eic-app .vis-item.eic-bar-approved.vis-point.eic-status-complete  .vis-dot { border-color: var(--eic-complete); }
.eic-app .vis-item.eic-bar-approved.vis-point.eic-status-none      .vis-dot { border-color: var(--eic-faint); }

/*
	Under Review = the dates are not settled, whichever dates they are. A dotted
	outline says "tentative" while the status fill and the solid left edge still
	carry the status, so the bar loses none of its meaning.

	Dotted, not dashed: dashed is already taken by "no status update", and the two
	need to stay tellable apart.
*/
.eic-app .vis-item.eic-tentative {
	border-top-style: dotted;
	border-right-style: dotted;
	border-bottom-style: dotted;
	border-top-width: 2px;
	border-right-width: 2px;
	border-bottom-width: 2px;
}

/* A point item's own border must not double as a bar outline. */
.eic-app .vis-item.vis-point { background: none; border: 0; }
.eic-app .vis-item.vis-point .vis-item-content { padding-left: .2rem; }

/* --------------------------------------------------------------- no dates */

.eic-app .eic-nodates {
	margin: 1.5rem 0 0;
	padding: 1rem 1.1rem;
	background: var(--eic-bg-soft);
	border: 1px solid var(--eic-line);
	border-radius: 4px;
}

.eic-app .eic-nodates h3 {
	margin: 0 0 .2rem;
	font-family: var(--eic-sans-bold);
	font-weight: 400;
	font-size: 1.05rem;
	color: var(--eic-navy);
}

.eic-app .eic-nodates-list {
	margin: .8rem 0 0;
	padding: 0;
	list-style: none;
}

.eic-app .eic-nodates-list li {
	margin: 0;
	padding: .4rem 0;
	border-top: 1px solid var(--eic-line);
	font-size: .93rem;
}

.eic-tag {
	display: inline-block;
	margin: 0 .4rem;
	padding: .05rem .5rem;
	background: #fff;
	border: 1px solid var(--eic-line);
	border-radius: 10px;
	font-size: .78rem;
	color: var(--eic-muted);
}

/* ------------------------------------------------------------ detail panel */

/*
	A centered modal. `position: fixed` with an explicit transform is set for BOTH
	paths on purpose: showModal() would centre it anyway in the top layer, and the
	fallback (a plain `open` attribute, where the dialog would otherwise sit in
	normal flow) needs it. One rule covers both.
*/
.eic-app dialog.eic-detail {
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	z-index: 900;
	width: min(46rem, calc(100vw - 2rem));
	max-height: min(80vh, 44rem);
	margin: 0;
	padding: 1.35rem 2.8rem 1.35rem 1.35rem;
	overflow-y: auto;
	background: #fff;
	color: var(--eic-ink);
	border: 1px solid var(--eic-line);
	border-top: 3px solid var(--eic-blue);
	border-radius: 5px;
	box-shadow: 0 18px 50px rgba(10, 35, 85, .28);
}

.eic-app dialog.eic-detail::backdrop { background: rgba(10, 35, 85, .45); }

.eic-app dialog.eic-detail:not([open]) { display: none; }

.eic-app .eic-detail h3 {
	margin: 0 0 .6rem;
	font-family: var(--eic-sans-med);
	font-weight: 400;
	font-size: 1.15rem;
	color: var(--eic-navy);
}

.eic-app .eic-detail h4 {
	margin: 1.3rem 0 .4rem;
	font-family: var(--eic-sans-bold);
	font-weight: 400;
	font-size: .95rem;
	text-transform: uppercase;
	letter-spacing: .04em;
	color: var(--eic-muted);
}

.eic-app .eic-detail-close {
	position: absolute;
	top: .6rem;
	right: .6rem;
	width: 1.9rem;
	height: 1.9rem;
	border: 1px solid var(--eic-line);
	border-radius: 3px;
	background: #fff;
	font-size: 1.2rem;
	line-height: 1;
	color: var(--eic-muted);
	cursor: pointer;
}

.eic-app .eic-detail-close:hover { color: var(--eic-ink); border-color: var(--eic-muted); }

.eic-app .eic-dl {
	display: grid;
	grid-template-columns: minmax(10rem, 15rem) 1fr;
	gap: 0;
	margin: 0;
	font-size: .93rem;
}

.eic-app .eic-dl dt,
.eic-app .eic-dl dd {
	margin: 0;
	padding: .4rem .6rem .4rem 0;
	border-top: 1px solid var(--eic-line-soft);
}

.eic-app .eic-dl dt {
	font-family: var(--eic-sans-med);
	font-weight: 400;
	color: var(--eic-muted);
}

/* --------------------------------------------------------------- page foot */

.eic-app .eic-foot {
	margin: 1.75rem 0 0;
	padding-top: .8rem;
	border-top: 1px solid var(--eic-line);
	font-size: .83rem;
	color: var(--eic-muted);
}

/* ------------------------------------------------------------------ narrow */

@media (max-width: 700px) {
	.eic-app .eic-dl { grid-template-columns: 1fr; }
	.eic-app .eic-dl dt { padding-bottom: 0; border-top: 1px solid var(--eic-line); }
	.eic-app .eic-dl dd { border-top: 0; padding-top: .1rem; }
	.eic-app .eic-summary li { flex: 1 1 45%; }
}
