/* Every literal colour and font is a token, so changes land in one place. */
:root {
  --font-body: ui-serif, Georgia, "Times New Roman", serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
}
:root { color-scheme: light dark; --fg:#111; --dim:#555; --bg:#fdfdfc; --line:#e3e3e0; --code:#f4f4f1; --accent:#a4432b; }
@media (prefers-color-scheme: dark) {
  :root { --fg:#e8e8e6; --dim:#a0a09b; --bg:#16161a; --line:#2c2c31; --code:#1e1e23; --accent:#e08a68; }
}
* { box-sizing: border-box; }
body { margin:0; background:var(--bg); color:var(--fg);
       font:16px/1.65 var(--font-body); }
main { max-width:46rem; margin:0 auto; padding:3.5rem 1.25rem 5rem; }
h1 { font-size:2rem; margin:0 0 .25rem; letter-spacing:-.02em; }
main > p:first-of-type { color:var(--dim); margin:0 0 2.5rem; font-size:1.05rem; }
h2 { font-size:1.15rem; margin:2.5rem 0 .6rem; letter-spacing:-.01em; }
p, li { margin:.6rem 0; }
code, pre { font-family:var(--font-mono); font-size:.875rem; }
pre { background:var(--code); border:1px solid var(--line); border-radius:6px;
      padding:.85rem 1rem; overflow-x:auto; line-height:1.5; }
code:not(pre code) { background:var(--code); padding:.1rem .3rem; border-radius:3px; }
.hljs { color:var(--fg); }
.hljs-comment, .hljs-quote { color:var(--dim); font-style:italic; }
.hljs-string, .hljs-number, .hljs-literal, .hljs-addition { color:var(--accent); }
.hljs-keyword, .hljs-built_in, .hljs-selector-tag { color:var(--accent); font-weight:600; }
.hljs-variable, .hljs-attr, .hljs-name, .hljs-title { color:var(--fg); font-weight:600; }
a { color:var(--accent); }
ul { padding-left:1.1rem; }
blockquote { color:var(--dim); margin:.6rem 0; font-size:.92rem; }
blockquote p { margin:0; }
hr { border:0; border-top:1px solid var(--line); margin:2.5rem 0; }
main > p:last-child { color:var(--dim); font-size:.9rem; }

﻿.sortable thead th:not(.no-sort){cursor:pointer}.sortable thead th:not(.no-sort)::after,.sortable thead th:not(.no-sort)::before{transition:color .1s ease-in-out;font-size:1.2em;color:rgba(0,0,0,0)}.sortable thead th:not(.no-sort)::after{margin-left:3px;content:"▸"}.sortable thead th:not(.no-sort):hover::after{color:inherit}.sortable thead th:not(.no-sort)[aria-sort=descending]::after{color:inherit;content:"▾"}.sortable thead th:not(.no-sort)[aria-sort=ascending]::after{color:inherit;content:"▴"}.sortable thead th:not(.no-sort).indicator-left::after{content:""}.sortable thead th:not(.no-sort).indicator-left::before{margin-right:3px;content:"▸"}.sortable thead th:not(.no-sort).indicator-left:hover::before{color:inherit}.sortable thead th:not(.no-sort).indicator-left[aria-sort=descending]::before{color:inherit;content:"▾"}.sortable thead th:not(.no-sort).indicator-left[aria-sort=ascending]::before{color:inherit;content:"▴"}.sortable{--stripe-bg: #e4e4e4;--stripe-color: #000;--stripe-bg-odd: #fff;--stripe-color-odd: #111;--th-bg: #808080;--th-color: #fff;border-spacing:0}.sortable.sticky thead th{position:sticky;top:0;z-index:1}.sortable tbody tr{background-color:var(--stripe-bg);color:var(--stripe-color)}.sortable tbody tr:nth-child(odd){background-color:var(--stripe-bg-odd);color:var(--stripe-color-odd)}.sortable thead th{background:var(--th-bg);color:var(--th-color);font-weight:normal;text-align:left;text-transform:capitalize;vertical-align:baseline;white-space:nowrap}.sortable thead td:first-child,.sortable thead th:first-child{border-top-left-radius:4px}.sortable thead td:last-child,.sortable thead th:last-child{border-top-right-radius:4px}.sortable td,.sortable th{padding:10px}
/* The viewer, on top of the site's own styles. Tokens only: every colour here
   is one site.css already defined. */
:root {
  --frontend:#7fb2e5; --codegen:#b39ddb; --link:#86d0a4; --other:#f2b880;
  --active:#3f9d63; --waiting:#d4633f; --inactive:#5566c4; --on-bar:#17202a;
  --script:#cc79a7; --hatch:#00000047;
  /* Five families rather than twenty-six unrelated hues, because the phases
     are not unrelated: a compile reads the source, checks it, makes machine
     code, links, and spends some of the clock on the compiler process itself.
     Hue says which of those a band belongs to -- which is the segment the
     census publishes -- and lightness says where in it, so a unit that is
     mostly checking looks green from across the room whether it was borrowck
     or type_check that did the checking, and a unit that is mostly back end
     looks warm whether it was the optimiser or the assembler.

     The warm family is six long because the back end is six phases. It used
     to be three, because the back end used to be one phase called `codegen`
     with nothing inside it. The green family is nine long for the same
     reason: trait solving, const evaluation and layout used to be nothing at
     all, which is to say they used to be `unattributed`.

     Anchored on Okabe-Ito, eight colours chosen to stay apart under every
     common colour-vision deficiency. Twenty-six categories is well past what
     any qualitative palette manages -- Tol's largest is nine, and his
     instruction is not to interpolate -- which is the argument for families
     Within a family the ramp is monotonic in luminance, and checked to be:
     `mir_build` and `borrowck` were 0.471 and 0.464, which is two names for
     one colour, and the five blues sat inside 0.03 of each other. */
  /* frontend: reading the source */
  --phase-0:#00354f; --phase-1:#00527d; --phase-2:#0a68b0;
  --phase-3:#2e7fdd; --phase-4:#6a9ce8;
  /* frontend: checking it */
  --phase-5:#00734f; --phase-6:#00875c; --phase-7:#00996f;
  --phase-8:#08ab65; --phase-9:#13bb57; --phase-10:#1fc949;
  --phase-11:#31d23f; --phase-12:#63d95b; --phase-13:#93e487;
  /* backend: making machine code */
  --phase-14:#7d3200; --phase-15:#994400; --phase-16:#b3600a;
  --phase-17:#c88a13; --phase-18:#d8b02e; --phase-19:#e3cb4a;
  /* link, then the compiler process itself */
  --phase-20:#6a4fbb;
  --phase-21:#a2408f; --phase-22:#bb5aa4; --phase-23:#cf7bb8;
  /* the two answers that are not compile work */
  --phase-24:#4c4c4c; --phase-25:#8f8f8f;
}
/* The viewer takes the whole window. The site's 46rem is a measure for
   reading prose; this is a page of tables and charts, and every rem the
   browser is given is a column or a second of build that fits on screen
   without scrolling. Top padding drops too -- the trail is the header. */
main { max-width:none; padding:1.25rem 1.25rem 4rem; }
h1 { margin-bottom:.5rem; }
.key { margin:.4rem 0; overflow-wrap:anywhere; }
.key code { background:none; padding:0; font-size:.8rem; color:var(--dim); }
p.dim, .dim { color:var(--dim); }
h2 .dim { font-weight:400; font-size:.85rem; }
section { margin:2.5rem 0; }
section p.dim { font-size:.85rem; margin:.2rem 0 .8rem; }
.null { color:var(--dim); }
.scroll { overflow-x:auto; border:1px solid var(--line); border-radius:6px; }
table { border-collapse:collapse; font:.8rem/1.5 var(--font-mono); min-width:100%; }
th, td { padding:.3rem .6rem; text-align:left; white-space:nowrap;
         border-bottom:1px solid var(--line); }
th { position:sticky; top:0; background:var(--code); font-weight:600; }
tbody tr:last-child td { border-bottom:0; }
tbody tr:hover td { background:var(--code); }
dl { display:grid; grid-template-columns:minmax(9rem,14rem) 1fr; gap:0;
     margin:0; border:1px solid var(--line); border-radius:6px; overflow:hidden; }
dt, dd { margin:0; padding:.35rem .6rem; font:.8rem/1.6 var(--font-mono);
         border-bottom:1px solid var(--line); overflow-wrap:anywhere; }
dt { background:var(--code); color:var(--dim); }
dl > :nth-last-child(-n+2) { border-bottom:0; }

/* Walking the key space, and finding your way around one observation. */
.trail { font:.8rem/1.6 var(--font-mono); color:var(--dim); margin:0 0 1.2rem; }
.trail .sep { opacity:.5; padding:0 .15rem; }
.trail span:not(.sep) { color:var(--fg); }
.entries { list-style:none; padding:0; margin:.4rem 0; }
.entries li { margin:0; border-bottom:1px solid var(--line); padding:.4rem .1rem; }
.entries li:last-child { border-bottom:0; }
.entries a { font-family:var(--font-mono); font-size:.85rem; }
.entries .dim { font-size:.78rem; margin-left:.4rem; }
.glance { grid-template-columns:minmax(6rem,8rem) 1fr; margin:1.5rem 0; }
.glance dt { text-transform:lowercase; }
.contents { margin:2rem 0 0; }
.contents h2 { font-size:1rem; margin:0 0 .5rem; }
.contents ul { list-style:none; padding:0; margin:0; display:flex; flex-wrap:wrap; gap:.35rem .9rem; }
.contents li { margin:0; font:.82rem/1.6 var(--font-mono); }
.contents li.empty { color:var(--dim); }
.contents .dim { font-family:var(--font-body); font-size:.75rem; }
h2 .top { float:right; font:.75rem/2.2 var(--font-body); opacity:.6; }
h2 .top:hover { opacity:1; }

/* The build, drawn. Cargo's three views, on our own palette.
   Bars are flat colour with no gradient: a gradient on a 3-pixel-tall rect is
   noise, and these get 3 pixels often. */
.chart { margin: 0 0 0.6rem; }
.chart svg { display: block; width: 100%; height: auto; min-width: 1000px; }
/* The lane chart is wider than the plots above it and scrolls. At 1000 across
   a fifteen-second build a half-second unit is 31 pixels, which is four
   characters of a name, so the labels it exists to carry would all be
   dropped. */
.chart.wide svg { min-width: 2600px; }
.rule { stroke: var(--line); stroke-width: 0.5; }
.tick { font-size: 12px; fill: var(--dim); text-anchor: middle; }
.tick.left, .row-number { text-anchor: end; }
/* A share reads after its bar and in the same direction, so it is anchored to
   where the bar ends rather than centred on it -- centred put it on top of the
   bar's own end. A class rather than an attribute, because the rule above is
   CSS and would win over one. */
.tick.after { text-anchor: start; }
.row-number { font-size: 12px; fill: var(--dim); }
.bar-label { font-size: 12px; fill: var(--fg); dominant-baseline: alphabetic; }
.bar-label.inside { fill: var(--on-bar); }

.seg.frontend, .swatch.frontend { fill: var(--frontend); background: var(--frontend); }
.seg.codegen,  .swatch.codegen  { fill: var(--codegen); background: var(--codegen); }
.seg.link,     .swatch.link     { fill: var(--link); background: var(--link); }
.seg.other,    .swatch.other    { fill: var(--other); background: var(--other); }
/* A build script running is not the compiler, and should not wear the colour
   of a unit that simply was not sampled. Hatched, because it is time the
   build spent without rustc being the thing spending it. */
.seg.script, .swatch.script { fill: var(--script); background: var(--script); }
.swatch.script { background-image: repeating-linear-gradient(45deg,
  transparent 0 2px, var(--hatch) 2px 4px); }

.cpu { fill: var(--other); opacity: 0.32; stroke: none; }
.cores { stroke: var(--dim); stroke-width: 1; stroke-dasharray: 4 3; }
.cores-label { text-anchor: start; }
.active, .waiting, .inactive { fill: none; stroke-width: 1.4; }
.active   { stroke: var(--active); }
.waiting  { stroke: var(--waiting); }
.inactive { stroke: var(--inactive); }
.swatch.active { background: var(--active); }
.swatch.waiting { background: var(--waiting); }
.swatch.inactive { background: var(--inactive); }
.swatch.cpu { background: var(--other); }

/* One colour per phase in the pipeline, so a phase is the same colour on a
   unit's bar, on the build's bar, and in the legend beside either. The
   list is twenty-six long; a phase beyond it wraps rather than running out. */
.p0 { fill: var(--phase-0); background: var(--phase-0); }
.p1 { fill: var(--phase-1); background: var(--phase-1); }
.p2 { fill: var(--phase-2); background: var(--phase-2); }
.p3 { fill: var(--phase-3); background: var(--phase-3); }
.p4 { fill: var(--phase-4); background: var(--phase-4); }
.p5 { fill: var(--phase-5); background: var(--phase-5); }
.p6 { fill: var(--phase-6); background: var(--phase-6); }
.p7 { fill: var(--phase-7); background: var(--phase-7); }
.p8 { fill: var(--phase-8); background: var(--phase-8); }
.p9 { fill: var(--phase-9); background: var(--phase-9); }
.p10 { fill: var(--phase-10); background: var(--phase-10); }
.p11 { fill: var(--phase-11); background: var(--phase-11); }
.p12 { fill: var(--phase-12); background: var(--phase-12); }
.p13 { fill: var(--phase-13); background: var(--phase-13); }
.p14 { fill: var(--phase-14); background: var(--phase-14); }
.p15 { fill: var(--phase-15); background: var(--phase-15); }
.p16 { fill: var(--phase-16); background: var(--phase-16); }
.p17 { fill: var(--phase-17); background: var(--phase-17); }
.p18 { fill: var(--phase-18); background: var(--phase-18); }
.p19 { fill: var(--phase-19); background: var(--phase-19); }
.p20 { fill: var(--phase-20); background: var(--phase-20); }
.p21 { fill: var(--phase-21); background: var(--phase-21); }
.p22 { fill: var(--phase-22); background: var(--phase-22); }
.p23 { fill: var(--phase-23); background: var(--phase-23); }
.p24 { fill: var(--phase-24); background: var(--phase-24); }
.p25 { fill: var(--phase-25); background: var(--phase-25); }

.legend { display: flex; flex-wrap: wrap; gap: 0.2rem 1rem; list-style: none;
          padding: 0; margin: 0 0 1.6rem; font-size: 0.82rem; color: var(--dim); }
.legend .swatch { display: inline-block; width: 0.65rem; height: 0.65rem;
                  border-radius: 2px; margin-right: 0.35rem; vertical-align: baseline; }
table.units .num { text-align: right; white-space: nowrap; }
table.units .features { font-size: 0.82rem; color: var(--dim); }

/* One column. The rail was a good idea while the page was mostly tables --
   configuration on the left, measurements on the right, the first still in
   view while you read the second. It stopped being one when the charts
   arrived: they want the whole window, and a sticky column holding a dozen
   session fields was taking a third of it to hold something you read once.
   The markup is unchanged; it simply stacks. */
.observation { display: block; }
.rail { position: static; max-height: none; overflow: visible; padding: 0;
        border-right: 0; margin: 0 0 1.5rem; }
.rail h1 { font-size: 1.6rem; margin: 0 0 .3rem; }
.rail section { margin: 1.5rem 0; }
.rail h2 { font-size: 1rem; }
.rail h2 .top { display: none; }
.rail dl { grid-template-columns: minmax(9rem, 16rem) 1fr; max-width: 64rem; }
.rail dt, .rail dd { padding: .3rem .55rem; font-size: .78rem; line-height: 1.5; }
.rail table { font-size: .78rem; }
.rail th, .rail td { padding: .25rem .5rem; }
.rail .contents li { display: inline-flex; gap: .4rem; border-bottom: 0;
                     padding: 0 .9rem 0 0; font-size: .8rem; }
.rail .contents ul { display: flex; flex-wrap: wrap; }
.rail .glance { max-width: 48rem; }
.body { min-width: 0; }
.body > section:first-child { margin-top: .2rem; }
.small { font-size: .78rem; line-height: 1.5; }
.actions { margin: .9rem 0 .6rem; }
.actions button { font: inherit; font-size: .8rem; padding: .35rem .7rem; cursor: pointer;
                  color: var(--fg); background: var(--code); border: 1px solid var(--line);
                  border-radius: 5px; }
.actions button:hover { border-color: var(--accent); color: var(--accent); }
.contents ul { display: block; }

/* Denser tables: this is a page of measurements, and the default padding was
   spending a third of the screen on whitespace between them. */
table { font-size:.75rem; }
th, td { padding:.2rem .5rem; }
section { margin:1.8rem 0; }
section p.dim { margin:.15rem 0 .5rem; }

/* Sorting affordance, on the library's own hooks. */
table.sortable th { cursor:pointer; user-select:none; }
table.sortable th::after { content:"↕"; opacity:.25; margin-left:.35rem; font-size:.7em; }
table.sortable th[aria-sort="ascending"]::after { content:"↑"; opacity:.9; }
table.sortable th[aria-sort="descending"]::after { content:"↓"; opacity:.9; }

@media (max-width:82rem) {
  .observation { grid-template-columns:1fr; gap:0; }
  .rail { position:static; max-height:none; border-right:0;
          border-bottom:1px solid var(--line); margin-bottom:1.5rem; }
}

/* One row per unit, and everything about it. Pills rather than a comma list:
   `clone-impls, default, derive, extra-traits, full` is a sentence you have to
   read; five pills is a shape you can count. */
/* Pills wrap, so the line box is what decides how tall a row of them is:
   tighter leading between the lines, more room inside each pill. Packed
   horizontally and airy vertically was exactly backwards. */
.pills { display:flex; flex-wrap:wrap; gap:.1rem .3rem; list-style:none; padding:0; margin:0;
         line-height:1.15; }
/* The site gives every `li` a .6rem vertical margin, which on a pill is 19px
   of nothing per row -- nearly doubling the height of a table of them. */
.pills li { margin:0; font-size:.75rem; line-height:1.5; padding:0 .4rem; border-radius:3px;
            background:var(--code); border:1px solid var(--line); color:var(--dim);
            white-space:nowrap; }
td .pills { flex-wrap:nowrap; }
.pills li.more { border-style:dashed; cursor:help; }
.unit { white-space:nowrap; }
/* The mix is the last column, so it takes whatever width is left rather than
   a fixed one: `width:100%` on the final cell of a table that is already
   `min-width:100%` hands it the slack. */
.mix-cell { min-width:14rem; width:100%; padding-right:.8rem; }
svg.mix { display:block; width:100%; height:1rem; border-radius:3px; overflow:hidden; }
/* Scaled to each unit instead. The switch is a checkbox and the share is a
   property on the bar, so the browser reflows two hundred rows without any
   script running and without redrawing a single band. */
#units:has(.mix-scale:checked) svg.mix { width:var(--of-longest); }
.scale { display:block; font:.8rem/1.6 var(--font-body); margin:.2rem 0 .8rem;
         cursor:pointer; }
.scale input { margin-right:.4rem; vertical-align:-1px; }
.target.macro, .target.unknown { color:var(--dim); }
table.units td { vertical-align:middle; padding:.18rem .4rem; }
table.units th { padding:.2rem .4rem; }
table.units td:has(.pills) { vertical-align:middle; }
table.units .unit { padding-right:.5rem; }
table.units .num { text-align:right; white-space:nowrap; }

/* The stored tables are still here, folded away. They are the object; the
   views above are what the object means, and one of those is what you came
   for roughly always. */
details.raw { margin:2rem 0 0; border-top:1px solid var(--line); padding-top:.8rem; }
details.raw > summary { cursor:pointer; font-size:.9rem; padding:.2rem 0; }
details.raw > summary .dim { font-weight:400; margin-left:.4rem; font-size:.78rem; }
details.raw[open] > summary { margin-bottom:.6rem; }

/* The staged keyspace as a tree. Partitions are `<details>` so this needs no
   script, and they are open because with staged objects deleted on merge the
   whole thing is usually a dozen rows. */
ul.tree { list-style:none; margin:0; padding:0 0 0 1rem; }
.observation ~ ul.tree, main > ul.tree { padding-left:0; }
ul.tree ul.tree { border-left:1px solid var(--line); margin-left:.3rem; }
ul.tree li { margin:0; }
ul.tree summary { cursor:pointer; padding:.2rem 0; font:.82rem/1.5 var(--font-mono);
                  list-style-position:outside; }
ul.tree summary::marker { color:var(--dim); }
ul.tree .part { color:var(--fg); }
ul.tree summary .dim, ul.tree .leaf .dim { font-family:var(--font-body); font-size:.75rem;
                                           margin-left:.5rem; }
ul.tree .leaf { padding:.2rem 0 .2rem 1.15rem; font:.82rem/1.5 var(--font-mono);
                border-bottom:1px solid var(--line); }
ul.tree .leaf:last-child { border-bottom:0; }

/* The explorer. Its own page: the query is a tool, so it gets the top of the
   window and the answer gets the rest. */
body.explore { display:flex; flex-direction:column; min-height:100vh; padding:1rem 1.25rem; gap:.7rem; }
body.explore header h1 { font-size:1.4rem; margin:0 0 .2rem; }
body.explore header p { max-width:60rem; margin:0; font-size:.85rem; }
.query { display:grid; grid-template-columns:minmax(13rem,17rem) minmax(0,1fr); gap:1rem; }
.tables { list-style:none; margin:0; padding:0; max-height:11rem; overflow-y:auto; }
.tables li { display:flex; gap:.5rem; align-items:baseline; padding:.1rem 0; }
.tables button { font:.78rem/1.5 var(--font-mono); color:var(--accent); background:none;
                 border:0; padding:0; cursor:pointer; text-align:left; }
.tables button:hover { text-decoration:underline; }
.tables span { font-size:.75rem; color:var(--dim); }
.editor { display:flex; flex-direction:column; gap:.4rem; }
#sql { font:.8rem/1.5 var(--font-mono); color:var(--fg); background:var(--code);
       border:1px solid var(--line); border-radius:6px; padding:.6rem .7rem;
       min-height:8.5rem; resize:vertical; }
.bar { display:flex; align-items:center; gap:.8rem; }
#run { font:inherit; font-size:.8rem; padding:.3rem .9rem; cursor:pointer; color:var(--fg);
       background:var(--code); border:1px solid var(--line); border-radius:5px; }
#run:hover { border-color:var(--accent); color:var(--accent); }
#status { font-size:.78rem; }
#status.bad { color:var(--waiting); }
perspective-viewer { flex:1; min-height:32rem; border:1px solid var(--line); border-radius:6px; }

/* Something to look at while 40 MB of engine arrives. */
.answer { position:relative; flex:1; display:flex; min-height:32rem; }
.answer perspective-viewer { flex:1; }
#boot { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center;
        justify-content:center; gap:.7rem; background:var(--bg); border-radius:6px; text-align:center; }
#boot[hidden] { display:none; }
#boot-text { margin:0; font:.95rem/1.4 var(--font-body); }
#boot .small { max-width:24rem; margin:0; }
.track { width:min(22rem,70%); height:4px; background:var(--code); border:1px solid var(--line);
         border-radius:3px; overflow:hidden; }
#boot-bar { height:100%; width:0; background:var(--accent); transition:width .2s linear; }
#boot-bar.indeterminate { width:35%; animation:sweep 1.1s ease-in-out infinite; }
@keyframes sweep { 0% { margin-left:-35%; } 100% { margin-left:100%; } }
@media (prefers-reduced-motion:reduce) { #boot-bar.indeterminate { animation:none; width:100%; opacity:.4; } }

/* The conclusion, before the plots that support it. */
.verdict { margin:.2rem 0 .9rem; font-size:1rem; line-height:1.5; max-width:56rem; }
.verdict strong { font-weight:600; }
.verdict.small { font-size:.85rem; margin:.2rem 0 .7rem; }
/* Busy cores as an area: the gap between it and the ceiling is the machine
   that went unused, which is the whole reason to look at this plot. */
.busy { fill:var(--active); opacity:.22; stroke:none; }
/* One outline per unit, around the unit rather than around each band inside
   it: the bands are the phase mix, and stroking every one of them turns a bar
   into a barcode. `crispEdges` because a half-pixel outline on a 3-pixel bar
   is a smear. */
.lane .stripe { fill: var(--code); }
.lane .edge { fill:none; stroke:var(--fg); stroke-width:.7; stroke-opacity:.5;
              shape-rendering:crispEdges; }
/* The critical path is named in the table and in the verdict; a box around
   nine bars in a chart of a hundred and sixty-seven was more noise than
   signal. */
.lane .critical-unit .edge { stroke:var(--fg); stroke-width:1.1; stroke-opacity:.85; }
.lane-label { font-size:12px; fill:var(--dim); }
/* A unit's own name leads its block of threads, so it is read first; the
   thread names beside each row are a size down, because which codegen unit a
   row is matters less than what colour it is. */
.unit-label { fill:var(--ink); }
.thread-label { font-size:10px; }
.swatch.on-path { background:none; border:2px solid var(--waiting); }
.swatch.phases-swatch { background:linear-gradient(90deg,
  var(--phase-7) 0 40%, var(--phase-16) 40% 75%, var(--phase-18) 75% 100%); }
.swatch.on-path { background:var(--waiting); }
.critical-unit .seg { stroke:var(--waiting); stroke-width:1.2; }
.critical-unit .bar-label { font-weight:600; }

/* Questions before an empty box. Somebody arriving does not know what to ask;
   these are the asking, and the SQL below is what they turn into. */
.starts { display:flex; flex-wrap:wrap; align-items:center; gap:.4rem .55rem; }
.starts .label { margin:0 .1rem 0 0; font-size:.78rem; color:var(--dim); }
.starts .label:not(:first-child) { margin-left:.8rem; }
.chips { display:contents; list-style:none; margin:0; padding:0; }
.chips li { margin:0; }
.chips button { font:inherit; font-size:.8rem; padding:.25rem .65rem; cursor:pointer;
                color:var(--fg); background:var(--code); border:1px solid var(--line);
                border-radius:999px; }
.chips button:hover { border-color:var(--accent); color:var(--accent); }
.chips button.on { border-color:var(--accent); color:var(--bg); background:var(--accent); }
.chips.tables button { font-family:var(--font-mono); font-size:.78rem; }
.query { grid-template-columns:minmax(0,1fr); }

/* A build you have not sent. Same charts, no request. */
.paste { margin-top:2.5rem; border-top:1px solid var(--line); padding-top:1.2rem; }
.paste h2 { font-size:1.05rem; margin:0 0 .3rem; }
.paste > p.dim { max-width:52rem; }
.paste textarea { display:block; width:100%; max-width:60rem; font:.8rem/1.5 var(--font-mono);
                  color:var(--fg); background:var(--code); border:1px solid var(--line);
                  border-radius:6px; padding:.6rem .7rem; resize:vertical; }
.paste .actions { display:flex; align-items:center; gap:.7rem; }
.paste button.quiet { background:none; }
.paste-status { font-size:.78rem; }
.paste-status.bad { color:var(--waiting); }
#drawn:not(:empty) { margin-top:1.5rem; }

/* Once a build has been read, the box that read it steps aside. */
.paste.done h1 { font-size:1.1rem; }
.paste.done > p.dim, .paste.done textarea { display:none; }
.paste.done { border-bottom:1px solid var(--line); padding-bottom:.6rem; margin-bottom:1.2rem; }
.elsewhere { margin:2rem 0 0; padding-top:1rem; border-top:1px solid var(--line);
             font-size:.9rem; max-width:52rem; }

/* The release graph. Edges under nodes, and a metadata release dashed: it
   only needed the interface, which is why it could start earlier. */
.wire { fill: none; stroke: var(--dim); stroke-width: 1; stroke-opacity: .45; }
.wire.metadata { stroke-dasharray: 3 3; stroke-opacity: .35; }
.dag .critical-unit .wire { stroke-opacity: 1; }

/* Absence, drawn as absence. A unit nothing was sampled from is hatched
   rather than filled: the flat amber it used to wear was nearer to codegen
   than two adjacent phases are to each other. */
.hatch-ground { fill: var(--bg); }
.hatch-line { stroke: var(--dim); stroke-width: 2.4; stroke-opacity: .5; }
.swatch.nothing { background: var(--bg); border: 1px solid var(--line);
  background-image: repeating-linear-gradient(45deg,
    transparent 0 2px, var(--hatch) 2px 4px); }

/* The target column, as shapes. Squares are compiles, the triangle is a run,
   and the run wears the colour it wears in the lane chart so the two charts
   agree about which rows are not the compiler. */
.target-cell { text-align: center; }
.target { vertical-align: -2px; color: var(--dim); }
.target.run { color: var(--script); }

/* The output cell holds a count and a size, and each gets its own width so
   the separator stops wandering between rows. */
.count { display:inline-block; width:2ch; text-align:right; }
.size { display:inline-block; width:6ch; text-align:right; }

/* The headline and the one action the page offers, on one line. */
.masthead { display:flex; align-items:flex-start; justify-content:space-between;
            gap:1.5rem; flex-wrap:wrap; margin:0 0 1rem; }
.masthead h1 { margin:0 0 .2rem; }
.masthead p { margin:0; }
.masthead .actions { margin:0; flex:none; }
.units a { color:inherit; text-decoration:none;
           border-bottom:1px solid var(--line); }
.units a:hover { color:var(--accent); border-bottom-color:var(--accent); }
