/*
 * IESL HRIS — admin design system.
 *
 * This file is the stylesheet for the whole plugin. Every rule is scoped under
 * .iesl so nothing leaks into WordPress core screens or other plugins, and the
 * screens themselves never carry inline styles: if something needs to look
 * different, it gets a class here.
 *
 * Tokens are the same set the prototype was built on. See DESIGN.md.
 */

/* ------------------------------------------------------------------ tokens */

.iesl {
	/*
	 * The IESL palette, taken from the brand guide of January 2025 and from the
	 * logo artwork itself, which do not quite agree: the guide names Dark Green
	 * #315D44 while the mark is drawn in #016535. The mark wins here, because the
	 * mark is the thing that will sit two centimetres from a button on the same
	 * screen, and a near-miss between two greens reads as a mistake where a
	 * deliberate difference would not.
	 *
	 * Gold, Lime and Red are brand colours but not text colours. Lime on white
	 * reaches 1.90 and Gold 1.53, so neither may ever carry a word or draw a line
	 * that tells somebody what state a control is in. They fill, they accent, and
	 * where the brand colour has to be readable there is a darkened companion
	 * beside it whose contrast is written next to the value.
	 */
	--green: #016535;        /* the logo green. White on it: 7.21 */
	--green-deep: #014A26;   /* pressed and hover of a filled green. White: 10.45 */
	--green-soft: #E6F0E9;
	--lime: #9DCB40;         /* fills and decorative rules only. On white: 1.90 */
	--lime-deep: #5A7C1F;    /* lime where it must be seen. White on it: 4.84 */
	--lime-ink: #4F6D1A;     /* lime as a word on its own tint: 5.29 */
	--lime-soft: #EDF5DE;
	--gold: #FBCC00;         /* fills only. On white: 1.53 */
	--gold-ink: #7A5C00;     /* gold as a word. On white: 6.25 */
	--red: #EF2127;          /* fills and icons. On white: 4.27, under the line */
	--red-ink: #C81018;      /* red as a word. On white: 5.93 */

	/*
	 * A filled control and the only colour allowed to sit on it. These exist
	 * because the brand colours swap places between the two schemes: on white,
	 * the dark green is the fill and the text on it is white; on the dark
	 * scheme the green that is legible is a pale one, and white text on a pale
	 * green reads 1.70. Writing the pair down together is what stops one of the
	 * two being changed without the other.
	 */
	--fill: #016535;         --on-fill: #FFFFFF;      /* 7.21 */
	/*
	 * --fill-2 was here: the lime darkened until white would sit on it. It was
	 * retired rather than retuned. Every use of it put a second green beside
	 * the logo green, and two greens that are nearly the same read as an error.
	 * What it filled is now either the one brand green or outlined in it.
	 */

	/*
	 * The overtime accent, and it is the brand gold rather than a shade of it.
	 *
	 * The first version used --fill-2, which is lime taken right down to
	 * #5A7C1F so that white can sit on it. That is a working colour derived
	 * from the palette, not a colour in it, and on an overtime payslip it read
	 * as an arbitrary olive next to the green of the salary one.
	 *
	 * Gold is in the brand guide, is unmistakable against the green at a glance
	 * on a desk, and carries dark ink at 11.05 rather than needing to be
	 * darkened first.
	 */
	--fill-ot: #FBCC00;      --on-fill-ot: #10201A;   /* 11.05 */
	--ot-ink: #7A5C00;       /* gold as a word, on white: 6.25 */
	--fill-danger: #C81018;  --on-fill-danger: #FFFFFF; /* 5.93 */

	--ground: #F4F6F2;
	--surface: #FFFFFF;
	--surface-2: #FAFBF8;
	--line: #DCE3DB;
	--line-soft: #E9EEE7;

	--ink: #10201A;
	--ink-2: #44554C;
	--ink-3: #5F7168;

	--link: #016535;
	/* Text on a tinted chip: small, so it needs more contrast than muted body text. */
	--chip-ink: #54655C;
	--chip-on-ink: #016535;
	--ok: #016535;      --ok-soft: #E6F0E9;      --ok-ink: #01542C;
	--warn: #FBCC00;    --warn-soft: #FEF6D6;    --warn-ink: #7A5C00;
	--crit: #EF2127;    --crit-soft: #FDE8E8;    --crit-ink: #C81018;
	/*
	 * Info was a blue, and a blue is not in the brand. It was the one tone in
	 * the system with no parent in the palette: the company has a green, a lime,
	 * a gold and a red, and nothing else. Lime takes the job, which also turns
	 * the four tones into an escalation anybody can read left to right without a
	 * key: green settled, lime in hand, gold wants attention, red is wrong.
	 *
	 * Lime itself cannot carry a word (1.90 on white), so the readable companions
	 * are used, as everywhere else lime appears in text.
	 */
	--info: #5A7C1F;    --info-soft: #EDF5DE;    --info-ink: #4F6D1A;  /* 4.84 white on fill, 5.29 ink on tint */

	--shadow: 0 1px 2px rgba(16,32,26,.06), 0 8px 24px -12px rgba(16,32,26,.18);
	--date-icon: none;              /* the native date picker icon, per scheme */
	--r: 10px;
	--r-sm: 6px;

	--display: "Barlow Condensed", "Arial Narrow", Arial, sans-serif;
	--body: "DM Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
	--mono: "DM Mono", ui-monospace, "SF Mono", Menlo, monospace;

	color: var(--ink);
	font-family: var(--body);
	font-size: 14px;
	line-height: 1.5;
}

/*
 * Colour scheme.
 *
 * Default is the operating system's preference. A site running a dark branded
 * admin theme under a light OS (or the reverse) can pin the plugin either way:
 *
 *   add_filter( 'iesl_hris_color_scheme', fn() => 'dark' );   // or 'light'
 *
 * which writes data-iesl-scheme on the page wrapper.
 */
@media (prefers-color-scheme: dark) {
	.iesl:not([data-iesl-scheme="light"]) {
		--ground: #0D1411;
		--surface: #141E19;
		--surface-2: #18231D;
		--line: #26332C;
		--line-soft: #1E2A24;
		--ink: #E7EFE9;
		--ink-2: #AFC0B6;
		--ink-3: #85978C;
		/*
		 * On the dark surface the brand colours change places. Lime reaches 8.99
		 * against #141E19 and becomes the readable one, while the logo green is
		 * too dark to write with and keeps only its filled uses.
		 */
		--fill: #7ED9A8;         --on-fill: #08130D;      /* 11.36 */
		--fill-ot: #FBCC00;      --on-fill-ot: #08130D;   /* 12.39 */
		--ot-ink: #E3C55C;       /* on the dark surface: 10.09 */
		--fill-danger: #C81018;  --on-fill-danger: #FFFFFF;
		--green: #7ED9A8;
		--green-deep: #9EE6BE;
		--green-soft: #13271D;
		--lime: #AED55A;
		--lime-deep: #C3E27F;
		--lime-ink: #C3E27F;
		--lime-soft: #1D2A17;
		--gold: #FBCC00;
		--gold-ink: #E3C55C;
		--red: #EF2127;
		--red-ink: #EE9A90;
		--link: #AED55A;
		--chip-ink: #9DAFA4;
		--chip-on-ink: #AED55A;
		--ok: #7ED9A8;   --ok-soft: #14261B;   --ok-ink: #8ACBA1;
		--warn: #FBCC00; --warn-soft: #2A2208; --warn-ink: #E3C55C;
		--crit: #EF2127; --crit-soft: #2B1512; --crit-ink: #EE9A90;
		--info: #AED55A; --info-soft: #1D2A17; --info-ink: #C3E27F;  /* 10.39 */
		--shadow: 0 1px 2px rgba(0,0,0,.4), 0 10px 28px -14px rgba(0,0,0,.7);
		--date-icon: invert(1);
	}
}

.iesl[data-iesl-scheme="dark"] {
		--ground: #0D1411;
		--surface: #141E19;
		--surface-2: #18231D;
		--line: #26332C;
		--line-soft: #1E2A24;
		--ink: #E7EFE9;
		--ink-2: #AFC0B6;
		--ink-3: #85978C;
		/*
		 * On the dark surface the brand colours change places. Lime reaches 8.99
		 * against #141E19 and becomes the readable one, while the logo green is
		 * too dark to write with and keeps only its filled uses.
		 */
		--fill: #7ED9A8;         --on-fill: #08130D;      /* 11.36 */
		--fill-ot: #FBCC00;      --on-fill-ot: #08130D;   /* 12.39 */
		--ot-ink: #E3C55C;       /* on the dark surface: 10.09 */
		--fill-danger: #C81018;  --on-fill-danger: #FFFFFF;
		--green: #7ED9A8;
		--green-deep: #9EE6BE;
		--green-soft: #13271D;
		--lime: #AED55A;
		--lime-deep: #C3E27F;
		--lime-ink: #C3E27F;
		--lime-soft: #1D2A17;
		--gold: #FBCC00;
		--gold-ink: #E3C55C;
		--red: #EF2127;
		--red-ink: #EE9A90;
		--link: #AED55A;
		--chip-ink: #9DAFA4;
		--chip-on-ink: #AED55A;
		--ok: #7ED9A8;   --ok-soft: #14261B;   --ok-ink: #8ACBA1;
		--warn: #FBCC00; --warn-soft: #2A2208; --warn-ink: #E3C55C;
		--crit: #EF2127; --crit-soft: #2B1512; --crit-ink: #EE9A90;
		--info: #AED55A; --info-soft: #1D2A17; --info-ink: #C3E27F;  /* 10.39 */
		--shadow: 0 1px 2px rgba(0,0,0,.4), 0 10px 28px -14px rgba(0,0,0,.7);
		--date-icon: invert(1);
}

.iesl * { box-sizing: border-box; }
.iesl :focus-visible { outline: 2px solid var(--lime-deep); outline-offset: 2px; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) {
	.iesl *, .iesl *::before, .iesl *::after {
		animation: none !important;
		transition: none !important;
	}
}

/* ------------------------------------------------------------------ motion */

/*
 * Restrained on purpose. This is a screen people work in every day, so movement
 * is there to show where a thing came from and to draw the eye to a figure that
 * changed, not to entertain. Everything animates once, on arrival, and nothing
 * moves while being read.
 */
@keyframes iesl-enter {
	from { opacity: 0; transform: translateY(6px); }
	to   { opacity: 1; transform: none; }
}

.iesl .iesl-enter {
	animation: iesl-enter .32s cubic-bezier(.2, .7, .3, 1) backwards;
}

.iesl .iesl-bar__f.iesl-grow {
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform .5s cubic-bezier(.2, .7, .3, 1);
}
.iesl .iesl-bar__f.iesl-grow.is-grown { transform: scaleX(1); }

/* Hover and focus: quick, because a delay here feels like lag rather than polish. */
.iesl .iesl-btn,
.iesl .iesl-tab,
.iesl .iesl-pill,
.iesl .iesl-theme__opt { transition: background-color .12s ease, border-color .12s ease, color .12s ease; }

.iesl .iesl-panel { transition: border-color .15s ease, box-shadow .15s ease; }
.iesl .iesl-panel:hover { box-shadow: var(--shadow); }

.iesl .iesl-table tbody tr { transition: background-color .1s ease; }
.iesl .iesl-row { transition: background-color .1s ease; }
.iesl .iesl-row:hover { background: var(--surface-2); }

.iesl .iesl-btn:active { transform: translateY(1px); }

/* The avatar lifts very slightly when its row is hovered: enough to read as
   interactive, not enough to shift the line. */
.iesl .iesl-av { transition: transform .15s ease; }
.iesl .iesl-row:hover .iesl-av,
.iesl .iesl-person:hover .iesl-av { transform: scale(1.06); }

/*
 * Inheritance guard.
 *
 * WP core, ERP, Elementor, Wordfence and the admin theme all set colours on
 * bare element selectors (h1, h2, p, strong, td) that reach inside our screens.
 * Anything of ours that would otherwise inherit its colour states it here, so a
 * foreign stylesheet cannot leave dark text on a dark panel.
 */
.iesl h1, .iesl h2, .iesl h3, .iesl h4,
.iesl strong, .iesl b, .iesl dd, .iesl li { color: var(--ink); }
.iesl p, .iesl td, .iesl dl, .iesl ol, .iesl ul { color: var(--ink); }

/*
 * And a plain link, which until now had no rule at all.
 *
 * Every link in the system happened to sit inside something that coloured it:
 * a table cell, a breadcrumb, a button. The first screen to use a bare anchor
 * got the browser's default blue, which reads at 1.82 against the dark surface
 * and was invisible in exactly the way the sign-in heading was. One rule here
 * costs nothing and closes the whole class.
 */
.iesl a { color: var(--link); }
.iesl a:hover { color: var(--lime-deep); }

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

/*
 * The wrapper paints its own background.
 *
 * Without this the plugin's colour scheme only reached as far as the panels:
 * a person choosing Dark on a light admin got light text on the admin's light
 * page for everything outside a card — the h1, the lede, every section label.
 * The scheme has to be self-contained, because the page it sits in is not ours.
 */
.iesl.wrap {
	/*
	 * Fills the admin's content area, like every other screen in it.
	 *
	 * This was capped at 1260px, which on anything wider than a laptop left the
	 * whole system hugging the left edge with a band of empty page beside it.
	 * A cap is still there, but far out: past about 1900px a line of text stops
	 * being readable, and at that width the space is better left as a margin on
	 * both sides than spent making a table wider than an eye can track.
	 */
	max-width: 1900px;
	margin-right: 20px;
	background: var(--ground);
	padding: 16px 18px 26px;
	border-radius: var(--r);
}

/* Beyond the cap, centre it rather than leaving all the space on one side. */
@media (min-width: 2000px) {
	.iesl.wrap { margin-left: auto; margin-right: auto; }
}

.iesl .wp-header-end { visibility: hidden; margin: -2px 0 0; border: 0; height: 0; }
.iesl .iesl-head { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; margin: 6px 0 18px; }
.iesl .iesl-head__main { min-width: 0; }
.iesl .iesl-head__actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

.iesl .iesl-h1 { font-family: var(--display); font-size: 30px; font-weight: 600; line-height: 1.12; margin: 0; padding: 0; color: var(--ink); }
.iesl .iesl-lede { margin: 5px 0 0; color: var(--ink-3); font-size: 13px; max-width: 74ch; }
.iesl .iesl-banner p, .iesl .iesl-panel__f, .iesl .iesl-note { color: var(--ink-3); }
.iesl .iesl-crumb { margin: 0 0 3px; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.iesl .iesl-crumb a { color: var(--ink-3); text-decoration: none; }
.iesl .iesl-crumb a:hover { color: var(--lime-deep); }

.iesl .iesl-sec { font-family: var(--body); font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); margin: 24px 0 11px; padding: 0; }
.iesl .iesl-note { color: var(--ink-3); font-size: 12.5px; margin: 12px 0 0; max-width: 78ch; }

/* A plain list inside a panel: advisories, notes, anything enumerated. */
.iesl .iesl-list { margin: 0; padding: 0; list-style: none; font-size: 12.5px; }
.iesl .iesl-list li { padding: 7px 0; border-bottom: 1px solid var(--line-soft); color: var(--ink-2); }
.iesl .iesl-list li:last-child { border-bottom: 0; padding-bottom: 0; }
.iesl .iesl-list li:first-child { padding-top: 0; }
.iesl .iesl-muted { color: var(--ink-3); }

/*
 * A problem stated inline, in a cell, rather than as a banner.
 *
 * The sheet loader lists one row per employee and says against each what it
 * would do; a row it cannot use has to say so where the eye already is, not
 * in a summary above 186 rows that scrolls out of sight.
 */
.iesl .iesl-crit { color: var(--crit-ink); }
.iesl .iesl-num, .iesl td.is-num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

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

.iesl .iesl-btn {
	display: inline-flex; align-items: center; gap: 6px;
	border: 1px solid var(--line); background: var(--surface); color: var(--ink);
	padding: 7px 14px; border-radius: var(--r-sm);
	font-family: var(--body); font-size: 13px; font-weight: 500; line-height: 1.2;
	text-decoration: none; cursor: pointer;
}
.iesl .iesl-btn:hover { border-color: var(--ink-3); color: var(--ink); }
.iesl .iesl-btn--pri { background: var(--fill); border-color: var(--fill); color: var(--on-fill); }
.iesl .iesl-btn--pri:hover { background: var(--green-deep); border-color: var(--green-deep); color: var(--on-fill); }
/*
 * The secondary action, outlined rather than filled.
 *
 * It used to be filled with --fill-2, the lime taken down to #5A7C1F so white
 * could sit on it. That put two different greens side by side on the run
 * screen: Recompute in olive next to Approve in the logo green, near enough to
 * read as a mistake rather than as a deliberate difference. It is the same
 * objection that moved the overtime accent off this colour, and the answer is
 * the same: a working colour derived from the palette is not a colour in it.
 *
 * Emphasis settles it rather than a second hue. One filled green on the row,
 * on the action that commits money. Recompute is outlined in the same green,
 * Delete is outlined in the red. Three buttons, one palette, and the ranking
 * is visible without reading the labels.
 */
.iesl .iesl-btn--go {
	background: transparent;
	border-color: color-mix(in srgb, var(--fill) 45%, transparent);
	color: var(--fill);
	font-weight: 600;
}
.iesl .iesl-btn--go:hover { background: var(--green-soft); border-color: var(--fill); color: var(--fill); }
.iesl .iesl-btn--danger { color: var(--crit-ink); border-color: color-mix(in srgb, var(--crit) 40%, transparent); }
.iesl .iesl-btn--sm { padding: 4px 10px; font-size: 12px; }

/* ------------------------------------------------------------ theme switch */

.iesl .iesl-theme { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden; background: var(--surface); }
.iesl .iesl-theme__opt {
	padding: 6px 11px; font-size: 12px; font-weight: 500; line-height: 1.2;
	color: var(--ink-3); text-decoration: none; border-right: 1px solid var(--line);
}
.iesl .iesl-theme__opt:last-child { border-right: 0; }
.iesl .iesl-theme__opt:hover { color: var(--ink); background: var(--surface-2); }
.iesl .iesl-theme__opt.is-on { background: var(--fill); color: var(--on-fill); }

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

.iesl .iesl-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); margin: 0 0 16px; overflow-x: auto; }
.iesl .iesl-tab {
	border-bottom: 2px solid transparent; padding: 8px 13px;
	color: var(--ink-3); font-size: 13px; text-decoration: none; white-space: nowrap;
}
.iesl .iesl-tab:hover { color: var(--ink-2); }
.iesl .iesl-tab.is-active { color: var(--ink); border-bottom-color: var(--green); font-weight: 500; }
.iesl .iesl-tab__n { margin-left: 6px; font-family: var(--mono); font-size: 10.5px; background: var(--line-soft); color: var(--chip-ink); border-radius: 20px; padding: 1px 6px; }
.iesl .iesl-tab.is-active .iesl-tab__n { background: var(--lime-soft); color: var(--chip-on-ink); }

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

.iesl .iesl-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 13px; margin: 0 0 14px; }
.iesl .iesl-stats--1 { grid-template-columns: repeat(1, 1fr); }
.iesl .iesl-stats--2 { grid-template-columns: repeat(2, 1fr); }
.iesl .iesl-stats--3 { grid-template-columns: repeat(3, 1fr); }
.iesl .iesl-stats--5 { grid-template-columns: repeat(5, 1fr); }
.iesl .iesl-stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: 13px 15px; }
.iesl .iesl-stat--accent { border-left: 3px solid var(--lime); }
.iesl .iesl-stat--alert { border-left: 3px solid var(--red); }
.iesl .iesl-stat--gold { border-left: 3px solid var(--gold); }
/* A stat took accent, alert and gold; the screens also pass the pill words ok,
   warn, info and mute, and those four had no rule at all, so a tile the writer
   had toned rendered as an untoned tile beside toned neighbours. Declared with
   the same colours the pills use for the same words, because the reader is
   being told the same thing in both places. */
.iesl .iesl-stat--ok { border-left: 3px solid var(--ok); }
.iesl .iesl-stat--warn { border-left: 3px solid var(--warn); }
.iesl .iesl-stat--info { border-left: 3px solid var(--info); }
.iesl .iesl-stat--mute { border-left: 3px solid var(--line); }
.iesl a.iesl-stat { display: block; text-decoration: none; color: inherit; transition: border-color .12s, transform .12s; }
.iesl a.iesl-stat:hover { border-color: var(--lime-deep); }
.iesl a.iesl-stat:hover .iesl-stat__v { color: var(--lime-deep); }
.iesl a.iesl-stat::after { content: "›"; float: right; margin-top: -18px; color: var(--ink-3); font-size: 16px; }
.iesl a.iesl-stat:hover::after { color: var(--lime-deep); }
.iesl .iesl-stat__k { display: block; font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }
.iesl .iesl-stat__v { display: block; font-family: var(--display); font-size: 30px; font-weight: 600; line-height: 1.05; margin-top: 3px; font-variant-numeric: tabular-nums; color: var(--ink); }
.iesl .iesl-stat__d { display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 2px; }

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

.iesl .iesl-cols { display: grid; grid-template-columns: repeat(2, 1fr); gap: 13px; margin-bottom: 13px; }
.iesl .iesl-cols--1 { grid-template-columns: 1fr; }
.iesl .iesl-cols--3 { grid-template-columns: repeat(3, 1fr); }
.iesl .iesl-cols--4 { grid-template-columns: repeat(4, 1fr); }

.iesl .iesl-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; margin-bottom: 13px; }
.iesl .iesl-cols .iesl-panel { margin-bottom: 0; }
.iesl .iesl-panel__h { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 11px 15px; border-bottom: 1px solid var(--line-soft); }
.iesl .iesl-panel__h h2 { font-family: var(--display); font-size: 16.5px; font-weight: 600; line-height: 1.12; margin: 0; padding: 0; flex: 0 0 auto; color: var(--ink); }
/* The card's own actions, on the right of its header. */
.iesl .iesl-panel__a { margin-left: auto; display: flex; gap: 6px; flex-wrap: wrap; }
.iesl .iesl-btn--sm { padding: 4px 10px; font-size: 12px; }
.iesl .iesl-panel__b { padding: 15px; }
.iesl .iesl-panel__b--flush { padding: 0; }

/*
 * A flush card is flush for its table, and for nothing else.
 *
 * "Flush" exists so a table can run edge to edge inside a card, which is right:
 * a table has its own cell padding and a second inset around it wastes the
 * width a wide table needs. But the flag is on the card body, so everything
 * else in that body lost its inset too, and most of these cards hold more than
 * a table. A requisition put its whole detail list, its reason box and its two
 * buttons hard against the border, the button row touching the bottom edge; the
 * appraisal form put every section heading a few pixels from the left while its
 * own card title sat properly indented above it. It reads as a page that has
 * come apart.
 *
 * The screens were not wrong to ask for flush, so this is fixed here rather
 * than by revisiting thirty calls and guessing which ones meant it. Plain
 * content is given the card's own inset back. Anything that is already a box
 * with a border or a background of its own is moved in by a margin instead, so
 * its edge stays visible rather than bleeding off the card. Anything that pads
 * itself already, a row, an empty state, a footer, is left alone, and so is the
 * table this was all for.
 *
 * The last clause is the one worth reading twice: a form that wraps a table
 * gets nothing itself, and its non-table children are inset individually.
 * Padding the form would have pushed the table off the edge it was flushed to,
 * which is the fault this rule exists to remove, reintroduced one level down.
 */
.iesl .iesl-panel__b--flush > .iesl-kv,
.iesl .iesl-panel__b--flush > .iesl-list,
.iesl .iesl-panel__b--flush > .iesl-sec,
.iesl .iesl-panel__b--flush > .iesl-note,
.iesl .iesl-panel__b--flush > p,
.iesl .iesl-panel__b--flush > h3,
.iesl .iesl-panel__b--flush > h4,
.iesl .iesl-panel__b--flush > .iesl-actions,
.iesl .iesl-panel__b--flush > .iesl-fields,
.iesl .iesl-panel__b--flush > .iesl-field,
.iesl .iesl-panel__b--flush > form:not(:has(.iesl-tablewrap)):not(:has(> table)) {
	padding-left: 15px; padding-right: 15px;
}

.iesl .iesl-panel__b--flush > form:has(.iesl-tablewrap) > *:not(.iesl-tablewrap):not(table),
.iesl .iesl-panel__b--flush > form:has(> table) > *:not(table) {
	padding-left: 15px; padding-right: 15px;
}

/* Boxes keep their own edge, so they are moved in rather than padded. */
.iesl .iesl-panel__b--flush > .iesl-banner,
.iesl .iesl-panel__b--flush > .iesl-panel,
.iesl .iesl-panel__b--flush > .iesl-cards,
.iesl .iesl-panel__b--flush > .iesl-tree {
	margin-left: 15px; margin-right: 15px;
}

/*
 * And the top and bottom of a flush card, which had the same fault in the other
 * direction: the first thing in it began level with the header's bottom rule
 * and the last thing ended on the card's bottom border.
 */
/*
 * .iesl-matrix joins the exclusions for the same reason .iesl-tablewrap is on
 * them: it is a table container, not content sitting beside one, and a flush
 * card is flush for its table. Without it the access matrix picked up 14px of
 * margin above and below and stopped being flush at all.
 */
.iesl .iesl-panel__b--flush > *:first-child:not(.iesl-tablewrap):not(.iesl-matrix):not(.iesl-row):not(.iesl-empty):not(.iesl-approval) { margin-top: 14px; }
.iesl .iesl-panel__b--flush > *:last-child:not(.iesl-tablewrap):not(.iesl-matrix):not(.iesl-row):not(.iesl-empty):not(.iesl-approval):not(.iesl-panel__f) { margin-bottom: 14px; }

/*
 * A button in a table cell is a label, not a paragraph.
 *
 * The appraisal form has an action column whose buttons were wrapping onto two
 * lines and growing the row, because the column is as narrow as the table can
 * make it. Kept on one line the column asks for the width it needs instead.
 */
.iesl .iesl-table .iesl-btn { white-space: nowrap; }
.iesl .iesl-panel__f { padding: 10px 15px; border-top: 1px solid var(--line-soft); font-size: 12.5px; color: var(--ink-3); }

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

.iesl .iesl-banner { display: flex; gap: 11px; align-items: flex-start; padding: 12px 14px; border-radius: var(--r); border: 1px solid; margin: 0 0 14px; }
.iesl .iesl-banner strong { display: block; font-size: 13.5px; margin-bottom: 2px; }
.iesl .iesl-banner p { margin: 0; font-size: 12.5px; color: var(--ink-2); }
.iesl .iesl-banner__i { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 2px; border-radius: 50%; border: 2px solid currentColor; position: relative; }
.iesl .iesl-banner__i::after { content: ""; position: absolute; left: 50%; top: 3px; width: 2px; height: 5px; margin-left: -1px; background: currentColor; }
.iesl .iesl-banner__i::before { content: ""; position: absolute; left: 50%; bottom: 2px; width: 2px; height: 2px; margin-left: -1px; background: currentColor; }
.iesl .iesl-banner--crit { background: var(--crit-soft); border-color: color-mix(in srgb, var(--crit) 28%, transparent); color: var(--crit); }
.iesl .iesl-banner--warn { background: var(--warn-soft); border-color: color-mix(in srgb, var(--warn) 28%, transparent); color: var(--warn); }
.iesl .iesl-banner--info { background: var(--info-soft); border-color: color-mix(in srgb, var(--info) 28%, transparent); color: var(--info); }
.iesl .iesl-banner--ok   { background: var(--ok-soft);   border-color: color-mix(in srgb, var(--ok) 28%, transparent);   color: var(--ok); }
.iesl .iesl-banner strong { color: var(--ink); }

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

.iesl .iesl-pill { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; padding: 2px 9px; border-radius: 20px; white-space: nowrap; }
.iesl .iesl-pill code { background: none; padding: 0; margin: 0; font-family: var(--mono); font-size: 10.5px; color: inherit; }
.iesl .iesl-pill--ok { background: var(--ok-soft); color: var(--ok-ink); }
.iesl .iesl-pill--warn { background: var(--warn-soft); color: var(--warn-ink); }
.iesl .iesl-pill--crit { background: var(--crit-soft); color: var(--crit-ink); }
.iesl .iesl-pill--info { background: var(--info-soft); color: var(--info-ink); }
.iesl .iesl-pill--mute { background: var(--line-soft); color: var(--chip-ink); }
/* Lime is a brand colour that cannot be read, so the pill is the tint and the
   word on it is the darkened companion: 5.29 on the tint, not 1.90 on white. */
.iesl .iesl-pill--lime { background: var(--lime-soft); color: var(--lime-ink); }
/* Gold is the same story as lime: the tint carries it, the word never does. */
.iesl .iesl-pill--gold { background: var(--warn-soft); color: var(--gold-ink); }
.iesl .iesl-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* ------------------------------------------------------------------ tables */

.iesl .iesl-tablewrap { overflow-x: auto; }
.iesl .iesl-table { width: 100%; border-collapse: collapse; font-size: 13px; margin: 0; }
.iesl .iesl-table th { text-align: left; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); font-weight: 700; padding: 9px 14px; border-bottom: 1px solid var(--line); white-space: nowrap; background: none; }
.iesl .iesl-table th a { color: inherit; text-decoration: none; }
.iesl .iesl-table th a:hover { color: var(--lime-deep); }
.iesl .iesl-table th.is-num, .iesl .iesl-table td.is-num { text-align: right; }
.iesl .iesl-table td { padding: 9px 14px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; color: var(--ink); }
.iesl .iesl-table tbody tr:last-child td { border-bottom: 0; }
.iesl .iesl-table tbody tr:hover { background: var(--surface-2); }
.iesl .iesl-table code { background: none; padding: 0; font-family: var(--mono); font-size: 12px; color: var(--ink-2); }
.iesl .iesl-table a { color: var(--link); text-decoration: none; }
.iesl .iesl-table a:hover { color: var(--lime-deep); text-decoration: underline; }
/* A button inside a cell is a button, not a link. */
.iesl .iesl-table a.iesl-btn { color: var(--ink); text-decoration: none; }
.iesl .iesl-table a.iesl-btn--pri { color: var(--on-fill); }
.iesl .iesl-table a.iesl-btn--go { color: var(--fill); }

/* A table narrower than its columns scrolls itself; the page never does. */
.iesl .iesl-tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* --------------------------------------------------------- people and rows */

.iesl .iesl-av { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; background: var(--fill); color: var(--on-fill); display: inline-flex; align-items: center; justify-content: center; font-family: var(--display); font-size: 13px; font-weight: 600; }
.iesl .iesl-av--sm { width: 27px; height: 27px; font-size: 11px; }
.iesl .iesl-av--photo { object-fit: cover; background: var(--line-soft); }
.iesl .iesl-av--lg { width: 72px; height: 72px; font-size: 26px; }

/* Who this record is: face, name, role, number. Sits above whatever follows. */
.iesl .iesl-ident { display: flex; gap: 14px; align-items: center; padding-bottom: 14px; margin-bottom: 15px; border-bottom: 1px solid var(--line-soft); }
.iesl .iesl-ident__t { min-width: 0; }
.iesl .iesl-ident__t strong { display: block; font-family: var(--display); font-size: 19px; font-weight: 600; line-height: 1.15; letter-spacing: .01em; color: var(--ink); text-transform: uppercase; }
.iesl .iesl-ident__t span { display: block; margin-top: 3px; font-size: 12.5px; color: var(--ink-2); }
.iesl .iesl-ident__t code { display: inline-block; margin-top: 5px; font-family: var(--mono); font-size: 11px; color: var(--ink-3); background: none; padding: 0; }

/* A photo and the form that replaces it, side by side. */
.iesl .iesl-photo { display: flex; gap: 15px; align-items: flex-start; }
.iesl .iesl-photo__form { flex: 1; min-width: 0; }
.iesl .iesl-photo__form .iesl-field { display: block; }
.iesl .iesl-photo__form input[type="file"] { display: block; width: 100%; font-family: var(--body); font-size: 12.5px; color: var(--ink-2); }
.iesl .iesl-photo .iesl-actions { padding: 0; margin: 11px 0 0; }

.iesl .iesl-person { display: flex; align-items: center; gap: 9px; min-width: 0; }
.iesl .iesl-person__t { min-width: 0; }
.iesl .iesl-person__t strong { font-weight: 500; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.iesl .iesl-person__t small { display: block; color: var(--ink-3); font-size: 11.5px; }

.iesl .iesl-row { display: flex; gap: 10px; align-items: center; padding: 10px 15px; border-bottom: 1px solid var(--line-soft); }
.iesl .iesl-row:last-child { border-bottom: 0; }
.iesl .iesl-row__main { min-width: 0; flex: 1; }
.iesl .iesl-row__main strong { display: block; font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.iesl .iesl-row__main small { color: var(--ink-3); font-size: 11.5px; display: block; }
.iesl .iesl-row__rt { flex: 0 0 auto; text-align: right; font-family: var(--mono); font-size: 11.5px; color: var(--ink-2); white-space: nowrap; }

/* -------------------------------------------------------------------- bars */

/*
 * The value column is auto rather than a fixed width, and the track is allowed
 * to shrink to nothing. A fixed column was fine while every value was a count;
 * the first bar to carry "193 · 100%" was wider than its 62 pixels and pushed
 * the whole panel past the page, which is a horizontal scrollbar on a report.
 */
.iesl .iesl-bar { display: grid; grid-template-columns: 150px minmax(0, 1fr) auto; gap: 10px; align-items: center; font-size: 12.5px; margin-bottom: 6px; }
.iesl .iesl-bar:last-child { margin-bottom: 0; }
.iesl .iesl-bar__l { color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.iesl .iesl-bar__t { height: 9px; background: var(--line-soft); border-radius: 20px; overflow: hidden; }
.iesl .iesl-bar__f { display: block; height: 100%; background: var(--fill); border-radius: 20px; }
.iesl .iesl-bar__f.is-lime { background: var(--lime); }
.iesl .iesl-bar__f.is-gold { background: var(--gold); }
.iesl .iesl-bar__f.is-crit { background: var(--red); }
.iesl .iesl-bar__n { text-align: right; font-family: var(--mono); font-size: 12px; color: var(--ink-2); white-space: nowrap; }

/* ----------------------------------------------------- definition lists    */

.iesl .iesl-kv { display: grid; grid-template-columns: auto 1fr; gap: 8px 18px; font-size: 13px; margin: 0; }
.iesl .iesl-kv dt { color: var(--ink-3); font-size: 11.5px; font-weight: 400; }
.iesl .iesl-kv dd { margin: 0; font-weight: 500; color: var(--ink); }

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

.iesl .iesl-timeline { list-style: none; margin: 0; padding: 0 0 0 20px; position: relative; }
.iesl .iesl-timeline::before { content: ""; position: absolute; left: 5px; top: 6px; bottom: 6px; width: 2px; background: var(--line); }
.iesl .iesl-timeline li { position: relative; padding-bottom: 14px; }
.iesl .iesl-timeline li:last-child { padding-bottom: 0; }
.iesl .iesl-timeline li::before { content: ""; position: absolute; left: -18px; top: 5px; width: 10px; height: 10px; border-radius: 50%; background: var(--surface); border: 2px solid var(--green); }
.iesl .iesl-timeline li:not(:first-child)::before { border-color: var(--line); background: var(--line); }
.iesl .iesl-timeline strong { display: block; font-weight: 500; font-size: 13px; margin: 1px 0 2px; }
.iesl .iesl-timeline p { margin: 0; font-size: 12.5px; color: var(--ink-2); }
.iesl .iesl-timeline strong { color: var(--ink); }
.iesl .iesl-when { display: block; font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em; color: var(--ink-3); }

/* ------------------------------------------------------------ process chain */

.iesl .iesl-chain { display: flex; flex-wrap: wrap; }
.iesl .iesl-step { flex: 1; min-width: 145px; padding: 9px 11px; border: 1px solid var(--line); border-right: 0; background: var(--surface-2); }
.iesl .iesl-step:first-child { border-radius: var(--r-sm) 0 0 var(--r-sm); }
.iesl .iesl-step:last-child { border-right: 1px solid var(--line); border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.iesl .iesl-step__n { display: block; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--chip-ink); }
.iesl .iesl-step strong { display: block; font-size: 12.5px; font-weight: 500; margin: 2px 0 4px; }
.iesl .iesl-step small { color: var(--ink-3); font-size: 11.5px; display: block; }
.iesl .iesl-step.is-done { background: var(--ok-soft); border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.iesl .iesl-step.is-active { background: var(--surface); border-color: var(--green); box-shadow: inset 0 0 0 1px var(--green); }

/* ------------------------------------------------------------ empty states */

.iesl .iesl-empty { text-align: center; padding: 30px 20px; color: var(--ink-3); }
.iesl .iesl-empty strong { display: block; font-family: var(--display); font-size: 16.5px; font-weight: 600; color: var(--ink-2); margin-bottom: 4px; }
.iesl .iesl-empty p { margin: 0 auto; max-width: 62ch; font-size: 12.5px; color: var(--ink-3); }
.iesl .iesl-table .iesl-empty { padding: 26px 16px; }

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

.iesl .iesl-filters { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 0 0 13px; }

/*
 * Every control in the bar, not a list of the types that were in it the day
 * this was written.
 *
 * It used to name input[type="search"] and select. The org chart then added a
 * date box to read the structure as it was on a past date, and that box got no
 * rule at all: a browser-default date field, grey and boxy, sitting beside two
 * styled controls on an otherwise finished screen. Nothing was broken and
 * nothing was reported, it just looked like somebody had forgotten to finish
 * the page, which is the kind of fault that costs confidence rather than data.
 *
 * A bare input selector cannot go out of date the next time somebody adds a
 * number or a month box, and the hidden inputs it also matches have no visible
 * form to affect.
 */
.iesl .iesl-filters input,
.iesl .iesl-filters select {
	padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--surface-2); color: var(--ink);
	font-family: var(--body); font-size: 13px; line-height: 1.3; min-height: 0; box-shadow: none;
}
.iesl .iesl-filters input[type="search"] { min-width: 250px; }
.iesl .iesl-filters select { max-width: 230px; }

/* The native date box: same height as its neighbours, and its own picker icon
 * tinted to the scheme rather than left as the browser's blue. */
.iesl .iesl-filters input[type="date"] { min-width: 150px; }
.iesl .iesl-filters input[type="date"]::-webkit-calendar-picker-indicator,
.iesl .iesl-field input[type="date"]::-webkit-calendar-picker-indicator {
	cursor: pointer; opacity: .6;
}
/*
 * The picker icon is a token like everything else.
 *
 * The first version of this wrote the inversion twice, once per scheme, and
 * brand-check refused it: a colour stated in two places is the fault that made
 * the sign-in card invisible and the demo banner unreadable. So the scheme
 * carries the filter and the rule just uses it.
 */
.iesl input[type="date"]::-webkit-calendar-picker-indicator { filter: var(--date-icon); }

/* --------------------------------------------------------------- approvals */

.iesl .iesl-approval { padding: 14px 15px; border-bottom: 1px solid var(--line-soft); }
.iesl .iesl-approval:last-child { border-bottom: 0; }
.iesl .iesl-approval .iesl-row { padding: 0 0 10px; border-bottom: 0; }
.iesl .iesl-decide { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 11px; }
.iesl .iesl-decide input[type="text"] {
	flex: 1; min-width: 220px; padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--surface-2); color: var(--ink); font-family: var(--body); font-size: 13px; min-height: 0; box-shadow: none;
}

/* ------------------------------------------------------------------- forms */

.iesl .iesl-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 14px; margin-bottom: 14px; }
.iesl .iesl-field { display: flex; flex-direction: column; gap: 5px; }
.iesl .iesl-field > span { font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); }
.iesl .iesl-field input, .iesl .iesl-field select, .iesl .iesl-field textarea {
	padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--surface-2); color: var(--ink);
	font-family: var(--body); font-size: 13px; line-height: 1.3; width: 100%; box-shadow: none; min-height: 0;
}
.iesl .iesl-field small { font-size: 11.5px; color: var(--ink-3); }

/*
 * A rating band, as a thing to tick rather than a list to choose from.
 *
 * The appraisal form asks for one of three bands against each of twelve
 * competencies. A dropdown per row would mean twelve clicks and twelve menus,
 * and a manager comparing the whole set — which is what calibrating a person
 * actually is — could never see more than one answer at a time. These sit in a
 * row, all visible, and the chosen one is obvious at a glance across the page.
 *
 * The whole label is the target, not the dot: a radio button is a small thing
 * to hit, and this form is filled in on a laptop in a meeting.
 */
.iesl .iesl-choice {
	display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
	padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--surface-2); font-size: 12.5px; line-height: 1.2;
}
.iesl .iesl-choice input { width: auto; min-height: 0; margin: 0; box-shadow: none; }
.iesl .iesl-choice small { color: var(--ink-3); }
.iesl .iesl-choice:has( input:checked ) { border-color: var(--green); background: var(--green-soft); color: var(--ink); }
.iesl .iesl-choice:has( input:disabled ) { cursor: default; opacity: .75; }

/*
 * A required field says so, before it is submitted.
 *
 * Nothing marked them. The browser refuses to send a form with an empty
 * required box, silently, by focusing it — and on a screen where the control
 * is inside a dialog, or below the fold, or simply one of six, what a person
 * sees is a button that does nothing when pressed. Pressing it again is the
 * next thing anybody does, and after that they conclude the system is broken.
 * I hit exactly this on the payment dialog: the bank reference was required,
 * I could not tell, and Confirm appeared dead three times running.
 *
 * Done here rather than in each of the forms because there are dozens of them
 * and a marker somebody has to remember to type is a marker that will be
 * missing on the one form that matters. :has() reads the control's own
 * required attribute, which is the same attribute the browser enforces, so
 * the mark and the rule can never disagree.
 *
 * The explicit modifier beside it is for the few places where the requirement
 * is real but the attribute cannot carry it — a group where one of two must
 * be filled, say — so those can be marked deliberately rather than left bare.
 */
/*
 * One star, not two.
 *
 * The rule below marks a required field from the control's own attribute, and
 * it was added after forty-odd labels had already been written with the star
 * typed into them by hand. Both then fired: every required field in the system
 * has been reading "COURSE * *" since, on screens nobody thought to re-check
 * because the marker had just been "fixed".
 *
 * Removing the hand-typed ones in forty templates is the tidier answer and the
 * riskier one, so the rule that was added last stands down where it finds a
 * star already there. Either mechanism marks the field; neither doubles it.
 */
.iesl .iesl-field:has( > input:required, > select:required, > textarea:required ) > span::after,
.iesl .iesl-field--req > span::after {
	content: "*";
	margin-inline-start: .3em;
	color: var(--red-ink);
	font-weight: 700;
	/* Back to normal size: the label is 10.5px uppercase and a star at that
	 * size and letter-spacing reads as a speck of dust. */
	font-size: 13px;
	line-height: 0;
	vertical-align: -.1em;
	letter-spacing: 0;
}

/*
 * After the rule above and naming the element, or it loses: :has() counts its
 * most specific argument, so input:required outweighed a bare .iesl-req and
 * every hand-starred required field showed two stars.
 */
.iesl .iesl-field:has( > span > i.iesl-req ) > span::after { content: none; }

/*
 * And the form says what the star means, once, where the eye lands before the
 * controls rather than after them. A symbol nobody has been told the meaning
 * of is decoration.
 */
.iesl .iesl-reqnote {
	margin: 0 0 10px; font-size: 11.5px; color: var(--ink-3);
}
.iesl .iesl-reqnote b { color: var(--red-ink); font-weight: 700; }

/*
 * A form laid out on purpose rather than by auto-fit.
 *
 * The default grid gives every field the same width, which is right for a row
 * of dates and wrong the moment one of them is a sentence: the reason box on a
 * leave request ended up the same size as a half-day selector, so the thing
 * people write most in was the hardest to read. This is an explicit twelve
 * column grid with spans, so a field can be given the width its content needs.
 */
.iesl .iesl-fields--form { grid-template-columns: repeat(12, 1fr); align-items: start; }
.iesl .iesl-fields--form > .iesl-field { grid-column: span 12; }
@media (min-width: 640px) {
	.iesl .iesl-fields--form > .iesl-field { grid-column: span 6; }
	.iesl .iesl-fields--form > .iesl-field--q { grid-column: span 3; }
	.iesl .iesl-fields--form > .iesl-field--third { grid-column: span 4; }
	.iesl .iesl-fields--form > .iesl-field--half { grid-column: span 6; }
	.iesl .iesl-fields--form > .iesl-field--two { grid-column: span 8; }
	.iesl .iesl-fields--form > .iesl-field--full { grid-column: span 12; }
}

/*
 * A form built as a run of labels, rather than laid into the grid above.
 *
 * Both are used: the grid where fields sit side by side, a plain sequence
 * inside a dialog where they do not. The grid carries its own gap, so a stack
 * written without it had none at all — the appraisal schedule dialog ran nine
 * fields together with the label of each sitting directly on the box above it,
 * and the Save button touching the last one with nothing between them. Where
 * the eye expects a form it reads as a wall.
 *
 * Fixed here rather than in each dialog because there are dozens of them and a
 * wrapper somebody has to remember to type is a wrapper that will be missing on
 * the one form that matters. Fields inside a grid are left alone: theirs comes
 * from the gap.
 */
.iesl :not(.iesl-fields):not(.iesl-opts) > .iesl-field + .iesl-field { margin-top: 12px; }

/*
 * And the row of buttons is separated from what it acts on.
 *
 * Adjacent-sibling on purpose: this is the button row that closes a form, not
 * a set of buttons sitting beside a heading or under a paragraph, which are
 * spaced by their own surroundings and would look adrift with a rule above
 * them.
 */
.iesl .iesl-field + .iesl-actions,
.iesl .iesl-fields + .iesl-actions,
.iesl .iesl-opts + .iesl-actions {
	margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-soft);
}

/* A box for prose is a box you can see more than one line of at a time. */
.iesl .iesl-field textarea { min-height: 84px; resize: vertical; line-height: 1.45; }

/*
 * A checkbox is a sentence with a box in front of it, not a labelled field.
 *
 * The pay component dialog was the first form here with real checkboxes, and it
 * used .iesl-field, which stacks a tiny uppercase label above a full-width
 * control. A text input looks right that way. A checkbox does not: the box
 * stretched to the width of the column, the label floated above the box below
 * it, and five questions read as five labels with five unattached ticks. From
 * a screenshot it was impossible to tell which answer belonged to which
 * question, which on this particular form decides what IESL remits to a PFA.
 *
 * So the modifier turns the column back into a row, puts the box at its own
 * size, and lets the label read as the ordinary sentence it is. The whole thing
 * is a <label>, so the text is part of the hit target.
 */
.iesl .iesl-field--check {
	flex-direction: row; align-items: flex-start; gap: 10px;
	padding: 9px 11px; min-height: 44px;
	border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--surface-2);
	cursor: pointer;
}
.iesl .iesl-field--check:hover { border-color: var(--fill); }

.iesl .iesl-field--check input[type="checkbox"] {
	flex: 0 0 auto;
	width: 17px; height: 17px; margin: 1px 0 0; padding: 0;
	min-height: 0; accent-color: var(--fill); cursor: pointer;
}

/* The label, reading as a sentence rather than as a field name. */
.iesl .iesl-field--check > span {
	font-size: 13px; letter-spacing: 0; text-transform: none;
	color: var(--ink); line-height: 1.35; cursor: pointer;
}

/* One consequence per line, so a column of them scans. */
.iesl .iesl-fields--form .iesl-field--check { grid-column: span 12; }

/* A group of them is one block, not five floating rows. */
.iesl .iesl-fields--form .iesl-field--check + .iesl-field--check { margin-top: -6px; }

/*
 * Six classes the screens had been using with no rule behind them.
 *
 * Found mechanically rather than by looking: brand-check now reads every class
 * the PHP writes and every class the stylesheet declares, and compares the two
 * lists. These six were in the first list and not the second, across nine
 * screens, and had been for several releases. None of them is a PHP error and
 * none of them is a CSS error; they are only wrong where the two meet.
 *
 * The worst was iesl-inline-form, on seven screens. Every Withdraw, Confirm,
 * Approve and Refuse button sits in its own little form so the action is a POST
 * rather than a link, and without a rule each of those forms is a block: the
 * buttons in a table cell stacked vertically instead of sitting in a row, and
 * two buttons meant to be read as a pair were read as a list.
 */
.iesl .iesl-inline-form {
	display: inline-flex; align-items: center; gap: 6px;
	margin: 0; vertical-align: middle;
}
.iesl .iesl-inline-form + .iesl-inline-form { margin-left: 6px; }

/*
 * The button that swallows Enter on a decision form.
 *
 * It carries the hidden attribute and nothing should ever put it back on
 * screen, so the rule is stated rather than left to the user agent default:
 * the flex and grid layouts in this file set display on their children, and a
 * child rule beats [hidden] every time. It is a real submit button and it is
 * disabled, which is what makes Enter do nothing at all. See UI::enter_guard.
 */
.iesl .iesl-enter-guard { display: none !important; }

/* A box that takes a figure beside a button, rather than above it. */
.iesl .iesl-inline-note {
	width: auto; min-width: 8ch; max-width: 22ch;
	padding: 6px 9px;
	border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--surface-2); color: var(--ink);
	font-family: var(--body); font-size: 12.5px; line-height: 1.3;
}

/* The naira sign or the per cent sign in front of such a box. */
.iesl .iesl-inline-unit {
	display: inline-block; min-width: 1.4em;
	font-family: var(--mono); font-size: 12.5px; color: var(--ink-3);
}

/* A single checkbox on a line of its own, inside a form. */
.iesl .iesl-check { margin: 0 0 10px; }
.iesl .iesl-inline-check {
	display: inline-flex; align-items: flex-start; gap: 9px;
	font-size: 13px; color: var(--ink); line-height: 1.35; cursor: pointer;
}
.iesl .iesl-inline-check input[type="checkbox"] {
	flex: 0 0 auto; width: 17px; height: 17px; margin: 1px 0 0;
	accent-color: var(--fill); cursor: pointer;
}

/* An ordinary form that is the whole panel rather than a dialog. */
.iesl .iesl-form { margin: 0; }

/*
 * A secret, shown once.
 *
 * It is the only place in the system that prints a value nobody may see twice,
 * so it is set in the monospace face at a size that can be read off a screen
 * and copied by hand without transposing two characters.
 */
.iesl .iesl-secret {
	margin: 10px 0 0; padding: 10px 12px;
	background: var(--surface-2); border: 1px dashed var(--line); border-radius: var(--r-sm);
	overflow-wrap: anywhere;
}
.iesl .iesl-secret code {
	font-family: var(--mono); font-size: 13px; color: var(--ink);
	background: none; padding: 0;
}

/*
 * A quiet heading inside a form. Not a section rule, which is page furniture
 * and too loud in a dialog: this is just enough to say that the three fields
 * under it answer one question.
 */
.iesl .iesl-formsec {
	grid-column: 1 / -1;
	margin: 6px 0 -4px;
	font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
	color: var(--ink-3); font-weight: 600;
}
.iesl .iesl-formsec:first-child { margin-top: 0; }
.iesl .iesl-inline { display: inline; margin: 0; }
/*
 * Row actions. Two of these used to be the most a cell held, so nowrap was
 * safe. The runs list now puts Open, Recompute and Delete on one row, and
 * nowrap there pushes the table wider than the screen on a laptop. Wrap
 * instead, and cancel the sibling margin the inline forms add so the gap is
 * the same in both directions.
 */
/*
 * flex, not inline-flex. inline-flex shrink-wraps to its contents, so the box
 * never reaches the width of the cell and justify-content: flex-end had
 * nothing to push against: it was written here and did nothing. Every cell in
 * an actions column therefore started at the cell's left padding and ended
 * wherever its own contents happened to end, which is the ragged right edge
 * on the run screen's Export panel. Measured at 1280px, three cells in one
 * column ended at x=1146.8, 1132 and 1193.2.
 *
 * Shrink-wrapping also broke the wrap. Once the column narrows enough for
 * Download and Print to need two lines, an inline-flex box is only as wide as
 * the widest line, so the short line is indented by the difference instead of
 * lining up: at 1000px Download sat at x=866.3 and Print below it at 892.9.
 *
 * Block-level fixes both: the box fills the cell, so flex-end has something to
 * push against and every row in the column ends on one edge, wrapped lines
 * included. Measured again after the change, all three cells end at x=1228 at
 * 1280px and at x=948 at 1000px.
 *
 * The third shape needs the wrapper in the markup, not more CSS. A cell
 * holding a plain sentence instead of controls was a bare span, so it stayed
 * flush left at x=811.8 while the control cells sat right at 866.3. Payroll's
 * "Nothing to pay" cell now uses this same wrapper. Vertically the two shapes
 * were already within half a pixel of each other; the difference was
 * horizontal, and that is what this fixes.
 */
.iesl .iesl-rowacts {
	display: flex; flex-wrap: wrap; align-items: center;
	gap: 6px; justify-content: flex-end;
}
.iesl .iesl-rowacts .iesl-inline-form + .iesl-inline-form { margin-left: 0; }

.iesl .iesl-opts--inline { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.iesl .iesl-step-row { border: 1px solid var(--line-soft); border-radius: var(--r-sm); padding: 12px 14px; margin-bottom: 10px; background: var(--surface-2); }
.iesl .iesl-inline-input { padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink); font-size: 12.5px; min-height: 0; }
.iesl .iesl-inline-check { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink-2); }
.iesl .iesl-inline-check input { margin: 0; }

.iesl .iesl-req { font-style: normal; color: var(--red-ink); margin-left: 3px; }

/*
 * A label only a screen reader hears.
 *
 * The capability matrix is a grid of bare checkboxes, and a checkbox whose
 * meaning is carried entirely by the column it sits under is unreadable to
 * anybody not looking at the column. The visible page is unchanged; what is
 * announced becomes "IESL Finance, Read pay" instead of "checkbox".
 */
.iesl .iesl-sr {
	position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
	overflow: hidden; clip-path: inset( 50% ); white-space: nowrap; border: 0;
}

/*
 * A box the system will not let go of.
 *
 * Shown ticked and disabled rather than hidden, because the honest statement
 * is "this role has this and cannot lose it", and an empty cell would say the
 * opposite. Dimmed so it does not read as an ordinary tick, and the cursor
 * stops claiming it can be clicked.
 */
.iesl .iesl-inline-check input[type="checkbox"]:disabled {
	cursor: not-allowed; opacity: 0.55;
}

/* One bare checkbox to a cell sits under the middle of its column heading. */
.iesl .iesl-table td > .iesl-inline-check:only-child { justify-content: center; width: 100%; }

/*
 * The capability matrix.
 *
 * Nine role columns and a capability column, and the whole reason somebody
 * opens this screen is to see a row across all nine at once. The first version
 * let the table size itself, which meant the widest column heading set the
 * width, the ninth role fell off the right-hand edge behind a scrollbar, and
 * the answer to "who signs off a run" needed a horizontal scroll to read. A
 * matrix you have to scroll sideways is not a matrix; it is nine lists.
 *
 * So it never scrolls. Every width is a percentage of whatever space there is
 * and the layout is fixed, which means the cells divide the table rather than
 * the contents stretching it: a long heading wraps onto another line instead
 * of pushing the table wider than the page. There is nothing to scroll because
 * there is nothing over the edge, at any width, with no minimum to breach.
 */
.iesl .iesl-matrix .iesl-tablewrap { overflow: visible; }
.iesl .iesl-matrix .iesl-table { table-layout: fixed; width: 100%; min-width: 0; }

/*
 * Headings wrap here, and this is the line that actually removes the scroll.
 *
 * Every table heading in the system is white-space: nowrap, which is right for
 * a column called "Staff number" and wrong for nine of them called "HR
 * Recruitment": nowrap makes each heading an unbreakable block, the columns
 * cannot be narrower than the longest word plus the rest of the phrase on one
 * line, and the table grows past the page however the widths are declared. A
 * fixed layout alone does not save it, because nowrap content still sets the
 * minimum. Letting the headings wrap is what lets nine columns share a page.
 */
.iesl .iesl-matrix .iesl-table th,
.iesl .iesl-matrix .iesl-table td { white-space: normal; overflow-wrap: anywhere; }

.iesl .iesl-matrix .iesl-table th:first-child,
.iesl .iesl-matrix .iesl-table td:first-child { width: 26%; }

/*
 * The role columns carry no width at all, deliberately.
 *
 * Under a fixed layout the columns that do not declare one divide whatever the
 * first column leaves, equally, however many of them there are. A percentage
 * here would have to be one ninth, and the whole point of the screen above is
 * that the set of roles is no longer fixed.
 */
.iesl .iesl-matrix .iesl-table th:not(:first-child),
.iesl .iesl-matrix .iesl-table td:not(:first-child) {
	text-align: center; padding-left: 3px; padding-right: 3px;
}

.iesl .iesl-matrix .iesl-table th:not(:first-child) {
	font-size: 10px; line-height: 1.25; letter-spacing: 0.02em; vertical-align: bottom; hyphens: auto;
}

/* The row name: a label, with its sentence under it rather than beside it. */
.iesl .iesl-matrix .iesl-table td:first-child strong { display: block; font-weight: 600; }
.iesl .iesl-matrix .iesl-table td:first-child small { display: block; margin-top: 2px; color: var(--ink-2); font-size: 11.5px; line-height: 1.35; }

/*
 * Below 900px the table stops being a table and the rows stack into cards,
 * where percentage columns are meaningless and a checkbox needs its label
 * beside it rather than centred in a column that is no longer there. The
 * number matches the breakpoint the tables already stack at; a different one
 * would leave a band of widths where the rows are cards and the cells are
 * still eight per cent wide.
 */
@media ( max-width: 900px ) {
	.iesl .iesl-matrix .iesl-table { table-layout: auto; }
	.iesl .iesl-matrix .iesl-table th:first-child,
	.iesl .iesl-matrix .iesl-table td:first-child { width: auto; }
	.iesl .iesl-matrix .iesl-table th:not(:first-child),
	.iesl .iesl-matrix .iesl-table td:not(:first-child) { width: auto; text-align: inherit; }
	.iesl .iesl-matrix .iesl-table td > .iesl-inline-check:only-child { justify-content: flex-start; width: auto; }
}

/* ------------------------------------------------------------------ dialog */

/*
 * A dialog rather than a page, because adding somebody is something you do
 * while looking at the list. It is styled here and opened by script; every
 * button that opens one is also a link to a page that does the same job, so
 * nothing is lost when neither is available.
 */
.iesl dialog.iesl-modal {
	width: min(1040px, calc(100vw - 40px));
	max-height: min(88vh, 980px);
	padding: 0;
	border: 1px solid var(--line);
	border-radius: var(--r);
	background: var(--surface);
	color: var(--ink);
	box-shadow: 0 24px 60px -20px rgba(16,32,26,.45);
	overflow: hidden;
}
.iesl dialog.iesl-modal::backdrop { background: rgba(16,32,26,.5); }
.iesl dialog.iesl-modal[open] { display: flex; flex-direction: column; animation: iesl-enter .22s cubic-bezier(.2,.7,.3,1) backwards; }

.iesl .iesl-modal__h { display: flex; align-items: flex-start; gap: 16px; padding: 17px 20px 15px; border-bottom: 1px solid var(--line); }
.iesl .iesl-modal__h h2 { margin: 0; font-family: var(--display); font-size: 23px; font-weight: 600; line-height: 1.1; color: var(--ink); }
.iesl .iesl-modal__h p { margin: 4px 0 0; font-size: 12.5px; color: var(--ink-3); max-width: 70ch; }
.iesl .iesl-modal__x {
	margin-left: auto; border: 0; background: none; cursor: pointer;
	font-size: 26px; line-height: 1; color: var(--ink-3); padding: 0 2px;
}
.iesl .iesl-modal__x:hover { color: var(--ink); }
.iesl .iesl-modal__b { padding: 18px 20px 20px; overflow-y: auto; }
.iesl .iesl-modal__f { margin: 14px 0 0; padding-top: 13px; border-top: 1px solid var(--line-soft); }

/* ------------------------------------------------------------------ wizard */

/*
 * The steps are a layer over a complete form. Until the script marks it as a
 * wizard every section is visible and the submit button is the only control
 * that matters, which is exactly what somebody without JavaScript should get.
 */
.iesl .iesl-wiz__rail { display: none; }
.iesl .iesl-wiz.is-wizard .iesl-wiz__rail { display: flex; gap: 8px; list-style: none; margin: 0 0 20px; padding: 0; flex-wrap: wrap; }
.iesl .iesl-wiz.is-wizard .iesl-wiz__rail { gap: 6px; flex-wrap: nowrap; }
.iesl .iesl-wiz__railitem {
	display: flex; align-items: center; gap: 7px; flex: 1 1 0; min-width: 0;
	padding: 8px 10px; border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--surface-2); color: var(--ink-3); font-size: 12px;
	white-space: nowrap; overflow: hidden;
}
.iesl .iesl-wiz__railitem span:last-child { overflow: hidden; text-overflow: ellipsis; }
.iesl .iesl-wiz__num {
	display: inline-flex; align-items: center; justify-content: center;
	width: 21px; height: 21px; border-radius: 50%;
	background: var(--line); color: var(--ink-2);
	font-family: var(--mono); font-size: 11px;
}
.iesl .iesl-wiz__railitem.is-current { border-color: var(--green); background: var(--surface); color: var(--ink); }
.iesl .iesl-wiz__railitem.is-current .iesl-wiz__num { background: var(--fill); color: var(--on-fill); }
.iesl .iesl-wiz__railitem.is-done { color: var(--ink-2); }
.iesl .iesl-wiz__railitem.is-done .iesl-wiz__num { background: var(--fill); color: var(--on-fill); }

/* Review: the same words as the form, in the same order, grouped by section. */
.iesl .iesl-review__h { font-family: var(--body); font-size: 11px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); margin: 18px 0 8px; }
.iesl .iesl-review__h:first-child { margin-top: 0; }
.iesl [data-iesl-review] .iesl-kv { padding-bottom: 4px; border-bottom: 1px solid var(--line-soft); }
.iesl [data-iesl-review] .iesl-kv:last-of-type { border-bottom: 0; }

.iesl .iesl-wiz__step { margin-bottom: 18px; }
.iesl .iesl-wiz.is-wizard .iesl-wiz__step { display: none; margin-bottom: 0; }
.iesl .iesl-wiz.is-wizard .iesl-wiz__step.is-current { display: block; animation: iesl-enter .2s cubic-bezier(.2,.7,.3,1) backwards; }

.iesl .iesl-wiz__foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 18px; padding-top: 15px; border-top: 1px solid var(--line-soft); }
.iesl .iesl-wiz__hint { font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); }
.iesl .iesl-wiz:not(.is-wizard) .iesl-wiz__hint { display: none; }
.iesl .iesl-wiz__acts { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
.iesl .iesl-wiz:not(.is-wizard) [data-iesl-wiz="back"],
.iesl .iesl-wiz:not(.is-wizard) [data-iesl-wiz="next"] { display: none; }
.iesl .iesl-wiz [hidden] { display: none; }

/*
 * Seven sections do not fit side by side on a laptop at this size, so below it
 * the rail keeps the numbers and drops the words: the current step is named by
 * the fields in front of the person anyway.
 */
@media (max-width: 1100px) {
	.iesl .iesl-wiz__railitem span:last-child { display: none; }
	.iesl .iesl-wiz__railitem.is-current span:last-child { display: inline; }
	.iesl .iesl-wiz__railitem { flex: 0 0 auto; }
	.iesl .iesl-wiz__railitem.is-current { flex: 1 1 auto; }
}

@media (max-width: 782px) {
	.iesl dialog.iesl-modal { width: calc(100vw - 20px); max-height: 92vh; }
	.iesl .iesl-wiz.is-wizard .iesl-wiz__rail { flex-wrap: wrap; }
}

/* ----------------------------------------------------------------- options */

.iesl .iesl-opts { display: grid; gap: 12px; margin-bottom: 14px; }
.iesl .iesl-opt { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; }
.iesl .iesl-opt input[type="checkbox"] { margin: 2px 0 0; }
.iesl .iesl-opt strong { display: block; font-weight: 500; color: var(--ink); }
.iesl .iesl-opt small { display: block; color: var(--ink-3); font-size: 12px; max-width: 76ch; }
.iesl .iesl-opt select { margin-top: 6px; padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink); font-family: var(--body); font-size: 13px; }
.iesl .iesl-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 0; }

/* -------------------------------------------------------------- pagination */

.iesl .iesl-pager { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 13px 0 0; font-size: 12.5px; color: var(--ink-3); }
.iesl .iesl-pager .page-numbers {
	display: inline-block; padding: 4px 9px; border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--surface); color: var(--ink-2); text-decoration: none; font-family: var(--mono); font-size: 12px;
}
.iesl .iesl-pager .page-numbers.current { background: var(--fill); border-color: var(--fill); color: var(--on-fill); }
.iesl .iesl-pager .page-numbers.dots { border-color: transparent; background: none; }

/* -------------------------------------------------------------- two-column */

.iesl .iesl-grid2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 24px; }

/* ----------------------------------------------------------------- roadmap */

.iesl .iesl-roadmap { display: flex; gap: 10px; align-items: flex-start; padding: 7px 0; }
.iesl .iesl-roadmap__n { flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%; background: var(--line-soft); color: var(--chip-ink); display: inline-flex; align-items: center; justify-content: center; font-family: var(--mono); font-size: 11px; font-weight: 700; }
.iesl .iesl-roadmap strong { display: block; font-size: 13px; font-weight: 500; }
.iesl .iesl-roadmap small { color: var(--ink-3); font-size: 12px; display: block; }

/* --------------------------------------------------------------- responsive */

@media (max-width: 1400px) { .iesl .iesl-cols--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 1200px) {
	.iesl .iesl-stats, .iesl .iesl-stats--5 { grid-template-columns: repeat(2, 1fr); }
	.iesl .iesl-cols--3 { grid-template-columns: 1fr; }
}
@media (max-width: 960px) {
	.iesl .iesl-cols, .iesl .iesl-cols--2 { grid-template-columns: 1fr; }
	.iesl .iesl-grid2 { grid-template-columns: 1fr; }
	.iesl .iesl-bar { grid-template-columns: 96px minmax(0, 1fr) auto; }
}
@media (max-width: 782px) {
	.iesl .iesl-stats { grid-template-columns: 1fr; }
	.iesl .iesl-head__actions { margin-left: 0; }
}


/*
 * Jumps: a quiet row of links to the sections of a long record. On a wide
 * screen it is a convenience; on a handset, where the same record is five
 * screens of scrolling, it is the difference between finding a phone number and
 * giving up on it, so it becomes a sticky strip there.
 */
.iesl .iesl-jumps {
	display: flex; flex-wrap: wrap; gap: 6px;
	margin: 0 0 14px;
}
.iesl .iesl-jumps__l {
	padding: 5px 11px; border-radius: 20px;
	border: 1px solid var(--line); background: var(--surface);
	font-size: 12px; color: var(--ink-2); text-decoration: none;
}
.iesl .iesl-jumps__l:hover { border-color: var(--green); color: var(--green); }
.iesl .iesl-sec { scroll-margin-top: 96px; }
.iesl .iesl-sec:focus { outline: none; }

/* --------------------------------------------------------------- directory */

/*
 * A grid of people rather than a table of them.
 *
 * A directory is scanned, not read: somebody arrives knowing roughly who they
 * are looking for and recognises a face or a name. Cards suit that and a table
 * does not, and the grid collapses to one column on a handset without needing
 * the stacked-card treatment the tables get.
 *
 * auto-fill with a minimum rather than a fixed column count, so the same rule
 * gives four across on a wide monitor and two on a tablet with nothing to
 * maintain between them.
 */
.iesl .iesl-cards {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(236px, 1fr));
	gap: 12px;
}

.iesl .iesl-card {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r);
	padding: 13px 14px;
	min-width: 0;
}
.iesl .iesl-card:hover { border-color: var(--lime-deep); }

/*
 * The pipeline on a vacancy: a column per stage still in the running, each
 * person a card. Read only; the table under it is where people are moved,
 * so a rejection always carries its reason. Columns scroll sideways on a
 * wide screen and stack on a phone, where six narrow columns are unreadable.
 */
.iesl .iesl-board { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(118px, 1fr); gap: 8px; overflow-x: auto; padding: 14px; }
.iesl .iesl-board__col { background: var(--ground); border: 1px solid var(--line-soft); border-radius: var(--r-sm); padding: 10px; min-width: 0; }
.iesl .iesl-board__col h3 { display: flex; justify-content: space-between; gap: 8px; margin: 0 0 8px; font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.iesl .iesl-board__col .iesl-card { margin-bottom: 8px; padding: 9px 10px; }
.iesl .iesl-board__col .iesl-card small { display: block; color: var(--ink-2); }
.iesl .iesl-board__col .iesl-card strong { display: block; overflow-wrap: anywhere; }
.iesl .iesl-board.is-movable .iesl-card[draggable="true"] { cursor: grab; }
.iesl .iesl-board .iesl-card.is-dragging { opacity: .5; }
.iesl .iesl-board__col.is-over { outline: 2px dashed var(--fill); outline-offset: -2px; background: color-mix(in srgb, var(--fill) 8%, var(--ground)); }
.iesl .iesl-board__hint { margin: 0; padding: 0 14px 12px; font-size: 12.5px; color: var(--ink-2); }
.iesl .iesl-more { margin-top: 12px; }
.iesl .iesl-more > summary { list-style: none; display: inline-flex; cursor: pointer; }
.iesl .iesl-more > summary::-webkit-details-marker { display: none; }
.iesl .iesl-more > summary::after { content: "\25BE"; margin-left: 6px; }
.iesl .iesl-more[open] > summary::after { content: "\25B4"; }
.iesl .iesl-more__b { margin-top: 10px; padding: 12px; border: 1px solid var(--line-soft); border-radius: var(--r-sm); background: var(--ground); }
.iesl .iesl-more__b p { margin: 0 0 10px; font-size: 12.5px; }
.iesl [hidden] { display: none !important; }
.iesl .iesl-next { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 0 0 16px; padding: 12px 14px; border: 1px solid color-mix(in srgb, var(--fill) 35%, transparent); border-left: 4px solid var(--fill); border-radius: var(--r-sm); background: color-mix(in srgb, var(--fill) 6%, var(--surface)); }
.iesl .iesl-next__t { flex: 1 1 260px; min-width: 0; }
.iesl .iesl-next__t b { display: block; font-size: 13.5px; }
.iesl .iesl-next__t span { display: block; font-size: 12.5px; color: var(--ink-2); }
.iesl .iesl-guide { margin: 0 0 16px; }
.iesl .iesl-guide > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; }
.iesl .iesl-guide > summary::-webkit-details-marker { display: none; }
.iesl .iesl-guide > summary::after { content: "Show"; font-size: 12.5px; font-weight: 600; color: var(--fill); }
.iesl .iesl-guide[open] > summary::after { content: "Hide"; }
.iesl .iesl-guide:not([open]) > summary { border-bottom: 0; }
.iesl .iesl-guide ol { margin: 8px 0 0 18px; padding: 0; font-size: 13px; }
.iesl .iesl-guide li { margin: 0 0 6px; }
.iesl .iesl-filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.iesl .iesl-filters .iesl-field { flex: 1 1 160px; margin: 0; }
.iesl .iesl-hint { margin: -4px 0 12px; font-size: 12.5px; }
.iesl div.iesl-stat.is-link { cursor: pointer; }
.iesl div.iesl-stat.is-link:hover, .iesl div.iesl-stat.is-link:focus-visible { border-color: var(--fill); box-shadow: 0 0 0 2px color-mix(in srgb, var(--fill) 25%, transparent); outline: none; }
.iesl .iesl-flash { outline: 3px solid color-mix(in srgb, var(--fill) 55%, transparent); outline-offset: 4px; border-radius: var(--r-sm); transition: outline-color .6s; }
.iesl .iesl-picklist__q { display: block; width: 100%; margin: 0 0 6px; }
.iesl .iesl-picklist__n { display: block; margin-top: 4px; font-size: 12px; color: var(--ink-2); }
@media (max-width: 782px) {
	.iesl .iesl-board { grid-auto-flow: row; grid-auto-columns: auto; overflow-x: visible; }
}

.iesl .iesl-card__top { display: flex; align-items: center; gap: 10px; min-width: 0; }
.iesl .iesl-card__who { min-width: 0; }
.iesl .iesl-card__who b {
	display: block; font-size: 13px; font-weight: 500;
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.iesl .iesl-card__who small {
	display: block; font-size: 11.5px; color: var(--ink-3);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.iesl .iesl-card__tags { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 10px; }

.iesl .iesl-card__contact {
	display: flex; flex-direction: column; gap: 2px;
	margin-top: 10px; padding-top: 9px;
	border-top: 1px solid var(--line-soft);
	font-size: 11.5px;
}
.iesl .iesl-card__contact a {
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
	text-decoration: none;
}
.iesl .iesl-card__contact a:hover { text-decoration: underline; }

/* ------------------------------------------------------------- org diagram */

/*
 * Three rows with a connector between them: the top rung of the ladder, the
 * rungs under it, and the departments. This is the picture people mean when
 * they say org chart, and it answers a different question from the tree below.
 *
 * The connector is a single centred line rather than the elbow-and-branch
 * drawing a real diagram tool produces. Elbows need to know how wide each child
 * is, which in CSS means either a fixed layout or a script measuring boxes, and
 * both break the moment a department name is longer than expected. One line and
 * a wrapping row survives 8 departments, 20 departments and a phone.
 */
.iesl .iesl-shape { text-align: center; padding: 6px 0 2px; }
.iesl .iesl-shape__row {
	display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;
}
.iesl .iesl-shape__line {
	width: 1px; height: 22px; margin: 0 auto;
	background: var(--line);
}
.iesl .iesl-shape__more { margin: 9px 0 0; font-size: 11.5px; color: var(--ink-3); }

.iesl .iesl-shape__box {
	display: inline-flex; align-items: center; gap: 10px;
	padding: 9px 14px 9px 10px; min-width: 0; max-width: 100%;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-sm);
	text-align: left;
}
.iesl .iesl-shape__box--top {
	border-color: var(--green);
	box-shadow: 0 0 0 1px var(--green);
}

/* The circle, in the brand green with the initials knocked out of it. */
.iesl .iesl-shape__av {
	flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
	background: var(--fill); color: var(--on-fill);
	display: inline-flex; align-items: center; justify-content: center;
	font-family: var(--display); font-size: 11px; font-weight: 700; letter-spacing: .04em;
}

.iesl .iesl-shape__who { min-width: 0; }
.iesl .iesl-shape__box b {
	display: block; font-size: 13px; font-weight: 500; line-height: 1.25;
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.iesl .iesl-shape__box small {
	display: block; font-size: 11.5px; color: var(--ink-3); line-height: 1.3;
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ------------------------------------------------------------------- tree */

/*
 * The whole company, top to bottom.
 *
 * Nested lists with the connectors drawn from the nesting, which is the one
 * technique that survives real data. Anything that positions a line has to know
 * how wide its children are, and the width of a row of 94 engineers is not
 * knowable until it is laid out; these elbows are borders on the list items and
 * cost nothing to be wrong about.
 *
 * Three rules do all of it. A child has a stub going up. Every child but the
 * first and last also has a horizontal run across the top. The first and last
 * get half of that run, on the side facing the middle, which is what closes the
 * corners. A single child gets a straight line instead, because a corner with
 * nothing to turn towards reads as a mistake.
 */
.iesl .iesl-tree { display: block; }

.iesl .iesl-tree__bar {
	display: flex; align-items: center; justify-content: space-between; gap: 10px;
	flex-wrap: wrap;
	padding: 9px 14px;
	border-bottom: 1px solid var(--line-soft);
	background: var(--surface-2);
}
.iesl .iesl-tree__zoom, .iesl .iesl-tree__acts { display: flex; align-items: center; gap: 6px; }
.iesl .iesl-tree__pc {
	font-family: var(--mono); font-size: 11.5px; color: var(--ink-2);
	min-width: 4.5ch; text-align: center;
}

/*
 * The viewport. It scrolls in both directions because a 193-person chart is
 * wider than any screen, and it is the only thing on the page that does: the
 * document itself never scrolls sideways.
 */
.iesl .iesl-tree__pane {
	overflow: auto;
	max-height: 78vh;
	padding: 20px 14px 24px;
	background: var(--surface-2);
	cursor: grab;
	overscroll-behavior: contain;
}
.iesl .iesl-tree__pane.is-dragging { cursor: grabbing; user-select: none; }

.iesl {
	--tree-gap: 40px;
	--tree-line: 2px;
	--tree-ink: var(--ink-3);
}

.iesl .iesl-tree__canvas {
	display: inline-block; min-width: 100%;
	transform-origin: 0 0;
	transition: transform .12s ease-out;
}

.iesl .iesl-tree__level {
	display: flex; justify-content: center; align-items: flex-start;
	list-style: none; margin: 0; padding: var(--tree-gap) 0 0;
	position: relative;
}
.iesl .iesl-tree__level--root { padding-top: 0; }

.iesl .iesl-tree__node {
	position: relative;
	display: flex; flex-direction: column; align-items: center;
	padding: 0 10px;
}

/*
 * The connectors.
 *
 * Drawn the way the approved organogram draws them: a stub down out of the
 * parent, a run across the top of the row, and a stub up into each child, with
 * enough vertical room that each of the three reads as a separate segment. At
 * the old 26px the three ran together into one smudge behind the boxes, and the
 * only question a chart has to answer at a glance - is this box under that one,
 * or beside it - could not be answered.
 *
 * Every line is painted at z-index 0 and every box at 1, so a line can never
 * cross a box even where a wide subtree puts one behind the other.
 */
.iesl .iesl-tree__level:not(.iesl-tree__level--root) > .iesl-tree__node::before {
	content: ""; position: absolute; top: calc(var(--tree-gap) * -1); left: 50%;
	width: var(--tree-line); height: var(--tree-gap);
	margin-left: calc(var(--tree-line) / -2);
	background: var(--tree-ink); z-index: 0;
}

.iesl .iesl-tree__level:not(.iesl-tree__level--root) > .iesl-tree__node::after {
	content: ""; position: absolute; top: calc(var(--tree-gap) * -1); left: 0; right: 0;
	height: var(--tree-line); background: var(--tree-ink); z-index: 0;
}
.iesl .iesl-tree__level:not(.iesl-tree__level--root) > .iesl-tree__node:first-child::after { left: 50%; }
.iesl .iesl-tree__level:not(.iesl-tree__level--root) > .iesl-tree__node:last-child::after { right: 50%; }
/* One child: a straight line down, with no corner to turn. */
.iesl .iesl-tree__level:not(.iesl-tree__level--root) > .iesl-tree__node:only-child::after { display: none; }

.iesl .iesl-tree__node.is-parent > .iesl-tree__box::after {
	content: ""; position: absolute; bottom: calc(var(--tree-gap) * -1); left: 50%;
	width: var(--tree-line); height: var(--tree-gap);
	margin-left: calc(var(--tree-line) / -2);
	background: var(--tree-ink); z-index: 0;
}
.iesl .iesl-tree__node.is-parent.is-closed > .iesl-tree__box::after { display: none; }

.iesl .iesl-tree__box {
	position: relative; z-index: 1;
	display: flex; align-items: center; gap: 10px;
	width: 212px; height: 66px;
	padding: 11px 12px 11px 10px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r-sm);
	text-align: left;
	box-shadow: 0 1px 0 rgba(0, 0, 0, .04);
}
.iesl .iesl-tree__node.is-closed > .iesl-tree__box { border-style: dashed; }


.iesl .iesl-tree__av {
	flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%;
	background: var(--fill); color: var(--on-fill);
	display: inline-flex; align-items: center; justify-content: center;
	font-family: var(--display); font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
}
.iesl .iesl-tree__who { min-width: 0; }
/*
 * Two lines before it gives up, rather than one and an ellipsis. "Materials and
 * Corros…" is not the name of anything, and on a chart the name is the whole
 * content of the box.
 */
.iesl .iesl-tree__who b {
	display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
	font-size: 12px; font-weight: 500; line-height: 1.25;
	overflow: hidden;
}
/*
 * One line, because the subtitle is a person's name. It used to hold the
 * sentence explaining why there was no name, which ran to three lines and made
 * one box in a row twice the height of its neighbours, so the connectors met
 * the row at three different heights. The explanation is a word on the corner
 * now.
 */
.iesl .iesl-tree__who small {
	display: block;
	font-size: 10.5px; color: var(--ink-3); line-height: 1.3;
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/*
 * The collapse button sits on the corner of the box rather than inside it, so
 * it never competes with the name for the width, and its label is the number of
 * people it would hide.
 */
.iesl .iesl-tree__toggle {
	position: absolute; right: -9px; top: -9px;
	min-width: 22px; height: 20px; padding: 0 6px;
	border: 1px solid var(--line); border-radius: 20px;
	background: var(--surface); color: var(--ink-3);
	font-family: var(--mono); font-size: 10px; line-height: 1;
	cursor: pointer;
}
.iesl .iesl-tree__toggle:hover { border-color: var(--green); color: var(--green); }
.iesl .iesl-tree__toggle:focus-visible { outline: 2px solid var(--lime-deep); outline-offset: 1px; }
.iesl .iesl-tree__node.is-closed > .iesl-tree__box > .iesl-tree__toggle {
	background: var(--fill); border-color: var(--fill); color: var(--on-fill);
}

/* A closed branch takes no space at all, which is the point of closing it. */
.iesl .iesl-tree__node.is-closed > .iesl-tree__level { display: none; }

@media (prefers-reduced-motion: reduce) {
	.iesl .iesl-tree__canvas { transition: none; }
}

/* ---------------------------------------------------------------- portal */

/*
 * The staff portal renders its own document rather than sitting inside the
 * theme, and it is laid out as an application: a rail down the side, a bar
 * across the pane, and one thing that scrolls.
 *
 * The rail rather than a strip of links, because seventeen screens in six
 * groups can be read down the side of a page and the same seventeen laid out
 * horizontally is a wrapping ribbon that pushes the content down and says
 * nothing about what belongs with what.
 */
/*
 * The chrome has tokens of its own, and they follow the same choice the content
 * follows.
 *
 * The chrome sits outside .iesl and so cannot read the design system's tokens.
 * The first cut answered that by keying every chrome colour to the operating
 * system, which meant the three buttons in the top bar changed the content and
 * left the rail, the bar and the page behind them alone. Somebody on a dark
 * laptop who chose Light got a light card floating in a dark frame, and the
 * demo banner, which sits inside .iesl, took its background from the machine
 * and its text colour from the choice and rendered dark on dark.
 *
 * So the chrome gets its own small set of tokens, written once per scheme, and
 * the attribute decides which set is in force exactly as it does for .iesl.
 */
body.iesl-portal {
	--c-ground: #F4F6F2;     /* the page behind the panels */
	--c-surface: #FFFFFF;    /* the top bar, the phone bar */
	--c-ink: #10201A;        /* 16.1 on --c-ground */
	--c-ink-2: #44554C;      /* 8.55 on --c-surface */
	--c-ink-3: #5F7168;      /* 5.43 on --c-surface */
	--c-line: #DCE3DB;
	--c-hover: #F4F6F2;
	--c-accent: #016535;     /* 7.21 carrying white */
	--c-accent-soft: #E6F0E9;
	--c-fill: #016535;       /* the pressed button in the bar */
	--c-on-fill: #FFFFFF;    /* 7.21 */

	margin: 0;
	background: var(--c-ground);
	color: var(--c-ink);
	font-family: "DM Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
	-webkit-text-size-adjust: 100%;
	height: 100%;
}
html:has(body.iesl-portal) { height: 100%; }

/* Chosen dark. */
body.iesl-portal[data-iesl-scheme="dark"] {
	--c-ground: #0D1411;
	--c-surface: #141E19;
	--c-ink: #E7EFE9;        /* 15.9 on --c-ground */
	--c-ink-2: #AFC0B6;      /* 8.03 on --c-surface */
	--c-ink-3: #85978C;      /* 4.87 on --c-surface */
	--c-line: #26332C;
	--c-hover: #18231D;
	--c-accent: #7ED9A8;     /* 9.98 as a word on --c-surface */
	--c-accent-soft: #14261B;
	--c-fill: #7ED9A8;
	--c-on-fill: #08130D;    /* 11.36 */
}

/* Or not chosen at all, in which case the machine decides. */
@media (prefers-color-scheme: dark) {
	body.iesl-portal:not([data-iesl-scheme="light"]) {
		--c-ground: #0D1411;
		--c-surface: #141E19;
		--c-ink: #E7EFE9;
		--c-ink-2: #AFC0B6;
		--c-ink-3: #85978C;
		--c-line: #26332C;
		--c-hover: #18231D;
		--c-accent: #7ED9A8;
		--c-accent-soft: #14261B;
		--c-fill: #7ED9A8;
		--c-on-fill: #08130D;
	}
}

.iesl-app { display: grid; grid-template-columns: 234px 1fr; height: 100vh; height: 100dvh; }
.iesl-main { display: flex; flex-direction: column; min-width: 0; overflow: hidden; }
.iesl-scroll { flex: 1; overflow-y: auto; padding: 20px 24px 56px; }

/* ------------------------------------------------------------------ rail */

/*
 * Dark, and in the company's own green rather than a neutral. Contrast is
 * written down beside each value because the rail is the one surface in the
 * system that is not the design-system's own light or dark scheme, so the
 * tokens do not check it for us.
 */
.iesl-rail {
	background: #01301A;                 /* the brand green, taken down */
	color: #CFE0D3;                      /* 10.60 on it */
	border-right: 1px solid #0B5231;
	display: flex; flex-direction: column;
	overflow-y: auto;
	padding-bottom: 16px;
}

.iesl-rail__brand {
	display: flex; align-items: center; gap: 10px;
	padding: 15px 14px 12px;
	text-decoration: none; color: inherit;
}
/*
 * The mark on a white plate. The rail is dark and the approved logo is drawn
 * in the company's dark green: on the rail itself the wordmark disappears and
 * only the gold, lime and red device survives. The guide says the primary logo
 * is used in its original colours, so it is given a surface instead.
 */
.iesl-rail__plate {
	flex: 0 0 auto; display: inline-flex; align-items: center;
	background: #fff; border-radius: 6px; padding: 5px 7px;
}
.iesl-rail__plate .iesl-brand__mark { display: block; }
.iesl-rail__name b {
	display: block; font-family: "Barlow Condensed", "Arial Narrow", Arial, sans-serif;
	font-size: 17px; font-weight: 600; letter-spacing: .03em; color: #fff; line-height: 1.05;
}
.iesl-rail__name small {
	display: block; font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase;
	color: #8BA793;                      /* 5.59 on the rail */
}

.iesl-rail__group { padding: 0 11px 4px; }
.iesl-rail__group h2 {
	font-size: 9.5px; letter-spacing: .15em; text-transform: uppercase;
	color: #8BA793; font-weight: 700; margin: 0;
	padding: 11px 9px 5px;
}

.iesl-rail__item {
	display: flex; align-items: center; gap: 9px;
	padding: 7px 10px; border-radius: 6px;
	font-size: 13px; color: #CFE0D3; text-decoration: none;
	transition: background .12s;
}
.iesl-rail__item span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.iesl-rail__item:hover { background: rgba(255,255,255,.07); color: #fff; }
.iesl-rail__item:focus-visible { outline: 2px solid #9DCB40; outline-offset: -2px; }
/* The current section: 4.65 for the white on it, 3.14 for the fill on the rail. */
.iesl-rail__item.is-here { background: #02864A; color: #fff; font-weight: 500; }
.iesl-rail__icon { flex: 0 0 auto; opacity: .92; }

.iesl-rail__n {
	margin-left: auto; flex: 0 0 auto;
	font-family: "DM Mono", ui-monospace, monospace; font-size: 10px; font-weight: 500;
	background: #EF2127; color: #12261B;   /* 4.92 */
	border-radius: 20px; padding: 1px 6px;
}
.iesl-rail__item.is-here .iesl-rail__n { background: rgba(0,0,0,.3); color: #fff; }

/* --------------------------------------------------------------- topbar */

.iesl-topbar {
	flex: 0 0 auto;
	display: flex; align-items: center; gap: 14px;
	padding: 11px 24px;
	background: var(--c-surface);
	border-bottom: 1px solid var(--c-line);
}
.iesl-topbar__crumb {
	margin: 0; min-width: 0;
	font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--c-ink-3);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.iesl-topbar__right { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/*
 * The colour switch lives in the bar now rather than repeating inside every
 * screen, and it shows which of the three is in force.
 */
.iesl-topbar .iesl-theme {
	display: inline-flex; border: 1px solid var(--c-line); border-radius: 6px; overflow: hidden;
}
.iesl-topbar .iesl-theme__opt {
	padding: 7px 10px; font-size: 12px; color: var(--c-ink-2); text-decoration: none;
	border-right: 1px solid var(--c-line);
}
.iesl-topbar .iesl-theme__opt:last-child { border-right: 0; }
.iesl-topbar .iesl-theme__opt:hover { background: var(--c-hover); }
.iesl-topbar .iesl-theme__opt.is-on { background: var(--c-fill); color: var(--c-on-fill); }
.iesl-topbar__who { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.iesl-topbar__av {
	flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%;
	background: #016535; color: #fff;
	display: inline-flex; align-items: center; justify-content: center;
	font-family: "Barlow Condensed", "Arial Narrow", Arial, sans-serif;
	font-size: 13px; font-weight: 600;
}
.iesl-topbar__name {
	font-size: 13px; font-weight: 500; color: var(--c-ink-2);
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 22ch;
}
.iesl-topbar__link {
	font-size: 13px; color: var(--c-ink-2); text-decoration: none;
	padding: 8px 12px; border: 1px solid var(--c-line); border-radius: 6px; white-space: nowrap;
}
.iesl-topbar__link:hover { color: var(--c-accent); border-color: var(--c-accent); }

/* The bottom bar is for handsets and is switched on in the phone block. */
.iesl-portal__tabs { display: none; }

.iesl-portal__body { padding: 24px 20px; }

/* The wrapper is an admin class; on the portal it is the page. */
body.iesl-portal .iesl.wrap { margin: 0 auto; border-radius: 0; max-width: 1220px; }

/*
 * The demo banner in the portal. In wp-admin the admin stylesheet gives
 * .notice its look; here there is no admin stylesheet, so it needs its own.
 *
 * It is printed inside .iesl, so it takes the design system's tokens and
 * nothing else. It used to paint its background from the operating system
 * while the paragraph inside it took .iesl p, which follows the chosen scheme:
 * a light-mode ink on a dark-mode surface, and a banner nobody could read. The
 * colour on the paragraph is deliberate and has to stay, because .iesl p would
 * otherwise win against a colour set only on the wrapper.
 */
.iesl .iesl-demo-banner {
	margin: 0 0 16px; padding: 12px 16px; border-radius: 8px;
	background: var(--warn-soft); border-left: 4px solid var(--warn); color: var(--ink);
	font-size: 13px; line-height: 1.5;
}
.iesl .iesl-demo-banner p { margin: 0; color: var(--ink); }
.iesl .iesl-demo-banner strong { color: var(--ink); }
.iesl .iesl-demo-banner a { color: var(--link); }

/* ============================================================== the door */

/*
 * The sign-in screen. One card, centred, with the mark above it and nothing
 * else on the page: no menu, no navigation, nothing to read and nothing to
 * click that is not the thing the person came to do.
 *
 * Every colour here is a token, and every selector starts at .iesl. Both of
 * those are scars. The first cut wrote the card in raw hexes under a
 * prefers-color-scheme query while the words inside it took their colour from
 * .iesl h1 and .iesl p, which follow the token system and therefore the
 * data-iesl-scheme attribute. The two disagreed, and the result was #10201A
 * text on a #141E19 card: the heading, the line under it and the footnote were
 * all present, all correctly sized, and all completely invisible. A second
 * source of truth for colour is how that happens, so there is one again.
 */
.iesl .iesl-door {
	display: flex; align-items: center; justify-content: center;
	min-height: 100vh; min-height: 100dvh;
	padding: 24px 16px calc(24px + env(safe-area-inset-bottom));
	background: var(--ground);
}

.iesl .iesl-door__card {
	width: 100%; max-width: 380px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: 12px;
	padding: 28px 26px 24px;
	box-shadow: var(--shadow);
}

.iesl .iesl-door__brand { margin: 0 0 20px; }
.iesl .iesl-door__brand .iesl-brand__mark { width: auto; height: 44px; }

.iesl .iesl-door__h {
	font-family: var(--display);
	font-size: 30px; font-weight: 600; letter-spacing: .01em;
	margin: 0; color: var(--ink);
}
.iesl .iesl-door__sub { margin: 2px 0 18px; font-size: 13px; color: var(--ink-3); }

.iesl .iesl-door__note {
	margin: 0 0 16px; padding: 10px 12px;
	border-radius: var(--r-sm); font-size: 13px; line-height: 1.45;
	border-left: 3px solid;
}
.iesl .iesl-door__note.is-crit { background: var(--crit-soft); border-color: var(--crit); color: var(--crit-ink); }
.iesl .iesl-door__note.is-warn { background: var(--warn-soft); border-color: var(--warn); color: var(--warn-ink); }
.iesl .iesl-door__note.is-ok   { background: var(--ok-soft);   border-color: var(--ok);   color: var(--ok-ink); }

.iesl .iesl-door__form { display: block; }
.iesl .iesl-door__label {
	display: block; margin: 0 0 5px;
	font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
	color: var(--ink-3);
}
.iesl .iesl-door__input {
	display: block; width: 100%; margin: 0 0 14px;
	min-height: 46px; padding: 11px 13px;
	/* 16px, or a handset zooms the page on focus and never zooms back. */
	font-size: 16px; font-family: inherit; color: var(--ink);
	background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px;
}
.iesl .iesl-door__input:focus {
	outline: none; border-color: var(--green);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--green) 22%, transparent);
}
.iesl .iesl-door__hint { display: block; margin: -9px 0 14px; font-size: 11.5px; color: var(--ink-3); }

.iesl .iesl-door__keep {
	display: flex; align-items: center; gap: 9px;
	margin: 2px 0 18px; font-size: 13px; color: var(--ink-2);
	min-height: 32px; cursor: pointer;
}
.iesl .iesl-door__keep input { width: 18px; height: 18px; accent-color: var(--fill); }

.iesl .iesl-door__go {
	display: block; width: 100%;
	min-height: 48px; padding: 12px 16px;
	font-family: inherit; font-size: 15px; font-weight: 600;
	color: var(--on-fill); background: var(--fill);
	border: 1px solid var(--fill); border-radius: 8px; cursor: pointer;
}
.iesl .iesl-door__go:hover { background: var(--green-deep); border-color: var(--green-deep); }
.iesl .iesl-door__go:focus-visible { outline: 2px solid var(--lime-deep); outline-offset: 2px; }

.iesl .iesl-door__help { margin: 16px 0 0; text-align: center; font-size: 13px; }
.iesl .iesl-door__help a { color: var(--link); }
.iesl .iesl-door__foot {
	margin: 20px 0 0; padding-top: 16px;
	border-top: 1px solid var(--line-soft);
	font-size: 11.5px; line-height: 1.5; color: var(--ink-3);
}

/* ==========================================================================
   Phones
   ==========================================================================
   Written last and read last, so it wins without a single !important.

   The system was laid out for a 1900px admin canvas and then handed to 193
   people who will mostly open it on a handset. Below 900px it is not the same
   layout made smaller: a table stops being a table, a dialog stops being a
   floating box, and anything you have to tap becomes big enough to tap.
   ========================================================================== */

@media (max-width: 900px) {

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

	.iesl.wrap {
		margin: 0;
		padding: 12px 14px 32px;
		border-radius: 0;
	}

	.iesl .iesl-head {
		display: block;
		margin: 2px 0 14px;
	}
	.iesl .iesl-head h1 { font-size: 26px; line-height: 1.15; }

	/*
	 * The page actions were a row that wrapped into a ragged block. On a phone
	 * they are a scrollable strip instead: the primary one stays reachable and
	 * the rest are a thumb-flick away, rather than pushing the content down the
	 * screen before anybody has read anything.
	 */
	.iesl .iesl-head__actions {
		display: flex;
		gap: 8px;
		margin-top: 12px;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		padding-bottom: 2px;
	}
	.iesl .iesl-head__actions::-webkit-scrollbar { display: none; }
	.iesl .iesl-head__actions > * { flex: 0 0 auto; }

	/* The colour switch is a preference, not a task. It goes last. */
	.iesl .iesl-theme { order: 99; }

	/* ------------------------------------------------------------ tiles */

	/*
	 * Two across, never four. Four tiles on a 360px screen gives each one 78
	 * pixels, which is not a figure anybody can read, and the whole point of a
	 * tile is that the number is legible at a glance.
	 */
	.iesl .iesl-stats,
	.iesl .iesl-stats--3,
	.iesl .iesl-stats--4,
	.iesl .iesl-stats--6,
	.iesl .iesl-stats--5 { grid-template-columns: repeat(2, 1fr); gap: 10px; }
	.iesl .iesl-stat { padding: 12px 13px; }
	.iesl .iesl-stat__v { font-size: 26px; }

	/* ------------------------------------------------------------ cards */

	.iesl .iesl-cols { display: block; }
	.iesl .iesl-cols > * + * { margin-top: 14px; }

	.iesl .iesl-panel__h {
		display: block;
		padding: 12px 14px;
	}
	.iesl .iesl-panel__a {
		display: flex;
		flex-wrap: wrap;
		gap: 8px;
		margin-top: 10px;
	}
	.iesl .iesl-panel__b { padding: 12px 14px; }

	/* --------------------------------------------------------- tables */

	/*
	 * A table becomes a stack of cards.
	 *
	 * Horizontal scrolling inside a page that also scrolls vertically is the
	 * worst thing you can hand somebody on a phone: they lose the first column,
	 * which is the one that says whose row it is. Each row becomes a block and
	 * each cell announces its own column from the data-label the table writes.
	 */
	.iesl .iesl-tablewrap { overflow: visible; }
	.iesl .iesl-table,
	.iesl .iesl-table tbody,
	.iesl .iesl-table tr,
	.iesl .iesl-table td { display: block; width: auto; }

	.iesl .iesl-table thead { display: none; }

	.iesl .iesl-table tr {
		border: 1px solid var(--line);
		border-radius: var(--r-sm);
		background: var(--surface);
		padding: 4px 0;
		margin: 0 0 10px;
	}
	.iesl .iesl-table tr:last-child { margin-bottom: 0; }

	.iesl .iesl-table td {
		display: flex;
		justify-content: space-between;
		align-items: baseline;
		gap: 14px;
		padding: 7px 13px;
		border: 0;
		text-align: right;
	}
	.iesl .iesl-table td::before {
		content: attr(data-label);
		flex: 0 0 auto;
		text-align: left;
		font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
		color: var(--ink-3); font-weight: 600;
	}
	/* A cell with no column name, such as a row of buttons, spans the card. */
	.iesl .iesl-table td[data-label=""] {
		justify-content: flex-end;
		padding-top: 4px;
	}
	.iesl .iesl-table td[data-label=""]::before { content: none; }
	.iesl .iesl-table td.is-num { text-align: right; }

	/* The empty state is one cell and must not be squeezed into a label row. */
	.iesl .iesl-table td[colspan] { display: block; text-align: center; }
	.iesl .iesl-table td[colspan]::before { content: none; }

	/* ---------------------------------------------------------- dialogs */

	/*
	 * A dialog becomes a sheet that fills the screen from the bottom. A
	 * centred floating box on a handset leaves its own actions below the fold
	 * and its top edge under the browser chrome.
	 */
	.iesl dialog.iesl-modal {
		width: 100%;
		max-width: none;
		max-height: 92vh;
		margin: auto 0 0;
		border-radius: var(--r) var(--r) 0 0;
	}
	.iesl .iesl-modal__b { padding: 14px; }

	/* -------------------------------------------------------- reaching */

	/*
	 * Anything you tap is at least 44 pixels tall. Smaller than that and the
	 * person misses it, taps the row behind it, and learns not to trust the
	 * screen.
	 */
	.iesl .iesl-btn {
		min-height: 44px;
		padding: 11px 16px;
		font-size: 14px;
	}
	.iesl .iesl-btn--sm { min-height: 38px; padding: 8px 12px; }
	.iesl .iesl-field input,
	.iesl .iesl-field select,
	.iesl .iesl-field textarea {
		min-height: 44px;
		/* 16px or the browser zooms the page on focus and never zooms back. */
		font-size: 16px;
	}
	.iesl .iesl-inline-check input { width: 20px; height: 20px; }

	/* The form grid is one column on a phone whatever a field asked for. */
	.iesl .iesl-fields,
	.iesl .iesl-fields--form { grid-template-columns: 1fr; }
	.iesl .iesl-fields--form > .iesl-field { grid-column: 1 / -1; }

	/* Key and value stack rather than sharing a line that fits neither. */
	.iesl .iesl-kv { grid-template-columns: 1fr; gap: 0; }
	.iesl .iesl-kv dt { padding-top: 10px; }
	.iesl .iesl-kv dd { padding-bottom: 10px; border-bottom: 1px solid var(--line-soft); }

	/*
	 * Sticky, and it scrolls sideways rather than wrapping: four labels on a
	 * 360px screen would otherwise take three rows off the top of the record.
	 */
	.iesl .iesl-jumps {
		position: sticky; top: 0; z-index: 20;
		flex-wrap: nowrap; overflow-x: auto;
		-webkit-overflow-scrolling: touch; scrollbar-width: none;
		margin: 0 -14px 14px; padding: 9px 14px;
		background: var(--ground);
		box-shadow: 0 1px 0 var(--line);
	}
	.iesl .iesl-jumps::-webkit-scrollbar { display: none; }
	.iesl .iesl-jumps__l { flex: 0 0 auto; min-height: 34px; display: inline-flex; align-items: center; }
	.iesl .iesl-sec { scroll-margin-top: 58px; }

	/*
	 * One card across. Two at 360px gives each one 160 pixels, which truncates
	 * the name, which is the only thing on it that matters.
	 */
	.iesl .iesl-cards { grid-template-columns: 1fr; gap: 10px; }

	/*
	 * The diagram keeps its three rows and gives up its width. Two boxes across
	 * at 360px, which is the most that leaves a readable label.
	 */
	.iesl .iesl-shape__row { gap: 6px; }
	.iesl .iesl-shape__box { padding: 7px 10px 7px 7px; gap: 7px; max-width: calc(50% - 3px); }
	.iesl .iesl-shape__av { width: 26px; height: 26px; font-size: 10px; }
	.iesl .iesl-shape__box b { font-size: 12px; }
	.iesl .iesl-shape__box small { font-size: 11px; }
	.iesl .iesl-shape__line { height: 16px; }

	/*
	 * The tree keeps its shape on a handset and gives up its box width. It is
	 * the one screen here that is genuinely a desktop thing; what a phone needs
	 * from it is the ability to pan around and read a name, which it has.
	 */
	.iesl .iesl-tree__pane { max-height: 70vh; padding: 16px 10px 20px; }
	.iesl .iesl-tree__box { width: 152px; min-height: 44px; padding: 7px 9px 7px 7px; gap: 7px; }
	.iesl .iesl-tree__av { width: 24px; height: 24px; font-size: 9.5px; }
	.iesl .iesl-tree__bar { padding: 8px 10px; }

	/* ----------------------------------------------------- portal chrome */

	/*
	 * The rail is the wrong shape for a handset, so it goes and the same
	 * sections come back along the bottom where a thumb can reach them. An
	 * employee sees four or five and never opens the sheet; HR sees four and a
	 * More that lifts the rest into view. It is a details element, so it opens
	 * and closes with no scripting.
	 */
	.iesl-app { grid-template-columns: 1fr; height: auto; }
	.iesl-rail { display: none; }
	.iesl-main { overflow: visible; }
	.iesl-scroll { overflow: visible; padding: 14px 0 0; }
	.iesl-topbar { padding: 9px 14px; position: sticky; top: 0; z-index: 30; }
	.iesl-topbar__name { display: none; }
	.iesl-topbar__link { padding: 9px 11px; }

	.iesl-portal__tabs {
		display: flex;
		position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
		background: var(--c-surface);
		border-top: 1px solid var(--c-line);
		padding-bottom: env(safe-area-inset-bottom);
	}
	.iesl-portal__tab {
		flex: 1 1 0; min-width: 0;
		display: flex; flex-direction: column; align-items: center; justify-content: center;
		gap: 3px; padding: 8px 2px 7px;
		min-height: 54px;
		font-size: 10.5px; font-weight: 500; letter-spacing: .01em;
		color: var(--c-ink-3); text-decoration: none;
		border-top: 2px solid transparent; margin-top: -1px;
		list-style: none; cursor: pointer;
	}
	.iesl-portal__tab::-webkit-details-marker { display: none; }
	.iesl-portal__tab span {
		max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	}
	.iesl-portal__tab.is-here,
	.iesl-portal__more.is-here > .iesl-portal__tab {
		color: var(--c-accent); border-top-color: var(--c-accent); font-weight: 600;
	}
	.iesl-portal__icon { flex: 0 0 auto; }

	.iesl-portal__more { flex: 1 1 0; min-width: 0; position: relative; }
	.iesl-portal__more > .iesl-portal__tab { width: 100%; }
	.iesl-portal__sheet {
		position: absolute; bottom: 100%; right: 0;
		min-width: 190px; max-width: 70vw;
		background: var(--c-surface);
		border: 1px solid var(--c-line); border-radius: 10px 10px 0 0;
		box-shadow: 0 -10px 30px -14px rgba(16,32,26,.35);
		padding: 6px;
		max-height: 60vh; overflow-y: auto;
	}
	.iesl-portal__sheetlink {
		display: flex; align-items: center; gap: 10px;
		padding: 12px 12px; min-height: 44px;
		font-size: 14px; color: var(--c-ink); text-decoration: none;
		border-radius: 7px;
	}
	.iesl-portal__sheetlink.is-here { color: var(--c-accent); background: var(--c-accent-soft); font-weight: 600; }

	/* Room for the bar, so the last row of a table is never under it. */
	body.iesl-portal .iesl-portal__body,
	body.iesl-portal .iesl.wrap { padding-bottom: calc(76px + env(safe-area-inset-bottom)); }

	/* The door has no bottom bar and wants none of that padding. */
	body.iesl-portal--door .iesl-door { padding-bottom: 24px; }

}

/* ============================================================== payslips */

/*
 * Six designs, two shapes, one set of colours.
 *
 * The shapes are the substantive half. IESL pays overtime separately from
 * salary, so somebody can be paid twice in a month for two different things,
 * and a single document that adds them together shows a gross nobody received
 * in one transfer while hiding the hours and the rate that are the only things
 * an overtime payment is ever checked against. Every design therefore renders
 * in both, and the overtime shape says on its face that it is not the salary.
 *
 * Every colour here is a token. A payslip is the one screen in this system
 * that is printed and emailed as often as it is read, so it has to survive
 * both schemes and a printer, and a hex written into a template would drift
 * from the rest of the system the first time the palette moved.
 */
.iesl .iesl-slip {
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r);
	padding: 24px 26px 20px;
	max-width: 760px;
	color: var(--ink);
	font-size: 13px; line-height: 1.5;
}

.iesl .iesl-slip__head {
	display: flex; align-items: flex-start; justify-content: space-between;
	gap: 18px; flex-wrap: wrap;
	padding-bottom: 16px; margin-bottom: 16px;
	border-bottom: 2px solid var(--fill);
}
.iesl .iesl-slip__brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
.iesl .iesl-slip__mark { width: auto; }
.iesl .iesl-slip__co { display: flex; flex-direction: column; min-width: 0; }
.iesl .iesl-slip__co b {
	font-family: var(--display); font-size: 16px; font-weight: 600;
	letter-spacing: .01em; color: var(--ink);
}
.iesl .iesl-slip__co small { font-size: 11.5px; color: var(--ink-3); }

.iesl .iesl-slip__what { text-align: right; min-width: 0; }
.iesl .iesl-slip__kind {
	margin: 0; font-family: var(--display); font-size: 19px; font-weight: 600;
	letter-spacing: .02em; text-transform: uppercase; color: var(--fill);
}
.iesl .iesl-slip__period { margin: 1px 0 0; font-size: 13px; color: var(--ink-2); }

/* The line that stops somebody reading an overtime payment as their salary. */
.iesl .iesl-slip__aside {
	margin: 5px 0 0; display: inline-block;
	padding: 2px 8px; border-radius: 999px;
	background: var(--warn-soft); color: var(--ot-ink);
	font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
}

.iesl .iesl-slip__who { display: flex; flex-wrap: wrap; gap: 10px 28px; margin-bottom: 18px; }
.iesl .iesl-slip__pairs { display: flex; flex-wrap: wrap; gap: 10px 22px; margin: 0; }
.iesl .iesl-slip__pairs div { min-width: 0; }
.iesl .iesl-slip__pairs dt {
	font-size: 10px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3);
}
.iesl .iesl-slip__pairs dd { margin: 1px 0 0; font-size: 13px; color: var(--ink); }

.iesl .iesl-slip__body { display: grid; grid-template-columns: 1fr; gap: 18px; }

/*
 * auto-fit rather than two fixed columns, so the split collapses when there is
 * not room for it.
 *
 * The first version said 1fr 1fr and held two columns open at any width. In
 * the design previews, where two payslips sit side by side, a landscape page
 * was squeezed to 441px and its columns to 180px each: the document was
 * present, correctly classed and completely unreadable, which reads as nothing
 * having happened. The viewport media query below could not help, because the
 * page was wide and the box inside it was not.
 */
.iesl .iesl-slip__body--split { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

.iesl .iesl-slip__col h3 {
	margin: 0 0 7px;
	font-family: var(--display); font-size: 12px; font-weight: 600;
	letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
}
/* Earnings is the column the other two are read against, so it keeps the
   ordinary heading colour. Written down rather than left absent: a modifier
   with no rule is indistinguishable from a misspelt one, and this file is
   checked for exactly that. */
.iesl .iesl-slip__col--earn h3 { color: var(--ink); }
.iesl .iesl-slip__col--take h3 { color: var(--red-ink); }
.iesl .iesl-slip__col--cost h3 { color: var(--lime-ink); }
.iesl .iesl-slip__none { margin: 0; color: var(--ink-3); font-size: 12.5px; }

.iesl .iesl-slip__table { width: 100%; border-collapse: collapse; }
.iesl .iesl-slip__table th,
.iesl .iesl-slip__table td {
	padding: 6px 0; text-align: left; font-weight: 400; vertical-align: top;
	border-bottom: 1px solid var(--line-soft);
}
.iesl .iesl-slip__table td { text-align: right; font-family: var(--mono); font-size: 12.5px; white-space: nowrap; }
.iesl .iesl-slip__table th small { display: block; font-size: 10.5px; color: var(--ink-3); }
.iesl .iesl-slip__table tfoot th,
.iesl .iesl-slip__table tfoot td {
	border-bottom: 0; border-top: 1px solid var(--line);
	font-weight: 600; color: var(--ink);
}

.iesl .iesl-slip__employer { margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--line); }

.iesl .iesl-slip__net {
	display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
	margin-top: 18px; padding: 13px 16px; border-radius: var(--r-sm);
	background: var(--fill); color: var(--on-fill);
}
.iesl .iesl-slip__net-label {
	font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
}
.iesl .iesl-slip__net-figure {
	font-family: var(--display); font-size: 25px; font-weight: 700; letter-spacing: .01em;
}

.iesl .iesl-slip__foot { margin-top: 16px; }
.iesl .iesl-slip__basis {
	padding: 12px 14px; border-radius: var(--r-sm);
	background: var(--surface-2); border: 1px solid var(--line-soft);
}
.iesl .iesl-slip__note { margin: 8px 0 0; font-size: 11.5px; color: var(--ink-3); }
.iesl .iesl-slip__sign { margin: 22px 0 10px; }
.iesl .iesl-slip__rule { display: block; width: 210px; border-top: 1px solid var(--ink-3); }
.iesl .iesl-slip__sign p { margin: 5px 0 0; font-size: 11.5px; color: var(--ink-3); }
.iesl .iesl-slip__issued { margin: 12px 0 0; font-size: 11px; color: var(--ink-3); }

/* ---------------------------------------------------- the six, by design */

/* Ledger: two facing columns, each reconciling on its own. */
.iesl .iesl-slip--ledger .iesl-slip__col--take { border-left: 1px solid var(--line-soft); padding-left: 18px; }

/* Compact: three hundred of these go through a printer. */
/* The three defaults: classic design, salary shape, portrait page. Every other
   value of each carries overrides below; these three are what the base .iesl-slip
   already is, and they are written down so that a modifier with no rule always
   means a mistake rather than sometimes meaning "as intended". */
.iesl .iesl-slip--classic,
.iesl .iesl-slip--salary,
.iesl .iesl-slip--portrait { /* base .iesl-slip, deliberately */ }

.iesl .iesl-slip--compact { padding: 16px 18px 14px; font-size: 12px; max-width: 620px; }
.iesl .iesl-slip--compact .iesl-slip__kind { font-size: 15px; }
.iesl .iesl-slip--compact .iesl-slip__net { padding: 9px 12px; }
.iesl .iesl-slip--compact .iesl-slip__net-figure { font-size: 20px; }
.iesl .iesl-slip--compact .iesl-slip__table th,
.iesl .iesl-slip--compact .iesl-slip__table td { padding: 3px 0; }

/* Card: the net figure first, because on a phone it is the whole question. */
.iesl .iesl-slip--card { max-width: 420px; padding: 20px; }
.iesl .iesl-slip--card .iesl-slip__head { display: block; border-bottom: 0; padding-bottom: 10px; }
.iesl .iesl-slip--card .iesl-slip__what { text-align: left; margin-top: 12px; }
.iesl .iesl-slip--card .iesl-slip__net {
	margin: 14px 0 18px; flex-direction: column; align-items: flex-start; gap: 2px;
}
.iesl .iesl-slip--card .iesl-slip__net-figure { font-size: 31px; }
.iesl .iesl-slip--card .iesl-slip__who { gap: 8px 18px; }

/* Formal: letterhead proportions, for an institution. */
.iesl .iesl-slip--formal { padding: 34px 36px 26px; }
.iesl .iesl-slip--formal .iesl-slip__head { border-bottom-width: 3px; padding-bottom: 20px; }
.iesl .iesl-slip--formal .iesl-slip__kind { letter-spacing: .14em; }

/* Detailed: the arithmetic is the point, so nothing is folded away. */
.iesl .iesl-slip--detailed .iesl-slip__table th { padding-right: 12px; }

/* Overtime, in any design: the accent moves off green so the two documents
 * are never mistaken for each other at a glance on a desk. */
.iesl .iesl-slip--overtime .iesl-slip__head { border-bottom-color: var(--fill-ot); }
.iesl .iesl-slip--overtime .iesl-slip__kind { color: var(--ot-ink); }
.iesl .iesl-slip--overtime .iesl-slip__net { background: var(--fill-ot); color: var(--on-fill-ot); }

@media (max-width: 720px) {
	.iesl .iesl-slip { padding: 18px 16px 16px; }
	.iesl .iesl-slip__body--split { grid-template-columns: 1fr; }
	.iesl .iesl-slip--ledger .iesl-slip__col--take { border-left: 0; padding-left: 0; }
	.iesl .iesl-slip__what { text-align: left; }
}

@media print {
	.iesl .iesl-slip { border: 0; padding: 0; max-width: none; }
	.iesl .iesl-slip__net { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

.iesl .iesl-slips { display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-start; margin: 4px 0 6px; }
.iesl .iesl-slips .iesl-slip { flex: 1 1 340px; }

/* ------------------------------------------------- portrait and landscape */

/*
 * Orientation is a property of the page, not of the design, so both are
 * offered for all six rather than there being landscape designs and portrait
 * ones.
 *
 * Landscape is not the same document turned sideways. A wide page with a
 * single stacked list down the middle wastes the paper and makes the reader's
 * eye travel further than the portrait one it replaced, so the columns face
 * each other and the header spreads out. What it buys: a payslip with twenty
 * component lines fits on one sheet instead of two, and a run of three hundred
 * printed two-up lands on half the paper.
 */
.iesl .iesl-slip--landscape { max-width: 1040px; }

/*
 * A landscape preview gets a row to itself.
 *
 * The previews are laid out side by side, which is right for portrait pages
 * and wrong for a landscape one: two wide documents in one row leaves each of
 * them narrower than the portrait page they are meant to be an alternative to,
 * which is the opposite of what is being shown.
 */
.iesl .iesl-slips .iesl-slip--landscape { flex: 1 1 100%; max-width: 100%; }
.iesl .iesl-slip--landscape .iesl-slip__who { gap: 10px 40px; }
.iesl .iesl-slip--landscape .iesl-slip__body--split { gap: 28px; }
.iesl .iesl-slip--landscape .iesl-slip__col--take { border-left: 1px solid var(--line-soft); padding-left: 24px; }

/* The net figure sits beside the breakdown rather than under it, because on a
 * wide page there is room and it is the first thing looked for. */
.iesl .iesl-slip--landscape .iesl-slip__net { margin-top: 16px; }

/* The card design is built for a phone and has no landscape to offer; asked
 * for one, it stays as it is rather than stretching into an unreadable line. */
.iesl .iesl-slip--card.iesl-slip--landscape { max-width: 420px; }
.iesl .iesl-slip--card.iesl-slip--landscape .iesl-slip__body--split { grid-template-columns: 1fr; }
.iesl .iesl-slip--card.iesl-slip--landscape .iesl-slip__col--take { border-left: 0; padding-left: 0; }

@media print {
	/* The real reason landscape exists: the sheet itself turns. */
	.iesl .iesl-slip--landscape { page-break-inside: avoid; }
}

@page { margin: 14mm; }

/* The address, the hours banner, and a line that shows its arithmetic. */

.iesl .iesl-slip__addr { display: block; margin-top: 2px; font-size: 11px; color: var(--ink-3); line-height: 1.4; }

/*
 * Hours first, and large, on an overtime document.
 *
 * The payment follows from the hours, so the hours are what the page leads
 * with. A page that leads with the money and puts the hours in small print is
 * asking the reader to take the arithmetic on trust, which is exactly what an
 * overtime payment is queried about.
 */
.iesl .iesl-slip__hours {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
	gap: 12px; margin-bottom: 18px;
	padding: 13px 16px; border-radius: var(--r-sm);
	background: var(--surface-2); border: 1px solid var(--line);
}
.iesl .iesl-slip__hours div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.iesl .iesl-slip__hours span {
	font-size: 10px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3);
}
.iesl .iesl-slip__hours b {
	font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--ink);
}

/* The overtime banner takes the gold, so the page reads as one document. */
.iesl .iesl-slip--overtime .iesl-slip__hours { border-color: var(--fill-ot); }

/* The working under a line: eleven and a half hours at seven thousand five. */
.iesl .iesl-slip__calc {
	display: block; margin-top: 1px;
	font-family: var(--mono); font-size: 10.5px; color: var(--ink-3);
}

/* A shortfall, said in words rather than shown as a minus sign. */
.iesl .iesl-slip__shortfall {
	margin: 8px 0 0; padding: 9px 12px; border-radius: var(--r-sm);
	background: var(--warn-soft); color: var(--ink-2);
	font-size: 11.5px; line-height: 1.45;
}

/* ------------------------------------------------------------ working panel */

/*
 * What a long action looks like while it runs.
 *
 * Computing a month reads 186 employees, runs a tax calculation for each and
 * writes their payslip lines. The first attempt at feedback changed the
 * button's wording, which on the run screen sits below five statistics and a
 * table: somebody who has scrolled sees nothing at all, concludes the click
 * did not land, and clicks again.
 *
 * Over the page, then. It cannot be dismissed, which is also what stops the
 * second click, and it goes when the answer arrives as a new page.
 */
.iesl-working {
	position: fixed; inset: 0; z-index: 100000;
	display: flex; align-items: center; justify-content: center;
	padding: 24px;
	background: rgba(16, 32, 26, .55);
	-webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.iesl-working__card {
	display: flex; flex-direction: column; align-items: center; gap: 10px;
	max-width: 30rem; padding: 28px 30px;
	background: var(--surface, #FFF); color: var(--ink, #10201A);
	border-radius: 12px; text-align: center;
	box-shadow: 0 24px 60px -20px rgba(16, 32, 26, .5);
	font-family: var(--body, system-ui, sans-serif);
}
.iesl-working__title { font-size: 15px; font-weight: 600; }
.iesl-working__detail,
.iesl-working__slow { font-size: 13px; line-height: 1.5; color: var(--ink-3, #5F7168); }
.iesl-working__slow { font-weight: 600; color: var(--ot-ink, #7A5C00); }

.iesl-working__spin {
	width: 30px; height: 30px; border-radius: 50%;
	border: 3px solid var(--line, #DCE3DB);
	border-top-color: var(--fill, #016535);
	animation: iesl-spin .9s linear infinite;
}

@keyframes iesl-spin { to { transform: rotate(360deg); } }

/*
 * Still legible without the animation. Somebody who has asked for no motion
 * still needs to know the page is busy, so the ring stays and stops turning.
 */
@media (prefers-reduced-motion: reduce) {
	.iesl-working__spin { animation: none; border-top-color: var(--fill, #016535); }
	.iesl-working { -webkit-backdrop-filter: none; backdrop-filter: none; }
}

.iesl .iesl-banner:focus-visible { outline: 2px solid var(--lime-deep); outline-offset: 3px; }

/* ---------------------------------------------------------------------------
   The organogram on the departments screen.

   A sub-department is a row in the same table as its department rather than a
   nested table, because a nested table cannot be read across on a phone and
   loses its column headings the moment it wraps. The indent and the turned
   arrow are what carry the relationship, and they survive a narrow screen.
   --------------------------------------------------------------------------- */
.iesl .iesl-sub {
	display: inline-flex;
	align-items: baseline;
	gap: 6px;
	padding-left: 18px;
	color: var(--ink-2);
}

.iesl .iesl-sub code { font-size: 11px; }

@media (max-width: 640px) {
	.iesl .iesl-sub { padding-left: 10px; }
}

/* A unit that answers to a manager rather than straight to the department. */
.iesl .iesl-sub--deep { padding-left: 38px; }

@media (max-width: 640px) {
	.iesl .iesl-sub--deep { padding-left: 22px; }
}

/* A labelled row of small buttons: one of a set, and which one is showing. */
.iesl .iesl-switch {
	display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
	margin: 0 0 12px;
	font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
	color: var(--ink-3);
}

/* ---------------------------------------------------------------------------
   The approved organogram, drawn.

   Every rule here is about one thing: the sheet has to read at the size it is
   drawn, because the whole reason for drawing it rather than laying it out is
   that fifteen departments fit across a page only when a box is a hundred
   points wide with the name wrapped inside it.
   --------------------------------------------------------------------------- */
.iesl svg.iesl-sheet { display: block; max-width: none; }

.iesl .iesl-sheet__lines path {
	stroke: var(--ink-3); stroke-width: 1.2; fill: none;
}
.iesl .iesl-sheet__lines path.is-dotted { stroke-dasharray: 5 4; }

.iesl .iesl-sheet .b rect { fill: var(--surface); stroke: var(--fill); stroke-width: 1.1; }
.iesl .iesl-sheet .b text {
	text-anchor: middle; font-family: var(--body); fill: var(--ink);
}
.iesl .iesl-sheet .b .t { font-weight: 700; fill: var(--fill); }
.iesl .iesl-sheet .b .s { font-weight: 400; fill: var(--ink-2); }
/* An empty seat, said in the box rather than left as a blank line under a name. */
.iesl .iesl-sheet .b .s--gap { fill: var(--warn-ink); font-style: italic; }

/* A department box is the way through to the people in it. */
.iesl .iesl-sheet a.b-open { cursor: pointer; }
.iesl .iesl-sheet a.b-open:hover rect,
.iesl .iesl-sheet a.b-open:focus-visible rect { stroke: var(--green); stroke-width: 2; }
.iesl .iesl-sheet a.b-open:focus-visible { outline: 2px solid var(--lime-deep); outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   Moving a box.

   Three states and nothing more: a box that can be picked up says so with the
   cursor, the pane says a move is in progress, and the one box under the
   pointer that will accept it is outlined. Anything more elaborate would be
   animating a change that has not happened yet: the drop fills the dialog in
   and the person still presses the button.
   --------------------------------------------------------------------------- */
.iesl [data-iesl-drag] { cursor: grab; }
.iesl .iesl-tree__pane.is-moving { cursor: grabbing; }
.iesl .iesl-tree__pane.is-moving [data-iesl-drag] { cursor: grabbing; }

.iesl .iesl-sheet .b.is-target rect { stroke: var(--green); stroke-width: 2.4; }
.iesl .iesl-tree__box.is-target {
	border-color: var(--green);
	box-shadow: 0 0 0 2px var(--ok-soft);
}
.iesl .iesl-sheet .b .n {
	text-anchor: end; font-size: 7px; font-weight: 500; fill: var(--ink-3);
}

.iesl .iesl-sheet .b--board rect { fill: var(--fill); stroke: var(--fill); }
.iesl .iesl-sheet .b--board .t,
.iesl .iesl-sheet .b--board .s { fill: var(--on-fill); }

.iesl .iesl-sheet .b--md rect,
.iesl .iesl-sheet .b--office rect { fill: var(--ok-soft); }

.iesl .iesl-sheet .b--unit rect { fill: var(--surface-2); stroke: var(--line); }
.iesl .iesl-sheet .b--unit .t { font-weight: 400; fill: var(--ink); }

/* ---------------------------------------------------------------------------
   Careers site (public)

   The pages CareersFrame.php wraps: body carries iesl-careers and a single
   .iesl child, so the tokens are one level down and the body itself must not
   read them. Phone first: one column, 44px touch targets, the primary Apply
   button full width; from 782px the column settles at a readable width.
   --------------------------------------------------------------------------- */

body.iesl-careers { margin: 0; }

body.iesl-careers > .iesl {
	min-height: 100vh;
	background: var(--ground);
}

.iesl .iesl-careers-head,
.iesl .iesl-careers-main,
.iesl .iesl-careers-foot {
	padding: 15px;
}

@media (min-width: 782px) {
	.iesl .iesl-careers-head,
	.iesl .iesl-careers-main,
	.iesl .iesl-careers-foot {
		max-width: 72rem;
		margin-left: auto;
		margin-right: auto;
	}
}

/* The logo plate: white in both themes, as the staff rail's is -- the mark
   is drawn in dark green and disappears on a dark surface. */
.iesl .iesl-careers-plate {
	display: inline-flex;
	align-items: center;
	background: #fff;
	border: 1px solid var(--line);
	border-radius: var(--r-sm);
	padding: 8px;
}

/* With no logo uploaded the plate holds the short name as text. The plate is
   white in both themes, so the text is the logo green in both (7.21), not
   --green, which turns pale in the dark theme. */
.iesl .iesl-careers-plate .iesl-brand__text {
	color: #016535;
	font-weight: 700;
}

.iesl .iesl-careers-plate img,
.iesl .iesl-careers-plate svg {
	display: block;
	height: 34px;
	width: auto;
}

.iesl .iesl-careers-main {
	padding-top: 6px;
	padding-bottom: 24px;
}

.iesl .iesl-careers-foot {
	color: var(--ink-3);
	font-size: 13px;
	border-top: 1px solid var(--line-soft);
	margin-top: 24px;
}

.iesl .iesl-careers-foot a { color: var(--link); }

/* Touch targets: a link or a button is at least a fingertip tall. */
.iesl .iesl-careers-foot a,
.iesl .iesl-careers-card h2 a,
.iesl .iesl-careers-filters .iesl-btn {
	justify-content: center;
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

/* The hero at the top of the list: engineers at work in Abuja (Pexels,
   free licence, careers-hero.jpg) under the logo green at 60%, and the
   logo's lime, gold and red as one rule along its top edge. The words sit
   on a deeper green scrim down the left, because at 60% alone the white
   hard hats behind them leave white text under 4.5. */
.iesl .iesl-hero {
	position: relative;
	overflow: hidden;
	display: flex;
	align-items: flex-end;
	min-height: 420px;
	margin: 0 0 32px;
	padding: 36px 20px 28px;
	border-radius: var(--r);
	background:
		linear-gradient(0deg, rgba(1, 74, 38, .92) 0%, rgba(1, 74, 38, .85) 55%, rgba(1, 74, 38, .62) 100%),
		linear-gradient(rgba(1, 101, 53, .6), rgba(1, 101, 53, .6)),
		var(--green-deep) url("careers-hero-800.jpg") 60% 30% / cover no-repeat;
	color: #F4F8F3;
}

@media (min-width: 782px) {
	.iesl .iesl-hero {
		align-items: center;
		min-height: 460px;
		background:
			linear-gradient(90deg, rgba(1, 74, 38, .92) 0%, rgba(1, 74, 38, .84) 48%, rgba(1, 74, 38, 0) 78%),
			linear-gradient(rgba(1, 101, 53, .6), rgba(1, 101, 53, .6)),
			var(--green-deep) url("careers-hero.jpg") 70% 35% / cover no-repeat;
	}
}

.iesl .iesl-hero::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 4px;
	background: linear-gradient(90deg, var(--lime) 0 55%, var(--gold) 55% 80%, var(--red) 80% 100%);
}

.iesl .iesl-hero__eyebrow {
	margin: 0 0 10px;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: #B5DA6A;              /* the lime lifted a step, so it holds 4.5 over the photograph too */
}

.iesl .iesl-hero__title {
	margin: 0;
	font-family: var(--display);
	font-size: 40px;
	font-weight: 600;
	line-height: 1.04;
	color: #F4F8F3;
	max-width: 16ch;
}

.iesl .iesl-hero__lede {
	margin: 14px 0 22px;
	max-width: 46ch;
	font-size: 16px;
	line-height: 1.55;
	color: #CFE3D6;              /* 8.6 on --green-deep */
}

.iesl .iesl-hero__cta {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 20px;
	border-radius: var(--r-sm);
	background: #F4F8F3;
	color: var(--green-deep);     /* 9.9 */
	font-weight: 600;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .16s ease, transform .16s ease;
}

.iesl .iesl-hero__cta:hover { background: var(--lime); color: var(--ink); }
.iesl .iesl-hero__cta:active { transform: translateY(1px); }
.iesl .iesl-hero__cta:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

.iesl .iesl-hero__copy { position: relative; max-width: 36rem; }

@media (min-width: 782px) {
	.iesl .iesl-hero { padding: 56px 48px; }
	.iesl .iesl-hero__title { font-size: 58px; }
}

/* The open roles under it. */
.iesl .iesl-careers-roles { scroll-margin-top: 16px; }
.iesl .iesl-careers-roles__h {
	margin: 0 0 4px;
	font-family: var(--display);
	font-size: 26px;
	font-weight: 600;
	color: var(--ink);
}
.iesl .iesl-careers-roles__tally { margin: 0 0 14px; color: var(--ink-2); }
.iesl .iesl-careers-roles__num { font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--green); }

/* A vacancy, or one application on the applicant's own page. */
.iesl .iesl-careers-card { width: 100%; }

/* A vacancy in the list: the whole card is the link, by the title's link
   stretched over it, and it lifts a little under the pointer. */
.iesl .iesl-careers-card--link {
	position: relative;
	transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.iesl .iesl-careers-card--link h3 {
	margin: 0 0 4px;
	font-family: var(--display);
	font-size: 22px;
	font-weight: 600;
}
.iesl .iesl-careers-card--link h3 a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: var(--ink);
	text-decoration: none;
	cursor: pointer;
}
.iesl .iesl-careers-card--link h3 a::after { content: ""; position: absolute; inset: 0; border-radius: var(--r); }
.iesl .iesl-careers-card--link:hover { border-color: var(--green); box-shadow: var(--shadow); }
.iesl .iesl-careers-card--link:hover h3 a { color: var(--green); }
.iesl .iesl-careers-card--link:focus-within { outline: 2px solid var(--green); outline-offset: 2px; }
.iesl .iesl-careers-card--link h3 a:focus-visible { outline: none; }
.iesl .iesl-careers-card__meta,
.iesl .iesl-careers-card__close { margin: 0; color: var(--ink-2); }
.iesl .iesl-careers-card__close { margin-top: 6px; font-size: 13px; }

@media (prefers-reduced-motion: no-preference) {
	.iesl .iesl-careers-card--link:hover { transform: translateY(-2px); }
}

@media (min-width: 782px) {
	.iesl .iesl-careers-card--link .iesl-panel__b {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		column-gap: 24px;
		align-items: center;
	}
	.iesl .iesl-careers-card--link h3,
	.iesl .iesl-careers-card--link .iesl-careers-card__meta { grid-column: 1; }
	.iesl .iesl-careers-card--link .iesl-careers-card__close { grid-column: 2; grid-row: 1 / span 2; margin: 0; text-align: right; }
}

/* Its title sits at the top of the card; the card's own padding is the only
   space above it. */
.iesl .iesl-careers-card h2 { margin-top: 0; }

/* The GET form that filters the list. */
.iesl .iesl-careers-filters {
	display: flex;
	flex-direction: column;
	gap: 8px;
	margin: 0 0 16px;
	padding: 14px;
	background: var(--surface);
	border: 1px solid var(--line);
	border-radius: var(--r);
}

.iesl .iesl-careers-filters .iesl-field,
.iesl .iesl-careers-filters > p { margin: 0; }
.iesl .iesl-careers-filters label { color: var(--ink-2); font-size: 13px; }
.iesl .iesl-careers-filters input[type="text"],
.iesl .iesl-careers-filters select {
	width: 100%;
	min-height: 44px;
}

@media (min-width: 782px) {
	.iesl .iesl-careers-filters {
		flex-direction: row;
		align-items: flex-end;
		flex-wrap: wrap;
		gap: 12px;
	}
	.iesl .iesl-careers-filters input[type="text"],
	.iesl .iesl-careers-filters select { width: auto; }
	/* Search takes the rest of the row, so the bar has no empty right half. */
	.iesl .iesl-careers-filters .iesl-field:first-child { flex: 1 1 16rem; }
	.iesl .iesl-careers-filters .iesl-field:first-child input[type="text"] { width: 100%; }
}

/* The primary action fills the column on a phone, where a thumb is. */
.iesl .iesl-careers-main .iesl-btn--pri,
.iesl .iesl-careers-main .iesl-btn--go {
	display: flex;
	justify-content: center;
	align-items: center;
	width: 100%;
	min-height: 44px;
}

@media (min-width: 782px) {
	.iesl .iesl-careers-main .iesl-btn--pri,
	.iesl .iesl-careers-main .iesl-btn--go {
		display: inline-flex;
		width: auto;
	}
}

/* A yes/no question: no browser default fieldset chrome, the legend reads
   like the labels beside it, and each radio label is a fingertip tall. */
.iesl .iesl-careers-choice {
	border: 0;
	padding: 0;
	margin: 0 0 14px;
}

.iesl .iesl-careers-choice legend {
	font-size: 13px;
	color: var(--ink-2);
	padding: 0;
	margin: 0 0 5px;
}

.iesl .iesl-careers-choice label {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-right: 12px;
}

/* Dates and other set-width figures. */
.iesl .iesl-careers-mono { font-family: var(--mono); white-space: nowrap; } /* a date never breaks across lines */

/* A field error, in the red the banners already use for crit. */
.iesl .iesl-careers-error { color: var(--crit-ink); margin: 4px 0 0; }

/* The honeypot: out of reach, not display:none, which bots check for. */
.iesl-careers-hp {
	position: absolute;
	left: -10000px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* For screen readers only. */
.iesl .iesl-careers-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* Type to search, on any long single list (Oct 2026). */
.iesl .iesl-combo { position: relative; }
.iesl .iesl-combo .iesl-combo__select { position: absolute; left: 0; bottom: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.iesl .iesl-combo .iesl-combo__q { width: 100%; padding-right: 30px; background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%); background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
.iesl .iesl-combo__list { position: absolute; z-index: 10050; left: 0; right: 0; top: calc(100% + 2px); max-height: 280px; overflow-y: auto; margin: 0; padding: 4px 0; list-style: none; background: var(--surface, #fff); color: var(--ink, #1c2520); border: 1px solid var(--line, #cfd8d3); border-radius: var(--r-sm, 6px); box-shadow: var(--shadow, 0 8px 24px rgba(0,0,0,.18)); }
.iesl .iesl-combo__list[hidden] { display: none !important; }
.iesl .iesl-combo__list li { padding: 7px 12px; cursor: pointer; font-size: 14px; line-height: 1.3; }
.iesl .iesl-combo__list li:hover, .iesl .iesl-combo__list li.is-active { background: var(--green-soft, #e6efe9); }
.iesl .iesl-combo__list li.is-sel { font-weight: 600; }
.iesl .iesl-combo__list li.is-none { color: var(--ink-3, #7a857f); cursor: default; }

/* Screen-reader-only text: WordPress defines this in wp-admin, the portal did not. */
.iesl .screen-reader-text { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Filter bar (Oct 2026): one aligned row, labels above, every control the same height. */
.iesl .iesl-filters--bar { display: grid; grid-template-columns: minmax(240px, 2fr) repeat(3, minmax(160px, 1fr)) auto; gap: 12px 14px; align-items: end; padding: 14px 16px; margin: 0 0 16px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r, 10px); }
.iesl .iesl-filter { display: flex; flex-direction: column; gap: 6px; min-width: 0; margin: 0; }
.iesl .iesl-filter > span { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3); }
.iesl .iesl-filters--bar .iesl-combo { width: 100%; }
.iesl .iesl-filters--bar input:not([type="hidden"]), .iesl .iesl-filters--bar select { box-sizing: border-box; width: 100%; min-width: 0; max-width: none; height: 40px; padding: 0 12px; font-size: 13.5px; border: 1px solid var(--line); border-radius: var(--r-sm); background-color: var(--surface-2); color: var(--ink); }
.iesl .iesl-filters--bar select { appearance: none; -webkit-appearance: none; padding-right: 32px; cursor: pointer; background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%); background-position: calc(100% - 16px) 50%, calc(100% - 11px) 50%; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
.iesl .iesl-filters--bar .iesl-combo__q { padding-right: 32px; cursor: pointer; }
.iesl .iesl-filters--bar input[type="search"] { padding-left: 36px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238A948E' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.5-3.5'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: 12px 50%; background-size: 16px 16px; }
.iesl .iesl-filters--bar input:focus, .iesl .iesl-filters--bar select:focus { outline: none; border-color: var(--fill); box-shadow: 0 0 0 3px color-mix(in srgb, var(--fill) 22%, transparent); }
.iesl .iesl-filter__go { display: flex; align-items: center; gap: 12px; white-space: nowrap; }
.iesl .iesl-filter__go .iesl-btn { height: 40px; padding: 0 18px; }
.iesl .iesl-filter__clear { font-size: 13px; font-weight: 500; color: var(--link); text-decoration: none; }
.iesl .iesl-filter__clear:hover { text-decoration: underline; }
@media (max-width: 1180px) {
	.iesl .iesl-filters--bar { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.iesl .iesl-filters--bar .iesl-filter--grow { grid-column: 1 / -1; }
	.iesl .iesl-filter__go { grid-column: 1 / -1; }
}
@media (max-width: 640px) {
	.iesl .iesl-filters--bar { grid-template-columns: 1fr; }
}

/* Staff register review panel (Oct 2026). */
.iesl .iesl-review { padding: 14px 18px 18px; }
.iesl .iesl-review__lede { margin: 0 0 12px; max-width: 72ch; font-size: 13px; color: var(--ink-2); }
.iesl .iesl-review__chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; padding: 0; list-style: none; }
.iesl .iesl-review__chips li { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; font-size: 12.5px; color: var(--ink-2); background: var(--surface-2); border: 1px solid var(--line); border-radius: 999px; }
.iesl .iesl-review__chips b { color: var(--ink); font-weight: 700; }
.iesl .iesl-review__list > summary { list-style: none; }
.iesl .iesl-review__list > summary::-webkit-details-marker { display: none; }
.iesl .iesl-review__list > summary::after { content: ""; width: 6px; height: 6px; margin-left: 8px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); transition: transform .15s; }
.iesl .iesl-review__list[open] > summary::after { transform: translateY(1px) rotate(-135deg); }
.iesl .iesl-review__list > .iesl-tablewrap { margin-top: 14px; }
.iesl .iesl-review__why { margin: 0; padding-left: 16px; font-size: 12.5px; }
.iesl .iesl-review__why li { margin: 0 0 3px; }
.iesl .iesl-review__chips li { padding: 0; border: 0; background: none; }
.iesl .iesl-review__chips a { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; font-size: 12.5px; color: var(--ink-2); text-decoration: none; background: var(--surface-2); border: 1px solid var(--line); border-radius: 999px; transition: border-color .15s, background .15s; }
.iesl .iesl-review__chips a:hover { border-color: var(--fill); color: var(--ink); }
.iesl .iesl-review__chips a.is-on { background: var(--fill); border-color: var(--fill); color: var(--on-fill); }
.iesl .iesl-review__chips a.is-on b { color: var(--on-fill); }
.iesl .iesl-review__all { margin-left: 12px; font-size: 13px; color: var(--link); }
.iesl .iesl-review__do { display: flex; gap: 8px; justify-content: flex-end; align-items: center; }
.iesl .iesl-review__do form { margin: 0; }
.iesl .iesl-review td:first-child { white-space: nowrap; }
.iesl .iesl-review__chips a.is-on::after { content: "\00D7"; margin-left: 2px; font-size: 14px; line-height: 1; opacity: .85; }
