/* Programming Language Atlas — documentation-first design system */

:root {
  --fg: #111318;
  --muted: #59616d;
  --line: #252a31;
  --line-soft: #d7dce2;

  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-alt: #f0f3f6;

  --accent: #1558b0;
  --visited: #4a3f9e;
  --success: #176b3a;
  --warning: #8a5a00;
  --secondary: #6b3fa0;
  --info: #0b6e75;
  --unknown: #737b86;

  --surface-hover: #fbfcfe;

  --max-width: 1180px;

  color-scheme: light;
}

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

html { -webkit-text-size-adjust: 100%; }

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* Anchor targets clear the heading rule when jumped to from a table of contents. */
:target { scroll-margin-top: 12px; }
h1, h2, h3, section, tr { scroll-margin-top: 12px; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 8px 12px;
  font-size: 14px;
  z-index: 10;
}

.skip-link:focus {
  left: 8px;
  top: 8px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums lining-nums;
  overflow-wrap: break-word;
}

.wrap {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 16px;
}

/* ---------- Header / navigation ---------- */

.site-header {
  background: var(--surface-alt);
  border-bottom: 1px solid var(--line);
  padding-top: 24px;
  text-align: center;
}

.site-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.site-title a { color: var(--fg); text-decoration: none; }
.site-title a:visited { color: var(--fg); }

.site-tagline {
  margin: 4px 0 0;
  font-size: 13px;
  color: var(--muted);
}

.site-nav {
  margin-top: 12px;
  font-size: 14px;
  border-top: 1px solid var(--line-soft);
  padding: 8px 0;
}

.site-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  justify-content: center;
}

.site-nav a { color: var(--accent); text-decoration: none; }
.site-nav a:hover { text-decoration: underline; }
.site-nav a:visited { color: var(--visited); }
.site-nav a[aria-current="page"] {
  color: var(--fg);
  font-weight: 600;
  text-decoration: none;
}

/* ---------- Links ---------- */

a { color: var(--accent); }
a:visited { color: var(--visited); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ---------- Typography ---------- */

main { padding-bottom: 24px; }

h1 {
  font-size: 1.7rem;
  line-height: 1.25;
  margin: 20px 0 6px;
}

h2 {
  font-size: 1.2rem;
  margin: 35px 0 12px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--line-soft);
}

h3 {
  font-size: 1rem;
  margin: 20px 0 8px;
}

h4 {
  font-size: 0.9rem;
  margin: 16px 0 6px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

p { margin: 0 0 12px; }

.lede {
  text-align: center;
  max-width: 780px;
  margin: 0 auto 16px;
  color: var(--muted);
  font-size: 14.5px;
}

.section-note {
  font-size: 13px;
  color: var(--muted);
  margin: -4px 0 12px;
}

code, kbd, samp, .mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.92em;
}

p code, li code, td code, th code {
  background: var(--surface-alt);
  border: 1px solid var(--line-soft);
  padding: 0 3px;
}

pre {
  margin: 0 0 12px;
  padding: 11px 13px;
  background: var(--surface);
  border: 1px solid var(--line);
  overflow-x: auto;
  font-size: 13px;
  line-height: 1.45;
}

pre code { background: none; border: 0; padding: 0; }

blockquote {
  margin: 0 0 12px;
  padding: 8px 13px;
  border-left: 3px solid var(--line-soft);
  color: var(--muted);
}

ul, ol { margin: 0 0 12px; padding-left: 22px; }
li { margin-bottom: 4px; }

hr { border: 0; border-top: 1px solid var(--line-soft); margin: 24px 0; }

/* ---------- Cards ---------- */

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
  margin: 0 0 12px;
}

.cards.cols-2 { grid-template-columns: repeat(2, 1fr); }
.cards.cols-3 { grid-template-columns: repeat(3, 1fr); }
.cards.cols-4 { grid-template-columns: repeat(4, 1fr); }
.cards.cols-5 { grid-template-columns: repeat(5, 1fr); }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 11px 13px;
}

.card h3 { margin: 0 0 6px; font-size: 0.95rem; }
.card p { margin: 0 0 6px; font-size: 13.5px; color: var(--muted); }
.card p:last-child, .card ul:last-child { margin-bottom: 0; }
.card ul { font-size: 13px; padding-left: 18px; color: var(--muted); }

a.card {
  display: block;
  text-decoration: none;
  color: var(--fg);
}
a.card:visited { color: var(--fg); }
a.card:hover, a.card:focus-visible {
  border-color: var(--accent);
  background: var(--surface-hover);
}
a.card h3 { color: var(--accent); }
a.card:hover h3 { text-decoration: underline; }

.card-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 6px;
  display: block;
}

/* Statistic tiles */

.stats {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 12px;
  margin-bottom: 12px;
}

.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 11px 13px;
}

.stat .value { font-size: 1.25rem; font-weight: 700; display: block; }
.stat .label { font-size: 12px; color: var(--muted); display: block; margin-top: 2px; }

/* ---------- Status markers ---------- */

.tag {
  display: inline-block;
  font-size: 11.5px;
  line-height: 1.4;
  padding: 0 5px;
  border: 1px solid currentColor;
  color: var(--unknown);
  white-space: nowrap;
  vertical-align: baseline;
}

.tag-static   { color: var(--accent); }
.tag-dynamic  { color: var(--secondary); }
.tag-gc       { color: var(--success); }
.tag-manual   { color: var(--warning); }
.tag-ownership{ color: var(--info); }
.tag-warning  { color: var(--warning); }
.tag-unknown  { color: var(--unknown); }

.legend {
  font-size: 12.5px;
  color: var(--muted);
  margin: 8px 0 12px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
}

/* ---------- Tables ---------- */

.table-scroll {
  overflow: auto;
  border: 1px solid var(--line);
  background: var(--surface);
  max-height: 70vh;
  margin-bottom: 6px;
}

/* The container is a keyboard-operable scroll region, so it takes a focus ring. */
.table-scroll:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

table {
  border-collapse: collapse;
  width: 100%;
  font-size: 13.5px;
  background: var(--surface);
}

/* Size to content so wide tables scroll horizontally instead of crushing their
   columns; min-width keeps short tables filling the panel. */
.table-scroll > table {
  width: auto;
  min-width: 100%;
}

th, td {
  padding: 6px 8px;
  border: 1px solid var(--line-soft);
  text-align: left;
  vertical-align: top;
}

thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-alt);
  font-weight: 700;
  white-space: nowrap;
  /* Collapsed borders do not paint under a sticky cell; draw them as insets. */
  box-shadow: inset 0 -2px 0 var(--line), inset -1px 0 0 var(--line-soft);
}

tbody th[scope="row"] {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--surface);
  font-weight: 700;
  white-space: nowrap;
  box-shadow: inset -1px 0 0 var(--line), inset 0 -1px 0 var(--line-soft);
}

tbody tr.group-start th[scope="row"] {
  box-shadow: inset -1px 0 0 var(--line), inset 0 -1px 0 var(--line-soft),
              inset 0 2px 0 var(--line);
}

thead th:first-child {
  left: 0;
  z-index: 3;
  background: var(--surface-alt);
}

/* Row headers wrap on narrow screens rather than forcing a very wide column. */
@media (max-width: 720px) {
  tbody th[scope="row"] { white-space: normal; min-width: 108px; }
}

tbody tr.group-start th, tbody tr.group-start td {
  border-top: 2px solid var(--line);
}

/* Group label spanning a long matrix, so rows read in labelled blocks. */
th.rowgroup {
  position: sticky;
  left: 0;
  background: var(--surface-alt);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  white-space: nowrap;
}

td.num { text-align: right; }

caption, .table-caption {
  caption-side: bottom;
  text-align: left;
  font-size: 12.5px;
  color: var(--muted);
  padding: 6px 0 0;
  margin-bottom: 12px;
}

/* Infobox (article pages) */

.infobox {
  float: right;
  width: 330px;
  margin: 4px 0 16px 20px;
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: 13px;
}

.infobox .infobox-title {
  background: var(--surface-alt);
  border-bottom: 2px solid var(--line);
  padding: 6px 8px;
  font-weight: 700;
  text-align: center;
  font-size: 14px;
}

.infobox table { font-size: 13px; }
.infobox th, .infobox td { border: 0; border-bottom: 1px solid var(--line-soft); }
.infobox th[scope="row"] { position: static; width: 40%; background: var(--surface); }
.infobox .subhead td {
  background: var(--surface-alt);
  text-align: center;
  font-weight: 700;
  border-top: 1px solid var(--line-soft);
}

/* ---------- Figures / media ---------- */

.figure {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 11px 13px;
  margin: 0 0 12px;
}

.figure .frame {
  aspect-ratio: 16 / 9;
  background: var(--surface-alt);
  border: 1px solid var(--line-soft);
  display: block;
  width: 100%;
  overflow: hidden;
}

.figure .frame.ratio-4-3 { aspect-ratio: 4 / 3; }
.figure .frame img, .figure .frame video, .figure .frame svg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.figure figcaption {
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 8px;
}

.media-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

/* ---------- Section permalinks / back to top ---------- */

.anchor {
  font-weight: 400;
  font-size: 0.8em;
  margin-left: 6px;
  color: var(--muted);
  text-decoration: none;
  opacity: 0;
}

h2:hover .anchor, h2:focus-within .anchor,
h3:hover .anchor, h3:focus-within .anchor,
.anchor:focus-visible { opacity: 1; }
.anchor:hover { color: var(--accent); }

/* Touch devices have no hover, so the marker stays visible there. */
@media (hover: none) {
  .anchor { opacity: 0.6; }
}

.to-top {
  display: block;
  text-align: right;
  font-size: 12.5px;
  margin: -6px 0 0;
}

/* ---------- Table of contents ---------- */

.toc {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 11px 13px;
  margin: 0 0 16px;
  font-size: 13.5px;
}

.toc h2 {
  font-size: 0.95rem;
  margin: 0 0 8px;
  border: 0;
  padding: 0;
}

.toc h2 .anchor { display: none; }

.toc ol {
  margin: 0;
  padding-left: 20px;
  columns: 2;
  column-gap: 24px;
}

.toc li { break-inside: avoid; }

.toc ol ol {
  columns: 1;
  padding-left: 18px;
  margin: 2px 0 4px;
  list-style-type: lower-alpha;
  color: var(--muted);
}

/* ---------- Source / reference notes ---------- */

.sources {
  font-size: 13px;
  color: var(--muted);
}

.sources ol { padding-left: 20px; }

.callout {
  border: 1px solid var(--line);
  border-left: 4px solid var(--warning);
  background: var(--surface);
  padding: 11px 13px;
  font-size: 13.5px;
  margin: 0 0 12px;
}

.callout.info { border-left-color: var(--info); }

/* ---------- Footer ---------- */

.site-footer {
  margin-top: 48px;
  border-top: 1px solid var(--line-soft);
  padding: 16px 0 32px;
  font-size: 12.5px;
  color: var(--muted);
}

.site-footer p { margin: 0 0 6px; }

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

@media (max-width: 1100px) {
  .cards.cols-4 { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 900px) {
  .cards.cols-3, .cards.cols-4, .cards.cols-5 { grid-template-columns: repeat(2, 1fr); }
  .stats { grid-template-columns: repeat(3, 1fr); }
  .infobox { float: none; width: auto; margin: 0 0 16px; }
}

@media (max-width: 720px) {
  .media-row { grid-template-columns: 1fr; }
  .site-nav ul { justify-content: flex-start; }
  .toc ol { columns: 1; }
}

@media (max-width: 520px) {
  .cards, .cards.cols-2, .cards.cols-3, .cards.cols-4, .cards.cols-5 {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 390px) {
  .wrap { padding: 0 12px; }
  .stats { grid-template-columns: 1fr; }
  table { font-size: 13px; }
}


/* ---------- Print ---------- */

@media print {
  :root { --bg: #fff; }
  body { font-size: 10.5pt; }
  .site-nav, .skip-link, .to-top, .anchor { display: none; }
  .site-header { border-bottom: 1pt solid var(--line); text-align: left; }
  .wrap { max-width: none; padding: 0; }
  /* Release the scroll and height clamps so tables print in full. */
  .table-scroll { overflow: visible; max-height: none; }
  thead th, tbody th[scope="row"] { position: static; box-shadow: none; }
  thead th { border-bottom: 2px solid var(--line); }
  tbody th[scope="row"] { border-right: 1px solid var(--line); }
  thead { display: table-header-group; }
  tr, .card, .figure, pre, .callout { break-inside: avoid; }
  h2, h3 { break-after: avoid; }
  a { color: inherit; text-decoration: underline; }
  /* Expose destinations that are lost once the page is on paper. */
  main a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: var(--muted); }
  .site-footer { margin-top: 24px; }
}

/* ==========================================================================
   Motion system
   Three durations and two easings, applied only to state changes and to
   figure reveals. Everything below is opt-in: with reduced motion requested,
   no rule in this file animates.
   ========================================================================== */

:root {
  --dur-fast: 120ms;
  --dur-base: 220ms;
  --dur-slow: 480ms;
  --dur-draw: 1100ms;
  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);
  --ease-out: cubic-bezier(0, 0.7, 0.3, 1);
}

@media (prefers-reduced-motion: no-preference) {
  a.card,
  .site-nav a,
  .anchor,
  .swatch,
  .chip {
    transition: background-color var(--dur-base) var(--ease),
                border-color var(--dur-base) var(--ease),
                color var(--dur-base) var(--ease),
                opacity var(--dur-fast) var(--ease);
  }

  a.card { transition: background-color var(--dur-base) var(--ease),
                       border-color var(--dur-base) var(--ease),
                       transform var(--dur-base) var(--ease); }
  a.card:hover { transform: translateY(-1px); }

  /* A permalinked destination announces itself once, then settles. */
  :target { animation: flag var(--dur-slow) var(--ease-out); }
}

@keyframes flag {
  from { background: #fff6d9; }
  to   { background: transparent; }
}

/* ==========================================================================
   Visualisation primitives
   Charts and diagrams are inline SVG styled from the same tokens as the rest
   of the page, so they inherit the palette, the print rules, and the motion
   preference.
   ========================================================================== */

.frame.ratio-auto {
  aspect-ratio: auto;
  padding: 4px;
}

.frame.ratio-auto svg {
  height: auto;
  object-fit: contain;
}

.viz {
  display: block;
  width: 100%;
  font-family: system-ui, sans-serif;
  overflow: visible;
}

.viz text { fill: var(--fg); font-size: 13px; }
.viz .lbl { fill: var(--muted); font-size: 12px; }
.viz .lbl-sm { fill: var(--muted); font-size: 10.5px; }
.viz .val { font-size: 12px; font-weight: 700; }
.viz .ttl { font-size: 13px; font-weight: 700; }

.viz .axis { stroke: var(--line); stroke-width: 1; fill: none; }
.viz .grid { stroke: var(--line-soft); stroke-width: 1; fill: none; }
.viz .grid-dash { stroke: var(--line-soft); stroke-width: 1; fill: none; stroke-dasharray: 3 3; }

.viz .node { fill: var(--surface); stroke: var(--line); stroke-width: 1; }
.viz .node-alt { fill: var(--surface-alt); stroke: var(--line); stroke-width: 1; }
.viz .flow { stroke: var(--line); stroke-width: 1.5; fill: none; }
.viz .flow-soft { stroke: var(--line-soft); stroke-width: 1.5; fill: none; }

/* Series colours reuse the classification palette, so a bar and a status tag
   for the same axis value always agree. Colour never encodes magnitude. */
.viz .s-static    { fill: var(--accent);    stroke: var(--accent); }
.viz .s-dynamic   { fill: var(--secondary); stroke: var(--secondary); }
.viz .s-gc        { fill: var(--success);   stroke: var(--success); }
.viz .s-manual    { fill: var(--warning);   stroke: var(--warning); }
.viz .s-ownership { fill: var(--info);      stroke: var(--info); }
.viz .s-neutral   { fill: var(--unknown);   stroke: var(--unknown); }
.viz .stroke-only { fill: none; }

/* ---------- Chart motion ----------
   Bars grow, lines draw, points settle. Each figure animates once when it
   first scrolls into view where scroll-driven animation is supported, and
   otherwise on load. Nothing animates on a repeat scroll past. */

@media (prefers-reduced-motion: no-preference) {
  .viz .grow {
    transform-box: fill-box;
    transform-origin: left center;
    animation: grow-x var(--dur-slow) var(--ease-out) both;
  }

  .viz .grow-up {
    transform-box: fill-box;
    transform-origin: bottom center;
    animation: grow-y var(--dur-slow) var(--ease-out) both;
  }

  /* Paths carry pathLength="1000", so one dash value fits every line. */
  .viz .draw {
    stroke-dasharray: 1000;
    stroke-dashoffset: 1000;
    animation: draw var(--dur-draw) var(--ease-out) both;
  }

  .viz .fade { animation: fade var(--dur-slow) var(--ease-out) both; }

  /* Dashes travel along a pipeline edge to show direction of movement. */
  .viz .stream {
    stroke-dasharray: 6 5;
    animation: stream 1.4s linear infinite;
  }

  .viz .spin {
    transform-box: fill-box;
    transform-origin: center;
    animation: spin 14s linear infinite;
  }

  @supports (animation-timeline: view()) {
    .viz .grow, .viz .grow-up, .viz .draw, .viz .fade {
      animation-timeline: view();
      animation-range: entry 10% cover 32%;
    }
  }
}

@keyframes grow-x   { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes grow-y   { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes draw     { to { stroke-dashoffset: 0; } }
@keyframes fade     { from { opacity: 0; } to { opacity: 1; } }
@keyframes stream   { to { stroke-dashoffset: -22; } }
@keyframes spin     { to { transform: rotate(360deg); } }

/* Staggered entry, so a series reads left to right rather than all at once. */
.viz .d1 { animation-delay: 60ms; }
.viz .d2 { animation-delay: 120ms; }
.viz .d3 { animation-delay: 180ms; }
.viz .d4 { animation-delay: 240ms; }
.viz .d5 { animation-delay: 300ms; }
.viz .d6 { animation-delay: 360ms; }
.viz .d7 { animation-delay: 420ms; }
.viz .d8 { animation-delay: 480ms; }

/* ---------- Chart interaction ----------
   Pointer and keyboard focus raise one mark out of the set. The value label
   is present in the markup at all times for assistive technology, and only
   its opacity changes. */

.viz .mark { cursor: default; }
.viz .mark .hit { fill: transparent; }
.viz .mark .peek { opacity: 0; }

@media (prefers-reduced-motion: no-preference) {
  .viz .mark .peek { transition: opacity var(--dur-fast) var(--ease); }
  .viz .mark rect, .viz .mark circle { transition: opacity var(--dur-fast) var(--ease); }
}

.viz .mark:hover .peek,
.viz .mark:focus-visible .peek { opacity: 1; }
.viz .mark:hover rect, .viz .mark:hover circle { opacity: 0.82; }
.viz .mark:focus-visible { outline: none; }
.viz .mark:focus-visible .node,
.viz .mark:focus-visible rect,
.viz .mark:focus-visible circle { stroke: var(--fg); stroke-width: 2; }

@media print {
  .viz .grow, .viz .grow-up, .viz .draw, .viz .fade,
  .viz .stream, .viz .spin { animation: none; }
  .viz .draw { stroke-dashoffset: 0; stroke-dasharray: none; }
  .viz .peek { opacity: 1; }
}

/* ---------- Visual catalogue entries ---------- */

.viz-entry {
  display: grid;
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: 12px;
  border: 1px solid var(--line);
  background: var(--surface);
  padding: 11px 13px;
  margin-bottom: 12px;
}

.viz-entry > div { min-width: 0; }
.viz-entry h3 { margin: 0 0 6px; }
.viz-entry .figure { border: 0; padding: 0; margin: 0; }
.viz-entry .frame { background: var(--surface); }
.viz-entry p { font-size: 13.5px; color: var(--muted); }

.blueprint {
  font-size: 11.5px;
  line-height: 1.35;
  background: var(--surface-alt);
  border: 1px solid var(--line-soft);
  color: var(--muted);
  padding: 8px 10px;
  margin: 0;
}

.use-when {
  font-size: 12.5px;
  border-left: 3px solid var(--line-soft);
  padding-left: 9px;
  margin: 0 0 8px;
}

.use-when strong { color: var(--fg); }

/* Motion specimens: a row of squares that replay the system's easings. */
.motion-demo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}

.motion-demo figure {
  margin: 0;
  border: 1px solid var(--line);
  background: var(--surface);
  padding: 11px 13px;
}

.motion-demo .track {
  height: 26px;
  background: var(--surface-alt);
  border: 1px solid var(--line-soft);
  position: relative;
  overflow: hidden;
}

.motion-demo .puck {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  background: var(--accent);
}

@media (prefers-reduced-motion: no-preference) {
  .motion-demo .puck { animation: slide 2.6s infinite; }
  .motion-demo .e-linear .puck { animation-timing-function: linear; }
  .motion-demo .e-base   .puck { animation-timing-function: var(--ease); }
  .motion-demo .e-out    .puck { animation-timing-function: var(--ease-out); }
}

@keyframes slide {
  0%, 12%   { transform: translateX(0); }
  50%, 62%  { transform: translateX(calc(100cqw - 24px)); }
  100%      { transform: translateX(0); }
}

.motion-demo .track { container-type: inline-size; }
.motion-demo figcaption { font-size: 12px; color: var(--muted); margin-top: 6px; }

@media (max-width: 900px) {
  .viz-entry { grid-template-columns: 1fr; }
}
