/* ============================================================
   show-your-work — Component layer
   Every value here reads a token from /tokens/*. Raw colors are
   rejected by scripts/check-style-tokens.mjs, so re-theming a
   fork never means hunting through this file.

   Order: chrome (header/footer) → page scaffolding → primitives
   → surfaces (cards, tags, chips) → Fit → graph → search.
   ============================================================ */

/* ------------------------------------------------------------
   Site chrome
   ------------------------------------------------------------ */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--bg);
  border-bottom: 1px solid var(--border-hairline);
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  height: 60px;
}

.site-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-body);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
  color: var(--fg);
  text-decoration: none;
}

.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.site-nav a {
  display: flex;
  align-items: center;
  font-size: var(--text-body);
  font-weight: var(--weight-medium);
  color: var(--fg-muted);
  text-decoration: none;
}

.site-nav a:hover {
  color: var(--fg);
}

.site-nav a[aria-current="page"] {
  color: var(--fg);
  font-weight: var(--weight-semibold);
}

/* Mobile: the same links stack under the bar behind a menu button. */
.site-nav--mobile {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding-bottom: var(--space-3);
}

.site-nav--mobile a {
  min-height: var(--touch-min);
}

.nav-toggle {
  width: var(--touch-min);
  height: var(--touch-min);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--fg);
  font-size: 1.125rem;
  line-height: 1;
  cursor: pointer;
}

.site-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--section-gap);
  padding-top: var(--space-8);
  padding-bottom: var(--space-12);
  border-top: 1px solid var(--border-hairline);
  font-size: var(--text-xs);
  color: var(--fg-subtle);
}

.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  flex-basis: 100%;
}

.site-footer nav a {
  color: var(--fg-muted);
  text-decoration: none;
}

.site-footer nav a:hover {
  color: var(--fg);
}

.site-footer__sep {
  color: var(--fg-faint);
}

.site-footer__route {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
}

/* ------------------------------------------------------------
   Page scaffolding
   ------------------------------------------------------------ */

.page {
  padding-top: var(--space-10);
}

.page > * + * {
  margin-top: var(--space-4);
}

.page h1 {
  font-size: var(--text-h1);
  letter-spacing: var(--tracking-display);
}

/* The home page is the one place the type scale reaches its top step. Until
   something used --text-display, the largest type anywhere was a 28→40px h1,
   which is the mechanical reason the page read flat. */
.page--home h1 {
  font-size: var(--text-display);
}

/* One line under the CTA row saying what Fit is. Sits with the buttons rather
   than starting a new block, so it reads as their caption.

   text-wrap: pretty because a two-word orphan on the second line is exactly
   what this sentence produced at desktop width. Ignored by browsers that do
   not support it, which is the correct degradation for a wrapping hint. */
.cta-note {
  margin-top: var(--space-3);
  max-width: var(--measure-reading);
  font-size: var(--text-body);
  color: var(--fg-muted);
  text-wrap: pretty;
}

.featured {
  margin-top: var(--section-gap);
}

.featured__more {
  display: inline-flex;
  align-items: center;
  margin-top: var(--space-4);
  font-size: var(--text-body);
  color: var(--fg-muted);
  text-decoration: none;
}

.featured__more:hover {
  color: var(--fg);
}

.page h2 {
  margin-top: var(--space-10);
}

.page-back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-body);
  color: var(--fg-muted);
  text-decoration: none;
}

.page-back:hover {
  color: var(--fg);
}

.lede {
  max-width: var(--measure-reading);
  font-size: var(--text-lead);
  line-height: var(--line-body);
  color: var(--fg-muted);
  text-wrap: pretty;
}

.prose {
  max-width: var(--measure-reading);
  font-size: var(--text-reading);
  line-height: var(--line-reading);
  color: var(--fg-reading);
}

/* ---------- Long-form body blocks ----------
   The element scope for an authored body (packages/content/body.py).

   Rhythm is owned by the flow, not by each block: the reset below clears every
   child's own margins, then one rule spaces every sibling, so a block type
   added later inherits the rhythm instead of inventing one. The corollary is
   that no rule further down may set `margin` — a `margin: 0` in a block rule is
   more specific than the flow rule and silently zeroes the gap above it, which
   is exactly what the first version of this section did to ul, blockquote and
   pre. Set padding and borders on blocks; leave margins to these three rules. */
.prose > * {
  margin-top: 0;
  margin-bottom: 0;
}

.prose > * + * {
  margin-top: var(--space-5);
}

/* A heading belongs to what follows it, so it opens a clear gap above itself
   and closes the one below. Done as a sibling selector rather than a negative
   margin-bottom: the negative version has to be kept in arithmetic sync with
   the flow gap, and reads as a correction rather than as an intent. */
.prose h2,
.prose h3 {
  margin-top: var(--space-10);
}

.prose h2 + *,
.prose h3 + * {
  margin-top: var(--space-3);
}

.prose h2 {
  font-size: var(--text-h2);
  font-weight: var(--weight-medium);
}

.prose h3 {
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
}

.prose ul,
.prose ol {
  padding-left: 1.3rem;
}

.prose li + li {
  margin-top: var(--space-2);
}

/* Quotes carry a rule rather than quotation marks: the mark would be typed
   into the text on some pages and not others, and the rule always renders. */
.prose blockquote {
  padding-left: var(--space-5);
  border-left: 2px solid var(--border);
  color: var(--fg-muted);
}

.prose blockquote p {
  font-style: italic;
}

.prose blockquote cite {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-body);
  font-style: normal;
  color: var(--fg-subtle);
}

/* Code scrolls inside its own box. Wrapping a shell line at a random column
   makes it unrunnable, so the overflow is horizontal and contained here rather
   than pushing the page sideways — which is what check-ux's overflow rule
   would catch. */
.prose pre {
  padding: var(--space-4);
  overflow-x: auto;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
  background: var(--ink-05);
  font-size: var(--text-xs);
  line-height: var(--line-body);
}

/* The inline-code chip treatment would double up inside a block. */
.prose pre code {
  padding: 0;
  background: none;
  border-radius: 0;
  font-size: inherit;
}

/* An aside the reader can skip, marked by weight of surface rather than by a
   color that would have to carry meaning on its own. */
.prose .note {
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--text-body);
  line-height: var(--line-body);
  color: var(--fg-muted);
}

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

.error {
  color: var(--danger);
}

/* ------------------------------------------------------------
   Primitives
   ------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--touch-min);
  padding: 0.5rem 1.15rem;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--surface-inverse);
  color: var(--fg-on-inverse);
  font-size: var(--text-body);
  font-weight: var(--weight-medium);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color var(--dur-fast) var(--ease-standard),
    opacity var(--dur-fast) var(--ease-standard);
}

.btn:hover {
  opacity: 0.9;
}

.btn.secondary {
  background: transparent;
  color: var(--fg);
  border-color: var(--border);
}

.btn.secondary:hover {
  opacity: 1;
  background: var(--ink-05);
}

.btn:disabled {
  opacity: 0.55;
  cursor: wait;
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
}

/* Contact strip — email and profile links share one outline, the way the
   sibling site's contact bar does. Wraps to its own rows on a phone. */
.contact-row {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: stretch;
  max-width: 100%;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}

.contact-row__item {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min);
  min-width: 0;
  padding: 0 var(--space-4);
  overflow: hidden;
  color: var(--fg-muted);
  font-size: var(--text-body);
  text-decoration: none;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.contact-row__item + .contact-row__item {
  border-left: 1px solid var(--border-hairline);
}

.contact-row__item:hover,
.contact-row__item:focus-visible {
  background: var(--ink-05);
  color: var(--fg);
}

button.linkish {
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  cursor: pointer;
}

button.linkish:active {
  color: var(--brand-deep);
}

.prose-link {
  color: var(--fg);
  font-weight: var(--weight-medium);
  text-decoration: underline;
  text-decoration-color: var(--ink-40);
  text-underline-offset: 0.18em;
}

.prose-link:hover {
  text-decoration-color: var(--accent);
}

/* ------------------------------------------------------------
   Surfaces — card lists, tags
   ------------------------------------------------------------ */

.card-list {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.card-link {
  display: block;
  padding: var(--space-5);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
  color: inherit;
  text-decoration: none;
  transition:
    box-shadow var(--dur-fast) var(--ease-standard),
    transform var(--dur-fast) var(--ease-standard);
}

.card-link__title {
  display: block;
  font-size: var(--text-h3);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-tight);
}

.card-link__summary {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-body);
  line-height: var(--line-body);
  color: var(--fg-muted);
}

.card-empty {
  padding: var(--space-5);
  border: 1px dashed var(--border);
  border-radius: var(--radius-2xl);
  color: var(--fg-muted);
  font-size: var(--text-body);
}

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.tags li {
  display: inline-flex;
  align-items: center;
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--fg-muted);
  font-size: var(--text-xs);
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
}

a.tag:hover {
  color: var(--fg);
  border-color: var(--border);
}

/* A described skill is worth hovering — hint it without shouting. */
.tag--described {
  border-style: dashed;
  cursor: help;
}

/* ------------------------------------------------------------
   Project brief — the editorial contract every work page shares
   ------------------------------------------------------------ */

.project-brief {
  margin: var(--space-8) 0;
  padding: var(--space-5);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.project-brief__grid {
  display: grid;
  gap: 0 var(--space-6);
}

.project-brief__cell {
  padding: var(--space-5) 0;
  border-bottom: 1px solid var(--border-hairline);
}

.project-brief__cell:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.project-brief__cell h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-muted);
}

.project-brief__cell p,
.project-brief__cell li {
  font-size: var(--text-body);
  line-height: var(--line-body);
  color: var(--fg-reading);
}

.project-brief__cell ul {
  margin: 0;
  padding-left: 1.1rem;
}

.project-brief__cell li + li {
  margin-top: var(--space-2);
}

@media (min-width: 768px) {
  .project-brief {
    padding: var(--space-6);
  }

  .project-brief__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .project-brief__cell--wide {
    grid-column: 1 / -1;
  }
}

/* ------------------------------------------------------------
   Skill bank
   ------------------------------------------------------------ */

.skill-bank {
  margin-top: var(--section-gap);
  padding-top: var(--space-8);
  border-top: 1px solid var(--border-hairline);
}

.skill-bank-title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-h2);
  font-weight: var(--weight-medium);
}

.skill-bank-groups {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  margin-top: var(--space-6);
}

.skill-bank-cat {
  margin-bottom: var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--fg-muted);
}

.skill-bank-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.skill-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2rem;
  padding: 0 var(--space-3);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--fg-muted);
  font-size: var(--text-xs);
  line-height: 1;
  cursor: pointer;
  transition:
    background-color var(--dur-fast) var(--ease-standard),
    color var(--dur-fast) var(--ease-standard);
}

.skill-chip:hover {
  color: var(--fg);
  border-color: var(--border);
}

/* The one genuinely stateful chip in the system: --brand-deep is specified as
   the pressed accent, and this is what "pressed" means here. */
.skill-chip.pressed {
  background: var(--brand-soft);
  border-color: var(--brand-deep);
  color: var(--fg);
}

.skill-dot {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
}

/* One rule per category slot, because the alternative — style="background:
   var(--cat-3)" from SkillBank.tsx — is a style attribute, and `style-src
   'self'` blocks those. The dots were silently stripped wherever the CSP was
   actually enforced. Purely decorative; the chip label carries the meaning. */
.skill-dot.cat-1 { background: var(--cat-1); }
.skill-dot.cat-2 { background: var(--cat-2); }
.skill-dot.cat-3 { background: var(--cat-3); }
.skill-dot.cat-4 { background: var(--cat-4); }
.skill-dot.cat-5 { background: var(--cat-5); }
.skill-dot.cat-6 { background: var(--cat-6); }
.skill-dot.cat-7 { background: var(--cat-7); }
.skill-dot.cat-8 { background: var(--cat-8); }

.skill-count {
  color: var(--fg-subtle);
  font-size: var(--text-2xs);
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------
   Fit — paste surface + evidence brief
   ------------------------------------------------------------ */

.fit-drop {
  padding: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-2xl);
  background: var(--surface);
}

.fit-drop textarea {
  display: block;
  width: 100%;
  min-height: 180px;
  padding: var(--space-3);
  border: none;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--fg);
  font-size: var(--text-body);
  line-height: var(--line-body);
  resize: vertical;
  outline: none;
}

.fit-drop textarea::placeholder {
  color: var(--fg-subtle);
}

.fit-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: var(--text-xs);
}

.fit-brief {
  margin-top: var(--space-10);
}

.fit-brief h2 {
  margin-top: var(--space-8);
  margin-bottom: var(--space-3);
}

.fit-reqs {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.fit-req {
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--border);
  border-radius: var(--radius-2xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}

.fit-req-head {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.fit-req-text {
  font-weight: var(--weight-medium);
}

.fit-req .muted {
  margin-top: var(--space-1);
  font-size: var(--text-body);
}

.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.15rem var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--ink-05);
  color: var(--fg-muted);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Status ramp: the left rule and the leading badge carry the verdict, so
   the state survives both color-blindness and a grayscale print. */
.status-aligned {
  border-left-color: var(--positive);
}

.status-aligned .badge:first-child {
  background: var(--positive-soft);
  color: var(--positive);
}

.status-partial {
  border-left-color: var(--caution);
}

.status-partial .badge:first-child {
  background: var(--caution-soft);
  color: var(--caution);
}

.status-missing,
.status-not_evidenced_on_site {
  border-left-color: var(--danger);
}

.status-missing .badge:first-child,
.status-not_evidenced_on_site .badge:first-child {
  background: var(--danger-soft);
  color: var(--danger);
}

.fit-cites {
  margin: var(--space-3) 0 0;
  padding-left: 1.1rem;
  font-size: var(--text-body);
  color: var(--fg-muted);
}

.fit-cites li + li {
  margin-top: var(--space-1);
}

.fit-cites a {
  color: var(--fg);
  font-weight: var(--weight-medium);
  text-decoration-color: var(--ink-40);
}

.fit-cites a:hover {
  text-decoration-color: var(--accent);
}

/* ------------------------------------------------------------
   Knowledge lens — the compact graph embedded on content pages
   ------------------------------------------------------------ */

.knowledge-lens {
  margin-top: var(--section-gap);
  padding-top: var(--space-8);
  border-top: 1px solid var(--border-hairline);
}

.knowledge-lens__title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-h2);
  font-weight: var(--weight-medium);
}

.knowledge-lens__hint {
  font-size: var(--text-xs);
}

/* ------------------------------------------------------------
   Graph page controls
   ------------------------------------------------------------ */

.graph-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
}

.graph-toolbar label {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--touch-min);
  font-size: var(--text-body);
  color: var(--fg-muted);
}

.graph-hint {
  font-size: var(--text-xs);
}

/* ------------------------------------------------------------
   Search palette
   ------------------------------------------------------------ */

.search-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 2rem;
  padding: 0 var(--space-3);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--fg-muted);
  font-size: var(--text-xs);
  cursor: pointer;
}

.search-trigger:hover {
  color: var(--fg);
  border-color: var(--border);
}

.search-trigger kbd {
  padding: 0 var(--space-1);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  color: var(--fg-subtle);
  font-size: var(--text-2xs);
}

.search-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: max(9vh, var(--space-8)) var(--space-4) var(--space-4);
  background: var(--scrim);
}

.search-dialog {
  display: flex;
  flex-direction: column;
  width: min(640px, 100%);
  max-height: min(70vh, 520px);
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-modal);
}

.search-input-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-hairline);
}

.search-input-row input {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: none;
  outline: none;
  background: transparent;
  color: var(--fg);
  font-size: var(--text-lead);
}

.search-input-row input::placeholder {
  color: var(--fg-subtle);
}

.search-esc {
  padding: 0.15rem var(--space-2);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-subtle);
  font-size: var(--text-2xs);
  text-transform: lowercase;
  cursor: pointer;
}

.search-results {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-2);
}

.search-empty {
  padding: var(--space-6) var(--space-4);
  text-align: center;
  color: var(--fg-muted);
  font-size: var(--text-body);
  line-height: var(--line-body);
}

.search-empty span {
  color: var(--fg);
  font-weight: var(--weight-medium);
}

.search-group-label {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--fg-muted);
}

.search-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg);
  font-size: var(--text-body);
  text-align: left;
  cursor: pointer;
}

.search-row.active {
  background: var(--brand-soft);
}

.search-row-title {
  font-weight: var(--weight-medium);
}

.search-row-meta {
  flex: none;
  color: var(--fg-subtle);
  font-size: var(--text-xs);
}

.search-footer {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--border-hairline);
  color: var(--fg-subtle);
  font-size: var(--text-2xs);
}

/* ------------------------------------------------------------
   Responsive
   ------------------------------------------------------------ */

@media (min-width: 768px) {
  .card-list--split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
