/* Self-hosted, not a CDN: a cross-origin font request is returned early by the
   service worker (sw.js leaves cross-origin to the browser), so an offline
   launch would silently fall back to system fonts. */
@font-face {
  font-family: 'DM Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('./fonts/dm-sans-400.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Sans'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('./fonts/dm-sans-700.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('./fonts/plex-mono-400.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('./fonts/plex-mono-600.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('./fonts/plex-mono-700.woff2') format('woff2');
}

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

/* viewport-fit=cover + black-translucent means content sits under the notch and
   home indicator. Without these insets the top of the UI is unreachable. */
body {
  margin: 0;
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
  padding-left: var(--safe-left);
  padding-right: var(--safe-right);
  min-height: 100vh;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-prose);
  line-height: 1.55;
  -webkit-text-size-adjust: 100%;
}

.wrap { max-width: 46rem; margin: 0 auto; padding: var(--gap) 1rem 5rem; }
.mono { font-family: var(--font-data); font-variant-numeric: tabular-nums; }
.muted { color: var(--color-text-dim); font-size: 0.9rem; }
.print-only { display: none; }

/* ── app bar ─────────────────────────────────────────────────────────── */
.app-bar {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; gap: var(--gap);
  padding: var(--gap) 1rem;
  padding-top: calc(var(--gap) + var(--safe-top));
  margin-top: calc(-1 * var(--safe-top));
  background: color-mix(in srgb, var(--color-bg) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--color-border);
}
.app-title {
  margin: 0; flex: 1;
  font-family: var(--font-data); font-size: 0.95rem; font-weight: 700;
  letter-spacing: 0.02em; color: var(--color-accent-green);
  text-decoration: none;
}

/* ── controls ────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); min-width: var(--tap);
  padding: 0 1.1rem;
  border: 1px solid transparent; border-radius: var(--radius);
  background: var(--color-accent-blue); color: #06101f;
  font-family: var(--font-prose); font-size: 0.95rem; font-weight: 700;
  text-decoration: none; cursor: pointer;
}
.btn:hover { filter: brightness(1.08); }
.btn:disabled { opacity: 0.5; cursor: default; }
.btn-sm { min-height: 2.2rem; padding: 0 0.8rem; font-size: 0.85rem; }
.btn-ghost {
  background: transparent; color: var(--color-text);
  border-color: var(--color-border); font-weight: 400;
}
.btn-ghost:hover { background: var(--color-surface); }
:where(button, input, select, textarea, a):focus-visible {
  outline: 2px solid var(--color-accent-green); outline-offset: 2px;
}

.input, select.input, textarea.intake-text {
  width: 100%; min-height: var(--tap); padding: 0.6rem 0.85rem;
  border: 1px solid var(--color-border); border-radius: var(--radius);
  background: var(--color-surface); color: var(--color-text);
  font-family: var(--font-prose);
  font-size: 16px;   /* below 16px, iOS Safari zooms the page on focus */
}
.input::placeholder, .intake-text::placeholder { color: var(--color-text-dim); }

.row { display: flex; gap: var(--gap); align-items: center; margin: var(--gap) 0; flex-wrap: wrap; }
.row-end { justify-content: flex-end; }

.field { margin: 1rem 0; }
.field-label {
  display: block; margin-bottom: 0.35rem;
  font-family: var(--font-data); font-size: 0.78rem; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--color-text-dim);
}

.segmented { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.seg {
  min-height: var(--tap); padding: 0 0.9rem;
  border: 1px solid var(--color-border); border-radius: var(--radius);
  background: var(--color-surface); color: var(--color-text);
  font-family: var(--font-prose); font-size: 0.9rem; cursor: pointer;
}
.seg-on {
  background: var(--color-accent-blue); color: #06101f;
  border-color: var(--color-accent-blue); font-weight: 700;
}

/* ── page furniture ──────────────────────────────────────────────────── */
.page-head { margin: 1.25rem 0 1.5rem; }
.backlink {
  display: inline-block; margin-bottom: 0.5rem;
  color: var(--color-text-dim); text-decoration: none;
  font-family: var(--font-data); font-size: 0.8rem;
}
.backlink:hover { color: var(--color-accent-green); }
.page-title { margin: 0; font-size: 1.6rem; line-height: 1.2; letter-spacing: -0.01em; }
.page-sub { margin: 0.4rem 0 0; color: var(--color-text-dim); }

.section-head { margin: 2rem 0 0.85rem; }
.section-title {
  margin: 0; font-family: var(--font-data); font-size: 0.82rem;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent-green);
}
.section-hint { margin: 0.35rem 0 0; color: var(--color-text-dim); font-size: 0.9rem; }

/* ── landing ─────────────────────────────────────────────────────────── */
.landing { padding: 2rem 0 1rem; }
.landing-kicker {
  margin: 0; font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--color-accent-green);
}
.choices { display: grid; gap: var(--gap); margin-top: 1.4rem; }
@media (min-width: 46rem) { .choices { grid-template-columns: 1fr 1fr; } }
.choice {
  display: flex; flex-direction: column; gap: 0.5rem;
  padding: 1.4rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: calc(var(--radius) * 1.6);
  color: inherit; text-decoration: none;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.choice:hover { border-color: var(--color-accent-blue); transform: translateY(-2px); }
.choice:hover .choice-glow { opacity: 1; }

/* A slow sweep of accent colour behind the card on hover. `position: absolute`
   inside the card, pointer-events none, so it never intercepts the click. */
.choice { position: relative; overflow: hidden; isolation: isolate; }
.choice-glow {
  position: absolute; inset: -40% -10% auto -10%; height: 160%;
  z-index: -1; opacity: 0; pointer-events: none;
  transition: opacity 0.35s ease;
  background: radial-gradient(60% 50% at 20% 0%,
              color-mix(in srgb, var(--color-accent-blue) 26%, transparent), transparent 70%);
}

/* Staggered entrance. --i is set per element in view-shared.js so the whole
   sequence retimes from here rather than from JS. */
.landing-kicker, .choice, .landing-sources .source {
  animation: rise 0.5s cubic-bezier(0.2, 0.8, 0.2, 1) backwards;
}
.landing-kicker { animation-delay: 0.02s; }
.choice { animation-delay: calc(0.10s + var(--i, 0) * 0.09s); }
.landing-sources .source { animation-delay: calc(0.34s + var(--i, 0) * 0.06s); }
@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* ── landing sources strip ───────────────────────────────────────────── */
.landing-sources {
  margin-top: 2.4rem; padding-top: 1.2rem;
  border-top: 1px solid var(--color-border);
}
.sources-label {
  display: block; font-size: 0.7rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--color-text-dim); margin-bottom: 0.7rem;
}
.sources-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.45rem; }
@media (min-width: 46rem) {
  .sources-list { grid-template-columns: repeat(3, 1fr); gap: 0.9rem; }
}
.source {
  display: flex; flex-direction: column; gap: 0.15rem;
  padding-left: 0.7rem; border-left: 2px solid var(--color-accent-green);
}
.source-name { font-size: 0.82rem; font-weight: 700; color: var(--color-text); }
.source-detail { font-size: 0.8rem; color: var(--color-text-dim); line-height: 1.35; }
.sources-disclaimer { margin: 1rem 0 0; font-size: 0.8rem; }

/* ── the working animation ───────────────────────────────────────────── */
.working {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.55rem;
  margin-top: 0.9rem; padding: 0.9rem 1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: var(--radius);
}
.working-scan { display: flex; align-items: flex-end; gap: 4px; height: 20px; }
.scan-bar {
  width: 4px; height: 100%; border-radius: 2px;
  background: var(--color-accent-blue);
  transform-origin: bottom;
  animation: scan 1.05s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * 0.11s);
}
@keyframes scan {
  0%, 100% { transform: scaleY(0.28); opacity: 0.45; }
  50%      { transform: scaleY(1);    opacity: 1; }
}
.working-label {
  margin: 0; font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--color-accent-green);
}
.working-step {
  margin: 0; font-size: 0.95rem; color: var(--color-text);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.working-step.is-swapping { opacity: 0; transform: translateY(4px); }
.choice-eyebrow {
  font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--color-text-dim);
}
.choice-title { font-size: 1.3rem; font-weight: 700; line-height: 1.2; }
.choice-body { color: var(--color-text-dim); font-size: 0.95rem; }
.choice-cta {
  margin-top: auto; padding-top: 0.6rem;
  color: var(--color-accent-blue); font-weight: 700; font-size: 0.95rem;
}
.landing-foot { margin-top: 2rem; max-width: 34rem; }

/* ── intake ──────────────────────────────────────────────────────────── */
.intake-text { min-height: 9rem; resize: vertical; line-height: 1.5; }
.intake-actions { display: flex; gap: var(--gap); margin-top: var(--gap); }
.intake-submit { flex: 1; }
.mic-live { border-color: var(--color-danger); color: var(--color-danger); }
.intake-status { min-height: 1.2rem; margin: 0.5rem 0 0; }

.examples { margin-top: 2rem; }
.examples-title {
  margin: 0 0 0.6rem; font-family: var(--font-data); font-size: 0.78rem;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-dim);
}
.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chip {
  min-height: var(--tap); padding: 0.4rem 0.9rem;
  border: 1px solid var(--color-border); border-radius: 999px;
  background: var(--color-surface); color: var(--color-text);
  font-family: var(--font-prose); font-size: 0.9rem; cursor: pointer;
  text-align: left;
}
.chip:hover { border-color: var(--color-accent-blue); }
.chip-on {
  background: color-mix(in srgb, var(--color-accent-blue) 22%, var(--color-surface));
  border-color: var(--color-accent-blue);
}
.chip-interest { display: inline-flex; align-items: center; gap: 0.5rem; }
.chip-code {
  font-size: 0.7rem; letter-spacing: 0.06em;
  padding: 0.1rem 0.35rem; border-radius: 4px;
  background: color-mix(in srgb, var(--color-accent-blue) 30%, transparent);
  color: var(--color-text);
}

/* ── extraction review ───────────────────────────────────────────────── */
.chips-profile { flex-direction: column; align-items: stretch; gap: 0.5rem; }
.chip-wrap { display: block; }
.chip-profile {
  display: flex; align-items: baseline; gap: 0.75rem; width: 100%;
  border-radius: var(--radius); padding: 0.6rem 0.9rem;
}
.chip-key {
  flex: 0 0 8.5rem;
  font-family: var(--font-data); font-size: 0.72rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--color-text-dim);
}
.chip-value { flex: 1; font-size: 0.95rem; }
.chip-empty .chip-value { color: var(--color-band-mid); font-style: italic; }
.chip-edited { border-color: var(--color-accent-green); }
.chip-editor {
  padding: 0.75rem 0.9rem 1rem;
  border: 1px solid var(--color-accent-blue); border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  background: color-mix(in srgb, var(--color-accent-blue) 8%, var(--color-surface));
}
.chip-editor[hidden] { display: none; }
.editor-body { display: flex; flex-wrap: wrap; gap: var(--gap); align-items: flex-start; }
.editor-body > .input, .editor-body > .intake-text { flex: 1 1 14rem; }

.assumptions {
  margin: 1.5rem 0; padding: 0.9rem 1rem;
  border-left: 3px solid var(--color-band-mid);
  background: var(--color-surface); border-radius: 0 var(--radius) var(--radius) 0;
}
.assumptions-title {
  margin: 0 0 0.4rem; font-family: var(--font-data); font-size: 0.75rem;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-band-mid);
}
.assumptions-list { margin: 0; padding-left: 1.1rem; color: var(--color-text-dim); font-size: 0.9rem; }

.gaps {
  margin: 1.75rem 0; padding: 1.1rem;
  background: var(--color-surface); border: 1px solid var(--color-accent-blue);
  border-radius: calc(var(--radius) * 1.4);
}
.gaps-title { margin: 0; font-size: 1.1rem; }
.gaps-hint { margin: 0.3rem 0 1rem; color: var(--color-text-dim); font-size: 0.9rem; }
.gaps-list { display: grid; gap: 1rem; }
.gap-q { margin: 0 0 0.4rem; font-size: 0.95rem; font-weight: 700; }

/* ── the disclosure (Track B) ────────────────────────────────────────── */
.disclosure {
  display: flex; flex-direction: column; gap: 0.35rem;
  margin: 1rem 0 1.5rem; padding: 0.85rem 1rem;
  background: color-mix(in srgb, var(--color-accent-green) 8%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--color-accent-green) 40%, transparent);
  border-radius: var(--radius);
}
.disclosure-mark {
  font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--color-accent-green);
}
.disclosure-text { margin: 0; font-size: 0.88rem; color: var(--color-text); }
.pool-meta { margin: 0.5rem 0 0; font-size: 0.8rem; }
.pool-stale { color: var(--color-band-mid); }

/* ── stats band ──────────────────────────────────────────────────────── */
.stats {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(2, 1fr);
  margin: 1rem 0 0.6rem;
}
@media (min-width: 40rem) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat {
  padding: 0.9rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: var(--radius);
}
.stat-value {
  font-family: var(--font-data); font-size: 1.6rem; font-weight: 700;
  line-height: 1.1; color: var(--color-accent-green);
  font-variant-numeric: tabular-nums;
}
.stat-label { margin-top: 0.3rem; font-size: 0.8rem; color: var(--color-text-dim); }
.stat-note {
  margin-top: 0.25rem; font-family: var(--font-data); font-size: 0.68rem;
  color: var(--color-text-dim); overflow-wrap: anywhere;
}
.stats-meta { margin: 0 0 1rem; font-size: 0.8rem; color: var(--color-text-dim); }
.stats-demoted { opacity: 0.72; }

/* ── source degradation notices ──────────────────────────────────────── */
.notices { margin: 0.75rem 0; }
.notice {
  display: flex; align-items: baseline; gap: 0.6rem;
  margin: 0.35rem 0; padding: 0.55rem 0.8rem;
  background: color-mix(in srgb, var(--color-band-mid) 10%, transparent);
  border-left: 3px solid var(--color-band-mid);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 0.88rem; color: var(--color-text);
}
.notice-dot {
  flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
  background: var(--color-band-mid);
}

/* ── cards ───────────────────────────────────────────────────────────── */
.cards { display: grid; gap: var(--gap); }
.card {
  position: relative;
  padding: 1.1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-border);
  border-radius: var(--radius);
  animation: card-in 0.34s ease both;
}
@keyframes card-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .landing-kicker, .choice, .landing-sources .source { animation: none; }
  .scan-bar { animation: none; transform: scaleY(0.6); opacity: 0.8; }
  .working-step { transition: none; }
  .choice-glow { transition: none; }
  .card { animation: none; }
}
.card-good { border-left-color: var(--color-band-good); }
.card-mid  { border-left-color: var(--color-band-mid); }
.card-low  { border-left-color: var(--color-band-low); }
.card-open { border-color: var(--color-accent-blue); }

.card-head { display: flex; gap: var(--gap); align-items: flex-start; }
.card-headings { flex: 1; min-width: 0; }
.card-title { margin: 0; font-size: 1.08rem; line-height: 1.3; }
.card-agency {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  margin: 0.3rem 0 0; font-size: 0.85rem; color: var(--color-text-dim);
}
.card-aln { font-size: 0.75rem; opacity: 0.85; }
.card-score { flex: 0 0 auto; text-align: right; }
.card-score-value {
  font-size: 1.5rem; font-weight: 700; line-height: 1;
  color: var(--color-text);
}
.card-good .card-score-value { color: var(--color-band-good); }
.card-mid  .card-score-value { color: var(--color-band-mid); }
.card-low  .card-score-value { color: var(--color-band-low); }
.card-score-label {
  font-size: 0.66rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--color-text-dim); font-family: var(--font-data);
  max-width: 6.5rem;
}

.card-band { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.75rem 0; }
.band {
  padding: 0.2rem 0.6rem; border-radius: 999px;
  font-family: var(--font-data); font-size: 0.72rem; letter-spacing: 0.03em;
}
.band-good { background: color-mix(in srgb, var(--color-band-good) 18%, transparent); color: var(--color-band-good); }
.band-mid  { background: color-mix(in srgb, var(--color-band-mid) 18%, transparent);  color: var(--color-band-mid); }
.band-low  { background: color-mix(in srgb, var(--color-band-low) 18%, transparent);  color: var(--color-band-low); }
.chip-flag {
  padding: 0.2rem 0.6rem; border-radius: 999px;
  border: 1px solid var(--color-border);
  font-family: var(--font-data); font-size: 0.7rem; color: var(--color-text-dim);
}
.chip-flag-urgent_deadline { border-color: var(--color-danger); color: var(--color-danger); }

.card-facts {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem;
  margin: 0.75rem 0 0.9rem; padding-top: 0.75rem;
  border-top: 1px solid var(--color-border);
}
.fact dt {
  font-size: 0.68rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--color-text-dim); font-family: var(--font-data);
}
.fact dd { margin: 0.15rem 0 0; font-size: 0.92rem; }

.card-toggle { width: 100%; min-height: 2.5rem; border-radius: var(--radius); }
.card-body { margin-top: 1rem; }
.card-body[hidden] { display: none; }
.card-objective {
  margin: 0 0 1rem; padding-left: 0.85rem;
  border-left: 2px solid var(--color-border);
  color: var(--color-text-dim); font-size: 0.92rem;
}

/* ── narrative blocks ────────────────────────────────────────────────── */
.narrative { display: grid; gap: 0.9rem; margin-bottom: 1.25rem; }
.nblock-label {
  margin: 0 0 0.2rem; font-family: var(--font-data); font-size: 0.72rem;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--color-accent-blue);
}
.nblock-text { margin: 0; font-size: 0.93rem; }
.nblock-could_disqualify .nblock-label,
.nblock-honest_difficulty .nblock-label { color: var(--color-band-mid); }
.nblock-next_step .nblock-label,
.nblock-first_move .nblock-label { color: var(--color-accent-green); }
.nblock-idea_title .nblock-text { font-size: 1.05rem; font-weight: 700; }
.narrative-pending {
  display: flex; align-items: center; gap: 0.6rem;
  color: var(--color-text-dim); font-size: 0.9rem;
}
.narrative-failed { color: var(--color-band-mid); font-size: 0.9rem; }
.spinner {
  width: 12px; height: 12px; border-radius: 50%;
  border: 2px solid var(--color-border); border-top-color: var(--color-accent-blue);
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }

/* ── component bars ──────────────────────────────────────────────────── */
.bars {
  margin: 1.25rem 0; padding: 0.9rem;
  background: color-mix(in srgb, var(--color-bg) 55%, transparent);
  border-radius: var(--radius);
}
.bars-title {
  margin: 0 0 0.75rem; font-family: var(--font-data); font-size: 0.72rem;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--color-text-dim);
}
.bar { margin-bottom: 0.85rem; }
.bar:last-child { margin-bottom: 0; }
.bar-head { display: flex; align-items: baseline; gap: 0.5rem; }
.bar-label { flex: 1; font-size: 0.88rem; }
.bar-weight { font-family: var(--font-data); font-size: 0.68rem; color: var(--color-text-dim); }
.bar-value {
  font-family: var(--font-data); font-size: 0.85rem; font-weight: 700;
  min-width: 2.8rem; text-align: right; font-variant-numeric: tabular-nums;
}
.bar-track {
  height: 6px; margin-top: 0.3rem;
  background: var(--color-border); border-radius: 3px; overflow: hidden;
}
.bar-fill { height: 100%; background: var(--color-accent-blue); border-radius: 3px; }
.bar-hint { margin: 0.3rem 0 0; font-size: 0.78rem; color: var(--color-text-dim); }
/* The server's per-card `detail` (CONTRACTS.md §3). Rendered instead of the
   static hint, and marked so a reader can see it is about THIS program rather
   than about the component in general. */
.bar-detail {
  margin: 0.35rem 0 0; padding-left: 0.6rem;
  border-left: 2px solid color-mix(in srgb, var(--color-accent-blue) 55%, transparent);
  font-size: 0.8rem; color: var(--color-text);
}

/* ── apply block ─────────────────────────────────────────────────────── */
.apply {
  margin-top: 1.25rem; padding: 1rem;
  background: color-mix(in srgb, var(--color-accent-blue) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent-blue) 35%, transparent);
  border-radius: var(--radius);
}
.apply-title {
  margin: 0 0 0.6rem; font-family: var(--font-data); font-size: 0.75rem;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--color-accent-blue);
}
.apply-kind-note {
  margin: 0 0 0.75rem; font-size: 0.85rem; color: var(--color-band-mid);
}
/* Anything that is not open for submission is visually distinct from the one
   kind that is, so "not open yet" is legible before the label is read. */
.apply-forecast_opportunity, .apply-program_listing, .apply-unknown {
  background: color-mix(in srgb, var(--color-band-mid) 8%, transparent);
  border-color: color-mix(in srgb, var(--color-band-mid) 45%, transparent);
}
.apply-forecast_opportunity .apply-title,
.apply-program_listing .apply-title,
.apply-unknown .apply-title { color: var(--color-band-mid); }
.apply-primary { width: 100%; margin-bottom: 0.85rem; text-align: center; }
.apply-rows { display: grid; gap: 0.45rem; }
.apply-row { display: flex; gap: 0.75rem; align-items: baseline; font-size: 0.88rem; }
.apply-key {
  flex: 0 0 6.5rem;
  font-family: var(--font-data); font-size: 0.7rem; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--color-text-dim);
}
.apply-val { flex: 1; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.apply-date { font-family: var(--font-data); }
.apply-countdown {
  padding: 0.05rem 0.5rem; border-radius: 999px;
  background: color-mix(in srgb, var(--color-accent-green) 18%, transparent);
  color: var(--color-accent-green);
  font-family: var(--font-data); font-size: 0.75rem;
}
.apply-row-urgent .apply-countdown {
  background: color-mix(in srgb, var(--color-danger) 20%, transparent);
  color: var(--color-danger);
}
.apply-note { font-size: 0.78rem; color: var(--color-text-dim); }
.apply-email { color: var(--color-accent-green); font-family: var(--font-data); }

/* ── prerequisite strip ──────────────────────────────────────────────── */
.prereq {
  margin: 2rem 0 1rem; padding: 1.1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-band-mid); border-radius: calc(var(--radius) * 1.4);
}
.prereq-title { margin: 0; font-size: 1.05rem; color: var(--color-band-mid); }
.prereq-hint { margin: 0.3rem 0 0.9rem; font-size: 0.88rem; color: var(--color-text-dim); }
.prereq-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; }
.prereq-item { display: flex; flex-direction: column; gap: 0.15rem; }
.prereq-link { color: var(--color-accent-blue); font-weight: 700; }
.prereq-note { font-size: 0.85rem; color: var(--color-text-dim); }

/* ── history panel ───────────────────────────────────────────────────── */
.history, .history-panel { margin: 1.25rem 0; }
.history-title, .history-panel .section-title { margin: 0 0 0.5rem; }
.history-title {
  font-family: var(--font-data); font-size: 0.72rem; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--color-text-dim);
}
.history-list { list-style: none; margin: 0.5rem 0 0; padding: 0; display: grid; gap: 0.3rem; }
.history-item {
  display: flex; gap: 0.75rem; align-items: baseline;
  padding: 0.4rem 0.6rem; background: var(--color-surface);
  border-radius: 6px; font-size: 0.85rem;
}
.history-name { flex: 1; }
.history-fy { color: var(--color-text-dim); font-size: 0.78rem; }

/* ── no-match screen ─────────────────────────────────────────────────── */
.nomatch {
  margin: 1rem 0 1.5rem; padding: 1.5rem;
  background: linear-gradient(
    160deg,
    color-mix(in srgb, var(--color-band-mid) 12%, var(--color-surface)),
    var(--color-surface));
  border: 1px solid var(--color-band-mid);
  border-radius: calc(var(--radius) * 1.6);
}
.nomatch-headline {
  margin: 0; font-size: 1.75rem; line-height: 1.2; letter-spacing: -0.01em;
  color: var(--color-band-mid);
}
.nomatch-sub {
  margin: 0.6rem 0 1.25rem; font-family: var(--font-data); font-size: 0.85rem;
  color: var(--color-text);
}
.nomatch-why-title {
  margin: 0 0 0.5rem; font-family: var(--font-data); font-size: 0.75rem;
  letter-spacing: 0.07em; text-transform: uppercase; color: var(--color-text-dim);
}
.nomatch-why-text { margin: 0 0 0.7rem; font-size: 0.93rem; }
.nomatch-why-text:last-child { margin-bottom: 0; }

.alternatives { margin: 2rem 0; }
.alt-list { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: var(--gap); }
.alt {
  padding: 0.9rem 1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: var(--radius);
  border-left: 3px solid var(--color-accent-green);
}
.alt-label { color: var(--color-accent-green); font-weight: 700; }
.alt-why { margin: 0.35rem 0 0; font-size: 0.9rem; color: var(--color-text-dim); }

.crosslink {
  margin: 2rem 0; padding: 1.25rem;
  background: color-mix(in srgb, var(--color-accent-blue) 12%, var(--color-surface));
  border: 1px solid var(--color-accent-blue);
  border-radius: calc(var(--radius) * 1.4);
}
.crosslink .btn { margin-top: 0.9rem; }

.floor-note {
  margin: 1.5rem 0; padding: 0.75rem 0.9rem;
  font-size: 0.85rem; color: var(--color-text-dim);
  border: 1px dashed var(--color-border); border-radius: var(--radius);
}

/* ── errors ──────────────────────────────────────────────────────────── */
.errorscreen {
  margin: 1.5rem 0; padding: 1.5rem;
  background: var(--color-surface);
  border: 1px solid var(--color-danger); border-radius: calc(var(--radius) * 1.4);
}
.errorscreen-title { margin: 0; font-size: 1.4rem; color: var(--color-danger); }
.errorscreen-body { margin: 0.6rem 0 0; font-size: 0.95rem; }
.errorscreen-partial { margin: 0.75rem 0 0; font-size: 0.82rem; color: var(--color-text-dim); }

/* ── report actions ──────────────────────────────────────────────────── */
.report-actions { display: flex; flex-wrap: wrap; gap: var(--gap); align-items: center; margin: 1rem 0; }
.report-hint { flex-basis: 100%; }

/* ── skeletons ───────────────────────────────────────────────────────── */
.skeleton, .card-skeleton {
  position: relative; overflow: hidden;
  background: var(--color-surface);
}
.card-skeleton { padding: 1.1rem; border-radius: var(--radius); border: 1px solid var(--color-border); }
.skeleton-line { height: 0.85rem; margin-bottom: 0.6rem; border-radius: 4px; background: var(--color-border); }
.skeleton-title { width: 70%; height: 1.1rem; }
.skeleton-sub { width: 45%; }
.skeleton-facts { width: 90%; }
.skeleton::after, .card-skeleton::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--color-text) 7%, transparent), transparent);
  animation: shimmer 1.4s infinite;
}
@keyframes shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) {
  .skeleton::after, .card-skeleton::after { animation: none; }
}

/* ── banner + toast ──────────────────────────────────────────────────── */
.banner, .toast {
  position: fixed; left: 1rem; right: 1rem; z-index: 20;
  bottom: calc(1rem + var(--safe-bottom));
  display: flex; align-items: center; gap: var(--gap);
  padding: 0.75rem 1rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border); border-radius: var(--radius);
  box-shadow: 0 8px 28px rgb(0 0 0 / 45%);
}
.banner[hidden], .toast[hidden] { display: none; }
.banner-text, .toast-text { flex: 1; margin: 0; font-size: 0.92rem; }
.toast { border-color: var(--color-accent-green); }

@media (min-width: 34rem) {
  .banner, .toast { left: auto; right: 1rem; max-width: 26rem; }
}

/* ════════════════════════════════════════════════════════════════════════
   PRINT — handoff.md §9. The PDF is the only artifact a judge keeps after the
   demo, so it is treated as a deliverable, not as a fallback.

   Rules encoded below:
   · nav, chrome, buttons and the mic are stripped
   · every card avoids a page break through its middle
   · everything the app collapses renders OPEN
   · running header carries the company name and the generation date
   · component bars print as VALUES — the CSS bar is not guaranteed to survive
     background-graphics being off, and a bar with no fill reads as a zero
   · apply URLs print as visible text next to their link, because a PDF whose
     links you cannot type is not actionable
   · deadlines print as absolute dates; the live countdown is removed
   ════════════════════════════════════════════════════════════════════════ */
@media print {
  @page { margin: 1.5cm 1.4cm; }

  :root {
    --color-bg: #ffffff;
    --color-surface: #ffffff;
    --color-border: #b9c2d0;
    --color-text: #101828;
    --color-text-dim: #4a5568;
    --color-accent-blue: #14448f;
    --color-accent-green: #0f6b46;
    --color-band-good: #0f6b46;
    --color-band-mid: #8a5a00;
    --color-band-low: #8a3f00;
    --color-danger: #8a1020;
  }

  body {
    background: #fff; color: #101828;
    padding: 0; font-size: 8.4pt; line-height: 1.28;
  }
  /* Room for the fixed running header and footer below. Chrome repeats a
     position:fixed element on every printed page but clips it to the page's
     content area, so a negative offset into the margin box disappears entirely —
     the header sits at top: 0 and the page reserves space for it instead. */
  .wrap { max-width: none; padding: 20pt 0 22pt; }

  /* chrome */
  /* :not(.apply-primary) is load-bearing. The apply link is styled as a button,
     and blanket-hiding buttons in print is how the one actionable thing on the
     page disappears from the PDF. */
  .app-bar, .banner, .toast, .screen-only,
  .btn:not(.apply-primary), .card-toggle, .mic, .backlink, .report-actions,
  /* The generic per-component sentence ("Whether the deadline leaves enough
     room to write a real proposal") is identical on every card, so printing it
     five times per card across five cards is 25 repeats of the same four lines
     — and it was the single biggest reason a card overflowed its page. The
     label, weight and value still carry the meaning. `.bar-detail` is NOT
     hidden: that one is the server's card-specific eligibility reasoning. */
  .bar-hint,
  .apply-countdown, .bar-track, .skeleton, .card-skeleton,
  /* A spinner on paper is a progress indicator that never finishes. The
     print-only .narrative-absent line says what actually happened instead. */
  .narrative-pending, .spinner, .working,
  #install-button, #update-toast, #ios-banner { display: none !important; }

  .narrative-absent { color: #4a5568; font-style: italic; }
  .bar-detail { border-left: 1.5pt solid #14448f; color: #101828; }
  .apply-kind-note { color: #8a5a00; font-weight: 700; }

  .print-only { display: block; }

  /* Running header and footer. position: fixed repeats them on every printed
     page; the @page margins above reserve the room they sit in. */
  .print-header, .print-footer {
    position: fixed; left: 0; right: 0;
    display: flex; justify-content: space-between; gap: 1rem;
    background: #fff;
    font-family: var(--font-data); font-size: 8pt; line-height: 1.25; color: #4a5568;
  }
  .print-header {
    top: 0;
    padding-bottom: 4pt; border-bottom: 0.5pt solid #b9c2d0;
  }
  .print-company { font-weight: 700; color: #101828; }
  .print-footer {
    bottom: 0;
    padding-top: 4pt; border-top: 0.5pt solid #b9c2d0;
  }
  .print-footer span:first-child { max-width: 70%; }
  .print-contact { white-space: nowrap; }

  /* everything collapsed in the app renders open in print */
  .card-body[hidden] { display: block !important; }
  .chip-editor { display: none !important; }

  .page-title { font-size: 16pt; }
  .page-sub { color: #4a5568; }
  .section-title { color: #101828; }

  .stats { grid-template-columns: repeat(4, 1fr); gap: 6pt; }
  .stat { border: 0.5pt solid #b9c2d0; padding: 6pt; }
  .stat-value { font-size: 13pt; color: #14448f; }

  /* PAGINATION. `break-inside: avoid` on the whole card looked careful and cost
     about 40% of the paper: any card taller than the space left on the page was
     pushed whole to the next one, leaving quarter-full pages behind, and the
     cards taller than a full page split anyway — so the rule bought nothing it
     claimed to. Measured density per page ran 0.31, 1.0, 0.25, 0.96, 0.22…
     A card may now flow across a break; the units INSIDE it may not, which is
     what actually matters for reading. */
  .cards { gap: 0; }

  /* ONE OPPORTUNITY PER PAGE. Each card starts a fresh page and is kept whole.
     The previous rule let cards flow across breaks to save paper, which packed
     the pages but meant an opportunity could begin two thirds down a page and
     finish on the next — so a reader comparing two programmes had to hold one
     in their head while turning. A grant report is read one opportunity at a
     time, not skimmed, so clean mapping beats density here.

     `:first-of-type` has no break-before, or the report opens on a blank sheet
     after the stats band. */
  .card {
    break-before: page; page-break-before: always;
    /* `break-inside: auto`, deliberately, alongside break-before: page.
       The two rules do different jobs and only one of them is wanted here.
       `break-before` is what gives the clean one-opportunity-per-page mapping.
       Adding `break-inside: avoid` on top looked like belt and braces but made
       the worst case worse: on a card a few lines over, the browser could not
       honour it, broke anyway, and threw the whole apply block (avoid, so
       indivisible) onto a fresh page while a third of the previous page sat
       empty. Letting the card flow means an oversized card fills its page and
       spills only the remainder. */
    break-inside: auto; page-break-inside: auto;
    border: 0.75pt solid #b9c2d0; border-left-width: 3pt;
    padding: 9pt 10pt; margin: 0;
    animation: none;
  }

  /* Everything below exists to fit one opportunity on one page. Measured: at
     10.5pt with default block spacing, four narrative blocks plus the component
     table plus the apply panel ran to about 1.6 pages, so every card spilled
     onto a second sheet and the "one per page" rule bought a half-empty page
     each time instead of a clean mapping. */
  .nblock { margin: 0 0 4.5pt; }
  .nblock:last-child { margin-bottom: 0; }
  .nblock-label { margin: 0 0 1.5pt; font-size: 7.5pt; letter-spacing: 0.1em; }
  .nblock p, .nblock-body { margin: 0; line-height: 1.3; }
  .card-objective { margin: 3pt 0 4.5pt; padding-left: 5pt; font-size: 8pt; line-height: 1.28; }
  .card-facts { gap: 8pt; margin: 5pt 0; }
  .card-head { margin-bottom: 3pt; }
  .history { margin-top: 6pt; }
  .history-item { padding: 2pt 0; font-size: 8.5pt; }
  /* The apply block is one indivisible unit (break-inside: avoid), so on Track B
     it was moving whole to the next page and taking 7 lines with it while the
     card page sat full at 44. Laid out as a run-in row it costs 3 lines instead
     of 7 — the difference between one opportunity per page and two. */
  .apply { margin-top: 5pt; padding: 5pt 6pt; }
  .apply-title { margin-bottom: 2pt; }
  .apply-primary { margin-bottom: 3pt; text-align: left; }
  .apply-rows {
    display: flex; flex-wrap: wrap; gap: 2pt 14pt;
    font-size: 7.8pt; line-height: 1.25;
  }
  .apply-row { display: inline-flex; gap: 4pt; align-items: baseline; font-size: 7.8pt; }
  .apply-key { font-size: 7pt; letter-spacing: 0.06em; }
  /* The first card gets a page break too. Letting it share page one with the
     stats band was the last thing splitting an opportunity: the header, the
     degraded-source notice and the four stat tiles ate roughly a third of the
     sheet, so card one always ran over. Page one is now a cover — title,
     company, stats — and every opportunity owns a page from there. */

  /* A card taller than one page still has to split — nothing can prevent that.
     Sub-unit rules below keep the split in a sensible place when it happens. */
  /* Keep the identity of the card with its first content: a title strand alone
     at the foot of a page is the one break that genuinely misleads. */
  .card-head, .card-band, .card-facts {
    break-inside: avoid; page-break-inside: avoid;
    break-after: avoid-page; page-break-after: avoid;
  }
  /* The indivisible units. Each is small enough to always fit a page. */
  .nblock, .bar, .apply, .history, .history-item, .prereq-item, .alt,
  .card-objective {
    break-inside: avoid; page-break-inside: avoid;
  }
  .nblock-label, .bars-title, .apply-title, .section-title {
    break-after: avoid-page; page-break-after: avoid;
  }
  .card-title { font-size: 11pt; line-height: 1.22; }
  .card-score-value { font-size: 14pt; }

  /* Component bars as printed values. The label/value row already carries the
     number; the track is hidden above, so nothing depends on a rendered bar. */
  .bars { border: 0.5pt solid #b9c2d0; padding: 5pt; background: none;
          break-inside: auto; page-break-inside: auto; }
  .bar { margin-bottom: 2.5pt; }
  .bar-detail, .bar-note { font-size: 7.5pt; line-height: 1.25; }
  .bar-value { font-weight: 700; }

  .apply { border: 0.75pt solid #14448f; background: none; }
  .apply-primary {
    display: inline !important;
    padding: 0; min-height: 0; background: none !important;
    border: none; color: #14448f !important; font-weight: 700;
  }
  .prereq, .nomatch, .crosslink, .alt, .errorscreen, .disclosure {
    break-inside: avoid; page-break-inside: avoid;
    border: 0.75pt solid #b9c2d0; background: none;
  }
  .nomatch-headline { font-size: 15pt; }

  /* The PDF is the artifact a judge keeps, so a link they cannot type is dead.
     Every external href prints its target next to its text. */
  a[href^="http"]:after {
    content: " (" attr(href) ")";
    font-family: var(--font-data); font-size: 8pt; color: #14448f;
    word-break: break-all;
  }
  a[href^="mailto:"] { color: #14448f; }
  a { color: #14448f; text-decoration: none; }
}
