:root {
	--bg: #eef1f6;
	--card: #ffffff;
	--border: #e2e6ee;
	--text: #1b2330;
	--muted: #6b7280;
	--green-bg: #e4f6ec;
	--green-fg: #137a46;
	--green-border: #bfe6d0;
	--amber-bg: #fdf0d4;
	--amber-fg: #975a05;
	--amber-border: #f2dca6;
	--gray-bg: #eef0f4;
	--gray-fg: #6b7280;
	--gray-border: #e0e4ea;
	--blue: #1a6fb5;
	--orange-fg: #c2540c;
	--red-fg: #b23a2f;

	/* Pill palette -- matches the "Density check" design exploration
	   (Claude Design canvas "Level Unit Tracker -- failed-status options",
	   board GridDensityA) exactly: blocked/progress/qc/fail all share ONE
	   fixed color per state regardless of stage, and generation-failure
	   and QC-failure deliberately share the SAME red (Option A's point --
	   only the checkbox glyph, "!" vs "x", plus a halo ring on the QC
	   failure, tell them apart). */
	--pill-blocked-bg: #eef0f2;
	--pill-blocked-border: #cbd0d6;
	--pill-progress-bg: #e4eeff;
	--pill-progress-border: #6b93f0;
	--pill-progress-fg: #3b6fe0;
	--pill-qc-bg: #fff3d6;
	--pill-qc-border: #e0aa3e;
	--pill-qc-fg: #a9720c;
	--pill-fail-bg: #fde2e1;
	--pill-fail-border: #e23b32;
	--pill-ready-bg: #e4eee7;
	--pill-ready-border: #5c9877;
	--pill-stale-bg: #ede2fa;
	--pill-stale-border: #8a5fc7;
	--dot-hollow-border: #c7cbd1;
}

* {
	box-sizing: border-box;
}

body {
	font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
	background: var(--bg);
	color: var(--text);
	max-width: 1160px;
	margin: 0 auto;
	padding: 1.5rem 1rem 3rem;
}

h1 {
	font-size: 1.4rem;
	letter-spacing: -0.02em;
	margin-bottom: 0.25rem;
}

h2 {
	font-size: 1rem;
	margin: 2rem 0 0.75rem;
	color: var(--muted);
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

/* Connection badges */

a.badge,
.badge {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.3rem 0.75rem;
	font-size: 0.8rem;
	font-weight: 600;
	border-radius: 999px;
	text-decoration: none;
}

.badge.is-on {
	background: var(--green-bg);
	color: var(--green-fg);
	border: 1px solid var(--green-border);
}

a.badge.is-off {
	background: var(--card);
	color: var(--blue);
	border: 1px solid var(--blue);
}

.tracker-sticky {
	/* Not sticky: page scrolls normally. */
	width: 100%;
	background: #fff;
	padding: 0.6rem 0 0;
	margin-bottom: 0.5rem;
	box-shadow: 0 1px 0 var(--border);
}

.tracker-sticky h2 {
	margin: 0 0 0.75rem;
}

.tracker-sticky .tracker-filters {
	margin-bottom: 0;
}

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

.tracker-filters {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 0.75rem;
	background: var(--card);
	border: 1px solid var(--border);
	border-radius: 12px;
	padding: 0.6rem;
	box-shadow: 0 1px 3px rgba(16, 24, 40, 0.06);
}

.tracker-filters input,
.tracker-filters select {
	padding: 0.4rem 0.6rem;
	font-size: 0.8rem;
	border: 1px solid var(--border);
	border-radius: 8px;
	background: #fff;
	color: var(--text);
}

.tracker-filters input {
	flex: 1 1 200px;
}

.tracker-filters button {
	padding: 0.4rem 0.85rem;
	font-size: 0.8rem;
	font-weight: 600;
	border: 1px solid var(--border);
	border-radius: 8px;
	background: var(--gray-bg);
	color: var(--text);
	cursor: pointer;
}

/* Auto-refresh paused -- amber to match the grid's own "running" color
   language, so it reads as an active/attention state, not a normal button. */
.tracker-filters button.is-paused {
	background: var(--amber-bg);
	color: var(--amber-fg);
	border-color: var(--amber-border);
}

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

/* Horizontal-only frame: the table overflows right when columns don't fit
   and the frame scrolls horizontally. Height is unconstrained, so the PAGE
   stays the vertical scroller -- no inner vertical scrollbar. */
.tracker-scroll {
	overflow-x: auto;
}

.tracker-table {
	border-collapse: separate;
	border-spacing: 0 0.85rem;
	table-layout: fixed;
	width: 100%;
	min-width: 480px;
}

.tracker-table th,
.tracker-table td {
	vertical-align: top;
	padding: 0;
}

/* Not sticky: page scrolls normally, horizontal frame handles the rest. */
.tracker-table thead th {
	background: #fff;
}

.tracker-table thead th.level {
	left: 0;
	z-index: 4;
}

/* Sticky level column: white and opaque, flush-straight edge. Every level
   label in here shares the same column width. */
.tracker-table th.level,
.tracker-table td.level {
	position: sticky;
	left: 0;
	z-index: 2;
	width: 140px;
	min-width: 140px;
	background: #fff;
	/* Width fits the longest label (PRE_READING_A4) on one line. */
	white-space: nowrap;
	overflow: hidden;
}

.tracker-table th.level {
	padding: 0.4rem 0.6rem;
	text-align: left;
	font-size: 0.75rem;
	font-weight: 700;
	color: var(--muted);
}

.tracker-table td.level {
	padding: 0.45rem 0.6rem;
	text-align: left;
	font-size: 0.8rem;
	font-weight: 700;
	color: var(--text);
	vertical-align: middle;
	/* Per-level accent rail (--accent set server-side) + right edge rule
	   for the sticky column. Both are inside the cell, so the column
	   stays fully opaque. */
	box-shadow: inset 3px 0 0 var(--accent, #888), 1px 0 0 var(--border);
}

.tracker-table th.unit,
.tracker-table td.unit {
	/* Fixed width so the four step rows never wrap. When the container is
	   wide enough the table fills it; otherwise it overflows and the page
	   scrolls horizontally. The checkbox+code+dots pill design is more
	   compact than the old word+emoji+tick-row one, so this shrank
	   accordingly (was 106px). */
	width: 84px;
	min-width: 84px;
}

.tracker-table th.unit {
	padding: 0.4rem 0.25rem;
	text-align: center;
	font-size: 0.75rem;
	font-weight: 600;
	color: var(--muted);
}

.tracker-table td.unit {
	padding: 0.3rem;
	/* Flat pastel wash of the level's own accent (--accent set on the
	   <tr>) -- no border/box, just the tinted band. */
	background: color-mix(in srgb, var(--accent, #888) 10%, #fff);
	transition: box-shadow 0.12s ease;
}

.tracker-table td.unit:not(.is-empty):hover {
	background: color-mix(in srgb, var(--accent, #888) 16%, #fff);
}

.tracker-table td.unit.is-empty {
	background: transparent;
	border-color: transparent;
}

.tracker-table td.unit.is-filtered {
	background: transparent;
	border-color: transparent;
}

.tracker-table td.unit.is-filtered .step-word {
	visibility: hidden;
	pointer-events: none;
}

.tracker-table tr.is-hidden-row {
	display: none;
}

/* Step pills -- checkbox-style status icon, the stage's own code letters,
   then a row of small progress dots, all pushed right. Matches the
   "Density check" design exploration (Claude Design canvas "Level Unit
   Tracker -- failed-status options", board GridDensityA) as closely as a
   real many-unit-wide table allows. */
.step-word {
	display: flex;
	align-items: center;
	gap: 5px;
	width: 100%;
	height: 18px;
	padding: 0 7px;
	font-size: 9.5px;
	font-weight: 700;
	border: 1px solid transparent;
	border-radius: 999px;
	cursor: pointer;
	margin-bottom: 5px;
	text-align: left;
	transition: filter 0.12s ease;
	overflow: hidden;
}

.step-word:hover {
	filter: brightness(0.97);
}

/* Checkbox-style status icon -- empty (blocked), a dashed spinner
   (progress/qcrun), an hourglass-cross (qcwait), or a solid glyph square
   (!/×/✓ for failed/failedqc/ready). */
.chk {
	flex: none;
	width: 11px;
	height: 11px;
	border-radius: 3px;
	border: 1.2px solid;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 8px;
	line-height: 1;
	font-weight: 800;
	background: #fff;
}

.chk svg {
	width: 7px;
	height: 7px;
	display: block;
}

.chk-blocked {
	border-color: var(--pill-blocked-border);
}

.chk-progress {
	border-color: var(--pill-progress-border);
	color: var(--pill-progress-fg);
}

.chk-qcwait,
.chk-qcrun {
	border-color: var(--pill-qc-border);
	color: var(--pill-qc-fg);
}

.chk-failed,
.chk-failedqc {
	background: var(--pill-fail-border);
	border-color: var(--pill-fail-border);
	color: #fff;
}

.chk-ready {
	background: var(--pill-ready-border);
	border-color: var(--pill-ready-border);
	color: #fff;
}

.chk-stale {
	background: var(--pill-stale-border);
	border-color: var(--pill-stale-border);
	color: #fff;
}

.code {
	flex: none;
	color: var(--text);
}

/* Progress-dot row -- one dot per real sub-status the stage can be in
   (see gridTick's own doc comment). Filled dots all share ONE phase
   color; the rest stay hollow. Pushed to the pill's trailing edge. */
.dots {
	display: flex;
	gap: 2px;
	margin-left: auto;
}

.dot {
	width: 4px;
	height: 4px;
	border-radius: 50%;
	border: 1px solid var(--dot-hollow-border);
	background: transparent;
	flex: none;
}

.dot.fb {
	background: var(--pill-progress-border);
	border-color: var(--pill-progress-border);
}

.dot.fa {
	background: var(--pill-qc-border);
	border-color: var(--pill-qc-border);
}

.dot.fr {
	background: var(--pill-fail-border);
	border-color: var(--pill-fail-border);
}

.dot.fg {
	background: var(--pill-ready-border);
	border-color: var(--pill-ready-border);
}

.dot.fp {
	background: var(--pill-stale-border);
	border-color: var(--pill-stale-border);
}

.step-word.pill-blocked {
	background: var(--pill-blocked-bg);
	border-color: var(--pill-blocked-border);
}

.step-word.pill-progress {
	background: var(--pill-progress-bg);
	border-color: var(--pill-progress-border);
	animation: pulse 1.4s ease-in-out infinite;
}

.step-word.pill-qc {
	background: var(--pill-qc-bg);
	border-color: var(--pill-qc-border);
}

.step-word.pill-failed,
.step-word.pill-failedqc {
	background: var(--pill-fail-bg);
	border-color: var(--pill-fail-border);
}

.step-word.pill-ready {
	background: var(--pill-ready-bg);
	border-color: var(--pill-ready-border);
}

.step-word.pill-stale {
	background: var(--pill-stale-bg);
	border-color: var(--pill-stale-border);
}

/* Halo: an extra ring on a QC failure specifically (never a plain
   generation failure) -- same red as the pill border, just softened, so
   a QC verdict-fail reads with slightly more visual weight than a
   generation exception. */
.step-word.is-halo {
	box-shadow: 0 0 0 2px rgba(226, 59, 50, 0.45);
}

@keyframes pulse {
	0%, 100% { opacity: 1; }
	50% { opacity: 0.55; }
}

#modal-actions {
	margin-top: 0.85rem;
	padding-top: 0.75rem;
	border-top: 1px solid var(--border);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
}

#modal-actions .action-btn {
	padding: 0.45rem 0.9rem;
	font-size: 0.82rem;
	font-weight: 700;
	color: var(--text);
	background: var(--gray-bg);
	border: 1px solid var(--gray-border);
	border-radius: 8px;
	cursor: pointer;
}

#modal-actions .action-btn:hover:not(:disabled) {
	border-color: var(--blue);
	color: var(--blue);
}

#modal-actions .action-btn:disabled {
	opacity: 0.55;
	cursor: not-allowed;
}

.modal-note {
	margin: 0;
	flex-basis: 100%;
	font-size: 0.8rem;
	color: var(--muted);
	overflow-wrap: anywhere;
}

.modal-note a {
	color: var(--blue);
	font-weight: 600;
}

/* ---- Unit modal ---- */

.modal {
	position: fixed;
	inset: 0;
	z-index: 50;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1rem;
}

.modal[hidden] {
	display: none;
}

.modal-backdrop {
	position: absolute;
	inset: 0;
	background: rgba(15, 23, 42, 0.45);
	backdrop-filter: blur(2px);
}

.modal-card {
	position: relative;
	background: #fff;
	border-radius: 14px;
	padding: 1.25rem 1.5rem;
	min-width: 280px;
	max-width: 420px;
	width: 100%;
	box-shadow: 0 20px 45px rgba(15, 23, 42, 0.3);
	border: 1px solid var(--border);
}

.modal-card h3 {
	margin: 0 0 0.75rem;
	font-size: 1.05rem;
}

.modal-step {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin-bottom: 0.75rem;
	font-size: 0.95rem;
}

.modal-step strong {
	padding: 0.15rem 0.6rem;
	border-radius: 6px;
	background: var(--gray-bg);
	color: var(--text);
	font-size: 0.8rem;
}

.modal-status {
	margin-bottom: 0.5rem;
	color: var(--muted);
	font-size: 0.85rem;
}

.modal-link {
	margin-bottom: 0.75rem;
	font-size: 0.85rem;
}

.modal-link a {
	display: inline-block;
	font-weight: 600;
	color: #fff;
	background: var(--blue);
	padding: 0.3rem 0.85rem;
	border-radius: 8px;
	text-decoration: none;
}

.modal-card button[data-modal-close] {
	padding: 0.4rem 1rem;
	font-size: 0.8rem;
	font-weight: 600;
	border: 1px solid var(--border);
	border-radius: 8px;
	background: #fff;
	color: var(--text);
	cursor: pointer;
}
/* Login page */
.login-body {
	display: grid;
	place-items: center;
	min-height: 100vh;
	margin: 0;
	background: var(--bg);
}
.login-card {
	display: flex;
	flex-direction: column;
	gap: 12px;
	width: min(320px, calc(100vw - 32px));
	padding: 28px;
	border: 1px solid var(--border);
	border-radius: 12px;
	background: var(--card);
}
.login-card h1 { margin: 0; font-size: 22px; }
.login-hint { margin: 0; color: var(--muted); font-size: 14px; }
.login-error {
	margin: 0;
	padding: 8px 10px;
	border-radius: 8px;
	background: #fdeaea;
	color: #a11b1b;
	font-size: 14px;
}
.login-card input {
	padding: 10px 12px;
	border: 1px solid var(--border);
	border-radius: 8px;
	font-size: 15px;
}
.login-card button {
	padding: 10px 12px;
	border: 1px solid var(--border);
	border-radius: 8px;
	background: var(--text);
	color: #fff;
	font-size: 15px;
	cursor: pointer;
}
