/* =============================================================================
   CASTFORM FIGURE SYSTEM — shared visual language for demo-run diagrams.

   AESTHETIC DIRECTION (committed)
   precise / engineered / calm.
   - Surface: white background. Hairline 1px borders. Every figure sits in a
     dotted-grid PANEL — engineering-paper, not decoration. Keep dots faint.
   - Type: Geist (the little prose there is) + Geist Mono (all labels, data,
     captions, figure content). Mono carries the "engineered" read.
   - Color: black/white + ink greys carry the structure. TWO accents do the
     pointing, never decoration: castform blue (--blue) for the agent / trained
     model and its answer (use `.card--accent`), and amber (--amber) for tool
     calls. Semantic green/red are used sparingly and only functionally (kept
     vs. filtered, ✓ vs. ✕).
   - Chrome: panels carry no caption or title. The figure speaks for itself;
     the surrounding page section supplies any heading.
   - Motion: figures are STATIC — render the end state directly, no intro
     reveals or line-draws. The only motion is the model glyph's quiet ambient
     breathe (cf-breathe / cf-core), which idles indefinitely.

   USAGE
     <link rel="stylesheet" href="/static/diagrams/figure.css">
     <div class="fig-panel">
       <div class="fig-stage"> …figure… </div>
     </div>
     <script src="/static/diagrams/figure.js"></script>
   figure.js adds `.play` (triggers reveals) and posts the panel height to the
   parent so the iframe self-sizes.
============================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap');

:root {
	--bg: #ffffff;
	--wash: #fafaf9;
	--wash2: #f5f5f4;
	--ink: #18181b;
	--ink-2: #52525b;
	--ink-3: #a1a1aa;
	--line: #e4e4e7;
	--line-soft: #efefee;
	--blue: #3b76f6;
	--blue-deep: #2563eb;
	--blue-wash: #eff4fe;
	--blue-line: #c7d9fc;
	/* amber = tool calls (the second accent). wash/line mirror the blue ramp. */
	--amber: #b45309;
	--amber-line: #f1d49a;
	--amber-wash: #fffaf0;
	--green: #15803d;
	--green-wash: #f0fdf4;
	--green-line: #bbe7c8;
	--red: #b91c1c;
	--red-wash: #fef2f2;
	--red-line: #f3cfcf;
	--dot: #e9e9ec;
	--sans: 'Geist', -apple-system, BlinkMacSystemFont, sans-serif;
	--mono: 'Geist Mono', ui-monospace, 'SF Mono', monospace;
}

* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}

html,
body {
	background: transparent;
	font-family: var(--sans);
	color: var(--ink);
	-webkit-font-smoothing: antialiased;
}

/* ---------- panel ---------- */
.fig-panel {
	position: relative;
	border: 1px solid var(--line);
	border-radius: 12px;
	background-color: var(--bg);
	background-image: radial-gradient(var(--dot) 1px, transparent 1.3px);
	background-size: 15px 15px;
	background-position: -1px -1px;
	padding: 22px;
	overflow: hidden;
}

.fig-stage {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 60px;
}

/* ---------- motion primitives (gated on .play) ---------- */
.reveal {
	opacity: 0;
	transform: translateY(7px);
	transition:
		opacity 0.5s ease,
		transform 0.5s cubic-bezier(0.3, 0.8, 0.3, 1);
	transition-delay: calc(var(--i, 0) * 80ms);
}
.fig-panel.play .reveal {
	opacity: 1;
	transform: none;
}
.grow {
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 0.5s cubic-bezier(0.3, 0.8, 0.3, 1);
	transition-delay: calc(var(--i, 0) * 80ms);
}
.fig-panel.play .grow {
	transform: scaleX(1);
}
.draw {
	stroke-dasharray: var(--len, 600);
	stroke-dashoffset: var(--len, 600);
	transition: stroke-dashoffset 1.8s cubic-bezier(0.4, 0.2, 0.2, 1);
}
.fig-panel.play .draw {
	stroke-dashoffset: 0;
}

/* ---------- flow of steps ---------- */
.flow {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 0;
	font-family: var(--mono);
}
.step {
	border: 1px solid var(--line);
	border-radius: 8px;
	background: var(--bg);
	/* explicit so a standalone .step (outside .flow) doesn't fall back to the
     sans body font — every figure node should read in mono */
	font-family: var(--mono);
	padding: 9px 13px;
	font-size: 11.5px;
	line-height: 1.3;
	color: var(--ink);
	text-align: center;
	white-space: nowrap;
}
.step .sub {
	display: block;
	font-size: 9px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--ink-3);
	margin-top: 3px;
	font-weight: 500;
}
.step--accent {
	border-color: var(--blue-line);
	background: var(--blue-wash);
	color: var(--blue-deep);
}
.step--solid {
	border-color: var(--blue);
	background: var(--blue);
	color: #fff;
}
.step--solid .sub {
	color: rgba(255, 255, 255, 0.72);
}
/* connector: hairline with a small chevron, grows in from the left */
.conn {
	flex: none;
	width: 26px;
	height: 1px;
	background: var(--line);
	position: relative;
	margin: 0 3px;
}
.conn::after {
	content: '';
	position: absolute;
	right: 0;
	top: 50%;
	width: 4.5px;
	height: 4.5px;
	border-top: 1px solid var(--ink-3);
	border-right: 1px solid var(--ink-3);
	transform: translateY(-50%) rotate(45deg);
}
/* a labelled bracket under a run of automated steps */
.flow-note {
	margin-top: 12px;
	text-align: center;
	font-family: var(--mono);
	font-size: 9.5px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ink-3);
}

/* ---------- input / output cards ---------- */
.card {
	border: 1px solid var(--line);
	border-radius: 10px;
	background: var(--bg);
	padding: 11px 13px;
	text-align: left;
}
.card-label {
	font-family: var(--mono);
	font-size: 9px;
	font-weight: 500;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: var(--ink-3);
	margin-bottom: 6px;
}
.card--accent {
	border-color: var(--blue-line);
	background: var(--blue-wash);
}
.card .body {
	font-family: var(--mono);
	font-size: 11px;
	line-height: 1.5;
	color: var(--ink);
}

/* mid-flow arrow used between cards */
.arrow {
	flex: none;
	color: var(--ink-3);
	font-size: 15px;
	padding: 0 12px;
	line-height: 1;
	user-select: none;
}

/* ---------- telestich poem ---------- */
.poem {
	font-family: var(--mono);
	font-size: 11px;
	line-height: 1.62;
	/* ch is the mono advance width; the longest line is 31 chars, so 33ch holds
     every line on one row (no wrap) with a hair of slack for justification. */
	width: 33ch;
}
.poem .ln {
	text-align: justify;
	text-align-last: justify;
}
.poem .k {
	color: var(--blue-deep);
	font-weight: 600;
	background: var(--blue-wash);
	border-radius: 3px;
	/* keep the highlight from adding line width (would force a wrap) */
	padding: 0 1px;
}

/* ---------- agent glyph: a bot head, the hero mark for a trained model ----- */
.model {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 9px;
	flex: none;
	/* the caption hangs below the glyph; matching top padding keeps the glyph
     itself centered, so it lines up with the connector / arrows in any row. */
	padding-top: 21px;
}
.model-glyph {
	width: 54px;
	height: 54px;
	overflow: visible;
	filter: drop-shadow(0 2px 7px rgba(59, 118, 246, 0.26));
	animation: cf-breathe 3.2s ease-in-out infinite;
}
.model-glyph .head,
.model-glyph .ear {
	fill: var(--blue);
}
.model-glyph .stalk {
	stroke: var(--blue);
	stroke-width: 2;
	stroke-linecap: round;
}
.model-glyph .bulb {
	fill: var(--blue);
	transform-box: fill-box;
	transform-origin: center;
	animation: cf-core 2.4s ease-in-out infinite;
}
.model-glyph .eye {
	fill: #fff;
}
@keyframes cf-breathe {
	0%,
	100% {
		filter: drop-shadow(0 2px 6px rgba(59, 118, 246, 0.2));
	}
	50% {
		filter: drop-shadow(0 3px 13px rgba(59, 118, 246, 0.42));
	}
}
@keyframes cf-core {
	0%,
	100% {
		opacity: 0.55;
		transform: scale(0.8);
	}
	50% {
		opacity: 1;
		transform: scale(1.2);
	}
}
.model-cap {
	font-family: var(--mono);
	font-size: 9.5px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--blue-deep);
}

/* ---------- rag: corpus + retrieved passages ---------- */
.doc {
	border: 1px solid var(--line);
	border-radius: 7px;
	background: var(--bg);
	padding: 8px 10px;
	width: 192px;
	display: flex;
	flex-direction: column;
	gap: 5px;
}
.doc .doc-head {
	display: flex;
	align-items: center;
	gap: 6px;
	font-family: var(--mono);
	font-size: 9.5px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--ink-3);
}
.doc .ln {
	height: 5px;
	border-radius: 3px;
	background: var(--line);
}
.doc--cited {
	border-color: var(--blue-line);
	background: var(--blue-wash);
}
.doc--cited .doc-head {
	color: var(--blue-deep);
}
.doc--cited .ln {
	background: var(--blue-line);
}
.cite {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	font-family: var(--mono);
	font-size: 10px;
	color: var(--blue-deep);
	border: 1px solid var(--blue-line);
	background: var(--bg);
	border-radius: 999px;
	padding: 2px 8px;
}

/* search pill with a quiet pulse */
.searching {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-family: var(--mono);
	font-size: 11px;
	color: var(--ink-2);
	border: 1px solid var(--line);
	border-radius: 999px;
	padding: 6px 13px;
	background: var(--bg);
}
.searching .pip {
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--blue);
	animation: cf-pulse 1.4s ease infinite;
}
@keyframes cf-pulse {
	0%,
	100% {
		opacity: 1;
		transform: scale(1);
	}
	50% {
		opacity: 0.35;
		transform: scale(0.7);
	}
}

/* ---------- trace → per-turn examples ---------- */
.tracecol {
	display: flex;
	flex-direction: column;
	gap: 8px;
	width: 208px;
	flex: none;
}
.tb {
	height: 12px;
	border-radius: 6px;
	transform: scaleX(0);
	transform-origin: left;
	transition:
		transform 0.45s cubic-bezier(0.3, 0.8, 0.3, 1),
		opacity 0.2s;
	transition-delay: calc(var(--i, 0) * 70ms);
}
.fig-panel.play .tb {
	transform: scaleX(1);
}
.tb.user {
	background: var(--blue);
	align-self: flex-end;
	transform-origin: right;
}
.tb.agent {
	background: var(--ink-2);
}
.tb.tool {
	background: var(--line);
}
.tb.dim {
	opacity: 0.2;
}
.tb.hot {
	outline: 2px solid var(--blue-line);
	outline-offset: 2px;
}
.excol {
	display: grid;
	grid-template-columns: repeat(2, 150px);
	gap: 12px;
	align-items: start;
}
.ex {
	position: relative;
	border: 1px solid var(--line);
	border-radius: 9px;
	padding: 13px 13px 11px;
	display: flex;
	flex-direction: column;
	gap: 5px;
	background: var(--bg);
	opacity: 0;
	transform: translateX(16px);
	transition:
		opacity 0.45s ease,
		transform 0.45s ease,
		border-color 0.15s;
	transition-delay: calc(0.5s + var(--i, 0) * 0.18s);
}
.fig-panel.play .ex {
	opacity: 1;
	transform: none;
}
.ex .mb {
	height: 5px;
	border-radius: 3px;
	background: var(--line);
}
.ex .mb.tgt {
	background: var(--blue);
}
.ex.cut {
	border-style: dashed;
}
.fig-panel.play .ex.cut {
	opacity: 0.5;
}
.ex.cut .mb.tgt {
	background: var(--red);
}
.ex::after {
	position: absolute;
	top: 8px;
	right: 10px;
	font-family: var(--mono);
	font-size: 10px;
	font-weight: 600;
}
.ex.kept::after {
	content: '✓';
	color: var(--green);
}
.ex.cut::after {
	content: '✕';
	color: var(--red);
}
.ex.kept {
	cursor: default;
}
.ex.kept:hover {
	border-color: var(--blue);
}

/* small legend strip */
.legend {
	display: flex;
	gap: 22px;
	justify-content: center;
	margin-top: 22px;
	font-family: var(--mono);
	font-size: 9.5px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ink-3);
}
.legend i {
	display: inline-block;
	width: 13px;
	height: 5px;
	border-radius: 3px;
	margin-right: 7px;
	vertical-align: middle;
}
.legend .l-ctx {
	background: var(--line);
}
.legend .l-tgt {
	background: var(--blue);
}
.legend .l-cut {
	background: var(--red);
	opacity: 0.5;
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
	}
}
