/* Palette and typography shared with tile-ai/TileFoundry.github.io, plus the
 * rules the benchmark data tables need.
 *
 * Single light scheme: a paper carrying the faintest violet, a dot texture,
 * one iris-violet accent for structure, teal reserved for asides. Violet and
 * teal are both dark and low-chroma — a saturated pair at this size reads as
 * candy rather than as an editorial page.
 *
 * The ground takes its cast from the accent rather than from cream: a warm
 * yellow paper under two cool hues leaves the page arguing with itself, and
 * the yellow is what the eye reads first on a wall of white space. Ink and the
 * muted grey follow it, so nothing on the sheet is warm.
 */

@import url("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,500;12..96,700;12..96,800&family=Hanken+Grotesk:wght@400;500;600;700;800&family=Space+Mono:wght@400;700&display=swap");

:root {
  --tf-paper: #f5f3f8;
  --tf-paper-2: #e9e5f1;
  --tf-ink: #1a1720;
  --tf-muted: #6a6478;
  --tf-violet: #5a3e85;
  --tf-violet-dark: #432c66;
  --tf-violet-light: #7c5cae;
  --tf-teal: #16706b;
  --tf-green: #23724a;
  --tf-rose: #a43f46;
  /* Rules and the dot texture carry a trace of the accent rather than plain
   * ink, so the paper reads as one ground with the headings instead of two.
   */
  /* The rule that marks a group: methods, examples, asides. Lighter than the
   * teal itself, which at full strength reads as a second heading colour. */
  --tf-rule: color-mix(in srgb, #16706b, transparent 40%);
  --tf-line: rgba(51, 35, 79, 0.18);
  --tf-line-soft: rgba(51, 35, 79, 0.08);
  /* Latin faces come first so technical terms inside Chinese prose keep the
   * site's voice; Han glyphs fall through to the platform UI face. No CJK
   * webfont: a Simplified Chinese subset costs megabytes, which is not worth
   * paying on every page for a partly translated site.
   */
  --tf-cjk: "PingFang SC", "HarmonyOS Sans SC", "Microsoft YaHei",
    "Noto Sans CJK SC", "Source Han Sans SC", sans-serif;
  --tf-display: "Bricolage Grotesque", var(--tf-cjk);
  --tf-body: "Hanken Grotesk", var(--tf-cjk);
  --tf-mono: "Space Mono", ui-monospace, monospace;
}

[data-md-color-scheme="default"] {
  --md-default-bg-color: var(--tf-paper);
  --md-default-fg-color: var(--tf-ink);
  --md-default-fg-color--light: var(--tf-muted);
  --md-default-fg-color--lighter: var(--tf-line);
  --md-default-fg-color--lightest: var(--tf-line-soft);
  --md-primary-fg-color: var(--tf-violet);
  --md-primary-fg-color--light: var(--tf-violet-light);
  --md-primary-fg-color--dark: var(--tf-violet-dark);
  --md-accent-fg-color: var(--tf-teal);
  --md-typeset-a-color: var(--tf-teal);
  /* Translucent, so a code block is an inset in the sheet the wash carries on
   * through rather than a slab dropped on top of it. The old flat fill was the
   * one opaque mass on the page and read as dead weight.
   */
  --md-code-bg-color: color-mix(in srgb, var(--tf-paper-2), transparent 45%);
  --md-code-fg-color: var(--tf-ink);
  --md-footer-bg-color: #241a33;
  --md-footer-bg-color--dark: #1b1327;
  /* Syntax highlighting drawn from the same two hues rather than Material's
   * default blue and red, which are the only warm-cool pair left on the page
   * once the accent is violet. Identifiers stay plain ink: in these snippets
   * they are the content, and colouring them too leaves nothing standing out.
   */
  --md-code-hl-keyword-color: var(--tf-violet);
  --md-code-hl-function-color: var(--tf-violet-light);
  --md-code-hl-constant-color: var(--tf-violet-light);
  --md-code-hl-string-color: var(--tf-teal);
  --md-code-hl-special-color: var(--tf-teal);
  --md-code-hl-variable-color: var(--tf-teal);
  --md-code-hl-number-color: var(--tf-rose);
  --md-code-hl-comment-color: var(--tf-muted);
  --md-code-hl-operator-color: var(--tf-muted);
  --md-code-hl-punctuation-color: var(--tf-muted);
  --md-code-hl-name-color: var(--md-code-fg-color);
}

/* The ground: paper, a dot texture, and a wash of each accent thrown in from
 * opposite corners. The wash is what puts the two hues on a page that is
 * otherwise a wall of tables — but it stays under 10% and is pushed to the
 * edges, so the column of text and numbers still sits on clean paper. Fixed
 * attachment keeps it reading as light on the sheet rather than as a graphic
 * scrolling past.
 *
 * Applied to html alone and propagated to the canvas: the containers used to
 * repeat it, which multiplied the dot alpha four times over.
 */
html {
  background-color: var(--md-default-bg-color);
  background-image: radial-gradient(var(--tf-line-soft) 1px, transparent 1.5px),
    radial-gradient(
      130% 95% at 4% -8%,
      color-mix(in srgb, var(--tf-violet), transparent 94%),
      transparent 58%
    ),
    radial-gradient(
      110% 85% at 100% 104%,
      color-mix(in srgb, var(--tf-teal), transparent 93%),
      transparent 55%
    );
  background-size: 26px 26px, auto, auto;
  background-attachment: scroll, fixed, fixed;
}

body,
.md-container,
.md-main {
  background: transparent;
}

body,
.md-typeset,
.md-nav,
.md-search__input {
  font-family: var(--tf-body);
}

/* Material's sheet is 61rem wide, sized for a page with one nav column. This
 * site has two — nav on the left, the page's own headings on the right — which
 * leaves the prose about 34rem, where every table wraps. The sheet widens to
 * hold a 46rem prose column; the reading measure is then set by the content
 * column below, not by the window.
 */
.md-grid {
  max-width: 76rem;
}

/* An op reference page has no left nav of its own to balance against, and its
 * signatures are the widest lines on the site.
 */
@media screen and (min-width: 100em) {
  .md-grid {
    max-width: 82rem;
  }
}

/* Header sits on the paper rather than in the accent colour, and lets the wash
 * behind it through: an opaque band across the top would cut the ground in two
 * at exactly the place the violet is strongest.
 */
.md-header,
.md-tabs {
  color: var(--tf-ink);
  background: color-mix(in srgb, var(--tf-paper), transparent 22%);
  backdrop-filter: blur(10px);
  box-shadow: none;
}

/* The rule under the header is the one place the two accents meet across the
 * full width — a hairline, so it registers as a tint rather than a stripe.
 */
.md-header {
  border-bottom: 1px solid transparent;
  border-image: linear-gradient(
      90deg,
      var(--tf-violet) 0%,
      var(--tf-violet-light) 32%,
      var(--tf-teal) 72%,
      var(--tf-line-soft) 100%
    )
    1;
}

.md-header__topic,
.md-header__button,
.md-header__button:hover,
.md-source,
.md-source:hover {
  color: var(--tf-ink);
}

.md-header__title,
.md-header__topic {
  font-family: var(--tf-display);
  font-size: 1rem;
  font-weight: 800;
}

/* The logo is a wordmark: it already reads TileOPs, so the site name beside it
 * says the same thing twice. Hidden rather than removed, because the second
 * topic in the same slot — the page's own title, which takes over once the h1
 * has scrolled away — still needs the space. The logo link carries the site
 * name as its label, so nothing is lost to a screen reader.
 */
.md-header__topic:first-child {
  visibility: hidden;
}

.md-source__repository {
  font-family: var(--tf-mono);
  font-size: 0.68rem;
}

/* Search: a pill drawn on the header's own paper. Material's default is a
 * filled grey field, which is the darkest thing in the header and pulls the
 * eye there before the page title.
 */
.md-search__form {
  border-radius: 999px;
  background: color-mix(in srgb, var(--tf-paper-2), transparent 35%);
  box-shadow: inset 0 0 0 1px var(--tf-line-soft);
}

.md-search__form:hover,
[data-md-toggle="search"]:checked ~ .md-header .md-search__form {
  background: color-mix(in srgb, var(--tf-paper-2), transparent 15%);
  box-shadow: inset 0 0 0 1px
    color-mix(in srgb, var(--tf-violet), transparent 70%);
}

.md-search__input,
.md-search__icon {
  color: var(--tf-ink);
}

.md-search__input::placeholder {
  color: var(--tf-muted);
}

.md-nav__title {
  color: var(--tf-ink);
  background: transparent;
  box-shadow: none;
  font-family: var(--tf-display);
  font-weight: 800;
}

/* On wide screens the sidebar is part of the sheet, so nothing in it may paint
 * its own paper — an opaque panel over the wash reads as a patch of a slightly
 * different white. The drawer at narrow widths keeps its background, which it
 * needs to sit over the content.
 */
@media screen and (min-width: 76.25em) {
  .md-sidebar,
  .md-sidebar__scrollwrap,
  .md-nav,
  .md-nav--primary .md-nav__title,
  .md-nav__title {
    background: transparent;
    box-shadow: none;
  }

  /* Material pins that title to the top of the nav and hides what scrolls
   * under it behind its own paper. With the paper gone the items ran straight
   * through it, and it has nothing to stay for anyway: it repeats the site
   * name already in the header. It scrolls with the list it heads.
   */
  .md-nav--primary .md-nav__title {
    position: static;
  }
}

.md-nav__item .md-nav__link--active,
.md-nav__item .md-nav__link--active code,
.md-nav__link:focus,
.md-nav__link:hover {
  color: var(--tf-violet);
}

.md-typeset {
  color: var(--md-default-fg-color);
  font-size: 0.78rem;
  line-height: 1.65;
}

/* Selection in the accent, weak enough that the ink stays the darkest thing on
 * the page.
 */
::selection {
  background: color-mix(in srgb, var(--tf-violet-light), transparent 78%);
}

/* Headings carry a violet rule whose weight tracks the level. Only h1 takes the
 * violet-to-teal gradient: it is the page's one title, so the flourish stays
 * singular instead of repeating down the page as decoration.
 */
.md-typeset h1,
.md-typeset h2,
.md-typeset h3,
.md-typeset h4 {
  color: var(--md-default-fg-color);
  font-family: var(--tf-display);
  letter-spacing: 0;
}

.md-typeset h1 {
  margin: 0 0 1.25rem;
  /* Drawn as a background bar, not a border: a single-side border-image would
   * sample one sliver of the gradient and lose the run from violet to teal.
   */
  padding-left: calc(0.3em + 11px);
  background: linear-gradient(
      180deg,
      var(--tf-violet-light) 0%,
      var(--tf-violet) 45%,
      var(--tf-teal) 100%
    )
    left top / 11px 100% no-repeat;
  font-size: 1.7rem;
  font-weight: 800;
  line-height: 1.1;
}

.md-typeset h2 {
  margin: 2em 0 0.7em;
  padding-left: 0.46em;
  border-left: 8px solid var(--tf-violet);
  font-size: 1.1rem;
  font-weight: 800;
  line-height: 1.13;
}

.md-typeset h3 {
  margin: 1.6em 0 0.5em;
  padding-left: 0.5em;
  border-left: 5px solid var(--tf-violet);
  font-size: 0.9rem;
  font-weight: 800;
  line-height: 1.2;
}

.md-typeset h4 {
  margin: 1.45em 0 0.4em;
  padding-left: 0.55em;
  border-left: 3px solid var(--tf-violet-light);
  font-size: 0.79rem;
  font-weight: 700;
}

/* An inline identifier is a chip in the accent rather than a grey box: at this
 * size a neutral fill just looks like a smudge in the line.
 */
.md-typeset code {
  padding: 0.05em 0.28em;
  border-radius: 4px;
  background: color-mix(in srgb, var(--tf-violet), transparent 93%);
  color: var(--md-code-fg-color);
  font-family: var(--tf-mono);
  font-size: 0.82em;
}

/* A block sits on a teal ground, the second accent: violet is the structural
 * colour — headings, section rules, the inline-identifier chip — so a block of
 * code reads as its own kind of material rather than more of the same. The tint
 * stays faint enough for the syntax colours to carry the contrast.
 */
.md-typeset pre > code {
  border: 1px solid color-mix(in srgb, var(--tf-teal), transparent 70%);
  border-radius: 8px;
  background: color-mix(in srgb, var(--tf-teal), transparent 86%);
}

/* Inside an admonition the block would otherwise sit on the same ground twice. */
.md-typeset .admonition pre > code,
.md-typeset details pre > code {
  background: color-mix(in srgb, var(--tf-teal), transparent 82%);
}

/* The line numbers are scenery: no fill of their own, a hairline to sit behind,
 * and digits light enough that the eye reads the code and not the count.
 */
.md-typeset .highlighttable .linenos {
  padding-right: 0.5rem;
  border: 0;
  border-right: 1px solid color-mix(in srgb, var(--tf-teal), transparent 78%);
  background: transparent;
  color: color-mix(in srgb, var(--tf-muted), transparent 45%);
  font-size: 0.88em;
  user-select: none;
}

.md-typeset .highlighttable .linenodiv pre {
  border: 0;
  background: transparent;
}

/* The table is the code block; only its outer edge is drawn. */
.md-typeset .highlighttable {
  border: 1px solid color-mix(in srgb, var(--tf-teal), transparent 70%);
  border-radius: 8px;
  background: color-mix(in srgb, var(--tf-teal), transparent 86%);
}

.md-typeset .highlighttable .code pre > code,
.md-typeset .highlighttable td > div > pre > code {
  border: 0;
  background: transparent;
}

.md-typeset .md-clipboard {
  color: var(--tf-muted);
}

.md-typeset .md-clipboard:hover {
  color: var(--tf-violet);
}

/* Links: violet, but underlined at less than full strength so a paragraph with
 * several of them does not turn into a ladder. Hover moves the underline to
 * teal, which is the one place the second accent answers the first.
 */
.md-typeset a {
  color: var(--tf-teal);
  text-decoration: underline;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.16em;
  text-decoration-color: color-mix(in srgb, var(--tf-teal), transparent 45%);
}

.md-typeset a:hover,
.md-typeset a:focus {
  color: var(--tf-teal);
  text-decoration-thickness: 0.14em;
  text-decoration-color: var(--tf-teal);
}

/* A link that is an identifier keeps the code chip and takes the same colour, so
 * a linked path reads as a link and not as one more inline identifier.
 */
.md-typeset a code {
  color: var(--tf-teal);
}

/* A rule between sections, drawn as light rather than as a line. */
.md-typeset hr {
  height: 1px;
  margin: 2rem 0;
  border: 0;
  background: linear-gradient(
    90deg,
    transparent,
    color-mix(in srgb, var(--tf-violet), transparent 70%) 18%,
    color-mix(in srgb, var(--tf-teal), transparent 76%) 82%,
    transparent
  );
}

.md-typeset blockquote {
  margin: 1.3em 0;
  padding: 0.08em 0 0.08em 1.05em;
  border-left: 3px solid var(--tf-teal);
  color: var(--md-default-fg-color);
}

.md-typeset .admonition,
.md-typeset details {
  border: 0;
  border-left: 3px solid var(--tf-rule);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

/* Material colours each admonition type differently — example violet, note
 * blue, tip green — which puts four more hues on the page. One rule for all of
 * them: teal, the same line the API blocks use. Only a warning differs, because
 * that one is a verdict rather than an aside.
 */
.md-typeset .admonition.example,
.md-typeset details.example,
.md-typeset .admonition.note,
.md-typeset details.note,
.md-typeset .admonition.info,
.md-typeset details.info,
.md-typeset .admonition.tip,
.md-typeset details.tip,
.md-typeset .admonition.abstract,
.md-typeset details.abstract,
.md-typeset .admonition.quote,
.md-typeset details.quote {
  border-left-color: var(--tf-rule);
}

.md-typeset .admonition.warning,
.md-typeset details.warning,
.md-typeset .admonition.danger,
.md-typeset details.danger,
.md-typeset .admonition.failure,
.md-typeset details.failure {
  border-left-color: var(--tf-rose);
}

/* Bold carries weight, not colour. A page has dozens of bold spans — a bullet's
 * leading term, a rule's name, a claim mid-paragraph — and colouring them all left
 * none of them standing out. The violet is spent on one sentence per page instead:
 * `.keystone` below.
 */

/* The claim a page rests on. It keeps its place in the paragraph and takes the
 * emphasis in the type: bold and italic, in the structural violet. No block, no
 * ground — a panel around one sentence stops the paragraph rather than pointing
 * at it. One per page: as soon as there are two, neither is the point.
 */
.md-typeset .keystone {
  padding: 0.05em 0.15em;
  /* A marker line under the text rather than a filled box: the sentence stays in
   * its paragraph, and the ground stops below the x-height so the letters keep
   * the page's own white behind them. */
  background: linear-gradient(
    to top,
    color-mix(in srgb, var(--tf-violet), transparent 82%) 0.62em,
    transparent 0.62em
  );
  color: var(--tf-violet);
  font-style: italic;
  font-weight: 700;
}

/* Italic Han glyphs are a synthetic slant, so the Chinese pages carry the
 * emphasis in weight and colour alone.
 */
html[lang="zh"] .md-typeset .keystone {
  font-style: normal;
}

.md-typeset .admonition-title,
.md-typeset summary {
  background: transparent;
  font-family: var(--tf-mono);
  font-size: 0.8rem;
}

/* Material sets an admonition two steps below body size, which is fine for a
 * one-line aside and wrong for the API pages, where every Example is one of
 * these blocks and its content is code.
 */
.md-typeset .admonition,
.md-typeset details {
  font-size: 0.78rem;
}

.md-typeset .admonition pre > code,
.md-typeset details pre > code {
  font-size: 0.74rem;
}

/* An `Example:` section in a docstring becomes an `example` admonition, whose
 * default icon is a lab flask — a picture of something the section is not. The
 * word and the teal rule already say what the block is.
 */
.md-typeset .admonition.example > .admonition-title,
.md-typeset details.example > summary {
  padding-left: 0.6rem;
}

.md-typeset .admonition.example > .admonition-title::before,
.md-typeset details.example > summary::before {
  display: none;
}

/* Three rules and nothing else: above the head, under it, under the last row.
 * No verticals, no zebra, no fill — the columns are held apart by their own
 * alignment, and every mark added beyond these three is one the reader has to
 * look past to get at the numbers.
 */
/* Material sizes a table to its content (`display: inline-block`), which leaves
 * every table a different width from the prose above it. A table is a block of
 * the page like a paragraph or a code block, so it takes the column. The
 * scroll wrapper Material puts around it still handles one too wide to fit.
 */
.md-typeset__table {
  width: 100%;
}

.md-typeset table:not([class]) {
  display: table;
  width: 100%;
}

.md-typeset table:not([class]) {
  margin: 1em 0;
  /* Material fills a table with the page colour, which over the wash reads as
   * a lighter panel laid on the sheet.
   */
  background: none;
  border: 0;
  border-top: 2px solid color-mix(in srgb, var(--tf-ink), transparent 55%);
  border-bottom: 2px solid color-mix(in srgb, var(--tf-ink), transparent 55%);
  font-size: 0.75rem;
}

/* The middle rule is the table's one accented mark, and on a Benchmarks page
 * the only place the palette can sit at all — those pages are columns of
 * figures with nowhere for a heading rule to go.
 */
/* An identifier broken across two lines stops reading as one name, and in a
 * table it is the first column — the one holding names — that gets squeezed. A
 * code span never wraps, so the column claims the width its longest name needs;
 * the scroll wrapper handles a table that then exceeds the page.
 */
.md-typeset table:not([class]) code {
  white-space: nowrap;
}

.md-typeset table:not([class]) th {
  border: 0;
  border-bottom: 2px solid var(--tf-violet);
  color: var(--tf-violet-dark);
  font-family: var(--tf-display);
  font-size: 0.8rem;
  font-weight: 700;
  background: none;
}

.md-typeset table:not([class]) td {
  border: 0;
  background: none;
}

/* Benchmark data tables: many short numeric cells. Keeping each cell on one
 * line and letting the table scroll beats wrapping every column to fit, which
 * turns one row into four. The wrapper comes from
 * scripts/gen_bench_pages.py.
 */
.md-typeset .datatable table:not([class]) {
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
}

.md-typeset .datatable table:not([class]) td,
.md-typeset .datatable table:not([class]) th {
  white-space: nowrap;
}

/* Everything centred in its column, except the workload name: it is the row's
 * label, of varying length, and reads as a list only when flush left.
 */
.md-typeset .datatable table:not([class]) th,
.md-typeset .datatable table:not([class]) td {
  text-align: center;
}

.md-typeset .datatable table:not([class]) td.colsep {
  text-align: left;
}

/* A hairline between the label and the numbers it belongs to — the table's one
 * vertical, thin and grey so it divides without ruling: what a row *is* on the
 * left, what it measured on the right.
 */
.md-typeset .datatable table:not([class]) .colsep {
  border-right: 1px solid color-mix(in srgb, var(--tf-ink), transparent 78%);
  padding-right: 1em;
}

/* A cell holding four stacked alternatives is four lines tall while its
 * neighbours are one. Tighter leading gives back most of a line; the row
 * padding is what separates one workload from the next, since nothing is
 * drawn between them.
 */
.md-typeset .datatable table:not([class]) td {
  padding-top: 0.55em;
  padding-bottom: 0.55em;
  line-height: 1.35;
  border-bottom: 0;
}

/* Everything but the fastest alternative is context. */
.md-typeset .datatable table:not([class]) .alt-slow,
.md-typeset .datatable table:not([class]) .alt-slow code {
  color: var(--tf-muted);
}

/* The Alternatives sub-columns stack one line per alternative. Top alignment is
 * what makes them read across, and keeps Ratio level with the fastest one.
 */
.md-typeset .datatable table:not([class]) td {
  vertical-align: top;
}

/* Two header rows, still one middle rule: it belongs under the whole header
 * block, not between its halves. The `Workload` cell spans both rows, so its
 * own bottom edge already sits on that line.
 */
/* Each header word is underlined thin and grey — under `Alternatives` that is
 * also what says how far a header spanning two columns reaches. The block's
 * own heavy rule stays below the units, so these read as brackets over their
 * columns rather than as further divisions of the table.
 */
.md-typeset .datatable table:not([class]) thead tr:first-child th:not([rowspan]) {
  border-bottom: 1px solid color-mix(in srgb, var(--tf-ink), transparent 74%);
}

/* Second header row: units and the ratio's direction. Subordinate to the
 * header word above it, so it reads as a qualifier rather than a column of its
 * own — which is exactly what teal marks everywhere else on the site.
 */
.md-typeset .datatable table:not([class]) th.subhead {
  color: color-mix(in srgb, var(--tf-teal), var(--tf-muted) 25%);
  font-family: var(--tf-mono);
  font-size: 0.66rem;
  font-weight: 400;
}

.md-typeset .datatable table:not([class]) code {
  background: transparent;
  padding: 0;
  color: var(--md-default-fg-color--light);
}

/* The workload names take a cool cast, so the teal rule reads as dividing a
 * teal label column from ink measurements rather than as a line dropped
 * between them. It is the same in every row, which is what keeps it clear of
 * the verdict: a colour that never varies cannot be reporting a result.
 */
.md-typeset .datatable table:not([class]) td.colsep code {
  color: color-mix(in srgb, var(--tf-teal), var(--tf-muted) 32%);
}

/* Benchmark verdicts. The ratio's colour *is* the result, so these carry the
 * weight no separate status glyph does: rose behind the alternative, plain ink
 * level with it, green ahead. Tabular figures keep a column of them aligned.
 *
 * Neither verdict colour is the link violet or the aside teal: a reader
 * scanning a Ratio column must not have to decide whether a coloured figure is
 * a verdict or a link. The green sits well away from the teal in both hue and
 * lightness for the same reason.
 */
.md-typeset .perf-ahead,
.md-typeset .perf-par,
.md-typeset .perf-behind {
  font-family: var(--tf-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  white-space: nowrap;
}

.md-typeset .perf-ahead {
  color: var(--tf-green);
}

.md-typeset .perf-par {
  color: var(--md-default-fg-color);
}

.md-typeset .perf-behind {
  color: var(--tf-rose);
}

/* A ratio against an eager reference only. Shown, but never as a win: the bar
 * is a naive composition of PyTorch ops that nobody competes at.
 */
.md-typeset .perf-unrated {
  color: var(--tf-muted);
  font-family: var(--tf-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.md-typeset .perf-none {
  color: var(--md-default-fg-color--light);
}

/* The count beside an op name is what the heading is *about*, not part of it:
 * teal, in the body face, at the weight of running text. In the display face
 * at 800 it was reading as a second half of the op's name.
 */
.md-typeset h3 > small {
  color: var(--tf-teal);
  font-family: var(--tf-body);
  font-size: 0.72em;
  font-weight: 500;
}

/* A verdict repeated in an op heading sits in the display face around it. */
.md-typeset h3 .perf-ahead,
.md-typeset h3 .perf-par,
.md-typeset h3 .perf-behind {
  font-size: 0.82em;
}

/* mkdocstrings: a symbol heading is a name, not prose. It carries the mono
 * face at a size close to the body text — an op class set at the prose h2 size
 * turns a reference page into forty display-weight banners, and the accent bar
 * beside each one is what makes the column look striped.
 */
.md-typeset h2.doc-heading,
.md-typeset h3.doc-heading,
.md-typeset h4.doc-heading,
.md-typeset h5.doc-heading {
  font-family: var(--tf-mono);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.35;
}

.md-typeset h2.doc-heading {
  margin: 2.1em 0 0.5em;
  border-left-width: 4px;
  font-size: 0.88rem;
}

.md-typeset h3.doc-heading {
  margin: 1.5em 0 0.4em;
  border-left-width: 3px;
  border-left-color: var(--tf-violet-light);
  font-size: 0.78rem;
}

.md-typeset h4.doc-heading,
.md-typeset h5.doc-heading {
  border-left-color: var(--tf-line);
  font-size: 0.76rem;
}

/* The name inside the heading is already in the mono face at heading size;
 * the inline-identifier chip on top of that is a second treatment of the same
 * thing. The symbol chip is a `code` element too, and it keeps its own fill.
 */
.md-typeset .doc-heading code:not(.doc-symbol) {
  padding: 0;
  background: transparent;
  font-size: 1em;
}

/* The symbol chips: mkdocstrings ships its own palette, which lands two more
 * hues on a page that already has two. A class takes the structural violet, a
 * method the teal, and the rest sit at the muted weight.
 */
:root {
  --doc-symbol-class-fg-color: var(--tf-violet);
  --doc-symbol-class-bg-color: color-mix(in srgb, var(--tf-violet), transparent 92%);
  --doc-symbol-method-fg-color: var(--tf-teal);
  --doc-symbol-method-bg-color: color-mix(in srgb, var(--tf-teal), transparent 90%);
  --doc-symbol-function-fg-color: var(--tf-teal);
  --doc-symbol-function-bg-color: color-mix(in srgb, var(--tf-teal), transparent 90%);
  --doc-symbol-attribute-fg-color: var(--tf-muted);
  --doc-symbol-attribute-bg-color: color-mix(in srgb, var(--tf-muted), transparent 92%);
  --doc-symbol-module-fg-color: var(--tf-muted);
  --doc-symbol-module-bg-color: color-mix(in srgb, var(--tf-muted), transparent 92%);
  --doc-symbol-parameter-fg-color: var(--tf-muted);
  --doc-symbol-parameter-bg-color: color-mix(in srgb, var(--tf-muted), transparent 92%);
}

/* Only the class keeps its chip. A method is already inside its class, under a
 * heading of its own, so `meth` repeats what the position says — and it lands
 * right where the eye enters the line. Keyed on the object, not the heading
 * level: a page that renders a package puts classes at h2 and methods at h3,
 * one that renders each op puts them at h3 and h4.
 */
.md-typeset .doc-object.doc-function > .doc-heading .doc-symbol-heading,
.md-typeset .doc-object.doc-attribute > .doc-heading .doc-symbol-heading {
  display: none;
}

.md-typeset .doc-symbol-heading {
  margin-right: 0.45em;
  font-family: var(--tf-body);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  vertical-align: 0.12em;
}

/* A class and everything under it hang from one line: the signature, the
 * parameters, and the methods are one group, marked by a spine rather than by a
 * filled card — a panel over the wash reads as a patch of different paper.
 */
.md-typeset .doc-object.doc-class > .doc-contents {
  margin-left: 0.15rem;
  padding-left: 1.5rem;
  border-left: 1px solid var(--tf-line-soft);
}

/* Everything under a class sits at one level: the prose, the constructor and the
 * call are siblings, so a second indent for the methods only pushed them away
 * from the parameters they belong with. The method's own contents keep a teal
 * hairline, which marks the group without moving it.
 */
.md-typeset .doc-object.doc-function > .doc-contents {
  padding-left: 0;
  border-left: 0;
}

/* A member's heading repeats the name the signature under it already carries, so
 * it collapses to a bare anchor: no text, no space, no permalink. It has to stay
 * in the document for the right-hand column to link to — the table of contents
 * still reads the heading, and reads only the name.
 */
.md-typeset .doc-object.doc-function > .doc-heading,
.md-typeset .doc-object.doc-attribute > .doc-heading {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 0;
  line-height: 0;
}

.md-typeset .doc-object.doc-function > .doc-heading .headerlink,
.md-typeset .doc-object.doc-attribute > .doc-heading .headerlink {
  display: none;
}

/* The signature carries the weight the heading gave up. */
.md-typeset .doc-object.doc-function > .doc-contents {
  margin-top: 1.7em;
}

/* The two method entries under one class are siblings, not a list: space them
 * rather than ruling between them.
 */
.md-typeset .doc-object.doc-function + .doc-object.doc-function {
  margin-top: 1.6em;
}

/* One op is one unit on the page. A rule above each symbol, and room around it,
 * gives the reference a beat: without them the page is a single column of text
 * where nothing marks where one op ends and the next begins.
 */
.md-typeset .doc-object.doc-class > .doc-heading {
  margin-top: 3em;
  padding-top: 1.3em;
  border-top: 1px solid var(--tf-line-soft);
}

/* The first class under a family heading needs no rule: the heading is the break. */
.md-typeset h2 + .doc-object.doc-class > .doc-heading,
.md-typeset h2 + div > .doc-object.doc-class > .doc-heading {
  padding-top: 0;
  border-top: 0;
}

/* A signature is a declaration, not a listing: violet like the other structural
 * marks, no fill, no rounded box — so it does not read as a second example.
 */
.md-typeset .doc-signature > pre > code,
.md-typeset div.doc-signature pre > code,
.md-typeset pre > code.doc-signature {
  border: 0;
  border-left: 3px solid var(--tf-rule);
  border-radius: 0;
  background: transparent;
  padding-left: 0.7rem;
}

/* Parameters, Returns, Raises: the label carries the break, the list stays tight
 * under it.
 */
.md-typeset .doc-section-title {
  margin-top: 1.4em;
  margin-bottom: 0.3em;
}

/* `property`, `classmethod`, `async` — a note about the symbol, not part of
 * its name.
 */
.md-typeset .doc-labels .doc-label {
  background: color-mix(in srgb, var(--tf-teal), transparent 90%);
  color: var(--tf-teal);
  font-family: var(--tf-body);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* Parameters render as a definition list. The section label heads it in the
 * display face, and each parameter name stays in mono so the list reads as a
 * signature rather than a paragraph.
 */
.md-typeset .doc-section-title {
  color: var(--tf-muted);
  font-family: var(--tf-display);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.md-typeset .doc-section-item {
  margin: 0.2em 0;
}

/* Right column: the page's own headings. It is a locator, so it is set quieter
 * and tighter than the left nav — smaller type, muted ink, and a hairline that
 * gives the column an edge instead of leaving it floating in the margin.
 */
.md-sidebar--secondary .md-nav__title {
  color: var(--tf-muted);
  font-family: var(--tf-display);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding-bottom: 0.5rem;
  text-transform: uppercase;
}

.md-sidebar--secondary .md-nav__list {
  border-left: 1px solid var(--tf-line-soft);
}

.md-sidebar--secondary .md-nav__link {
  color: var(--tf-muted);
  font-size: 0.68rem;
  line-height: 1.45;
  margin-top: 0.42rem;
  padding-left: 0.7rem;
}

/* The section being read is marked on the rule the list hangs from, so the
 * text itself does not have to change weight to say where you are.
 */
.md-sidebar--secondary .md-nav__link--active,
.md-sidebar--secondary .md-nav__link--passed:hover,
.md-sidebar--secondary .md-nav__link:hover {
  color: var(--tf-violet);
}

.md-sidebar--secondary .md-nav__link--active {
  box-shadow: inset 2px 0 var(--tf-violet);
}

/* A third-level entry is subordinate to the h2 above it: indented once, and a
 * step down in size rather than a second bullet level.
 */
.md-sidebar--secondary .md-nav__list .md-nav__list .md-nav__link {
  border-left: 0;
  font-size: 0.65rem;
  padding-left: 1.35rem;
}

.md-sidebar--secondary .md-nav__list .md-nav__list {
  border-left: 0;
}

/* Han glyphs need the extra leading in a column this narrow. */
html[lang="zh"] .md-sidebar--secondary .md-nav__link {
  font-size: 0.7rem;
  line-height: 1.6;
}

/* Material maps the token classes onto --md-code-hl-*, which covers keywords,
 * strings and numbers. A typical example is mostly names, operators and calls —
 * all of which fell through to plain ink, so the block read as unhighlighted.
 */
.md-typeset .highlight .o,        /* operator: = * -> */
.md-typeset .highlight .ow {
  color: var(--tf-violet);
}

.md-typeset .highlight .p {       /* punctuation: ( ) , [ ] */
  color: var(--tf-muted);
}

.md-typeset .highlight .nf,       /* function definition */
.md-typeset .highlight .fm,
.md-typeset .highlight .nc,       /* class */
.md-typeset .highlight .nb,       /* builtin */
.md-typeset .highlight .bp {
  color: var(--tf-violet-light);
}

.md-typeset .highlight .nd,       /* decorator */
.md-typeset .highlight .kn,       /* import */
.md-typeset .highlight .kc {
  color: var(--tf-teal);
}

.md-typeset .highlight .c1,       /* comment */
.md-typeset .highlight .cm,
.md-typeset .highlight .ch {
  font-style: italic;
}

/* Language switcher: a quiet pill on the paper header, matching the source
 * link beside it rather than Material's default bare-icon dropdown.
 */
.md-header__option .md-select__inner {
  border-radius: 999px;
}

.md-header__option .md-select__link {
  font-family: var(--tf-body);
  font-size: 0.75rem;
  font-weight: 700;
}

/* A page served from the default language because this locale has no
 * translation yet. Reads as a status line, not as a warning.
 */
.md-typeset .locale-notice {
  margin: -0.4rem 0 1.4rem;
  padding: 0.5rem 0.8rem;
  border-left: 3px solid var(--tf-line);
  background: var(--tf-line-soft);
  color: var(--tf-muted);
  font-size: 0.78rem;
  line-height: 1.6;
}

.md-typeset .locale-notice strong {
  margin-right: 0.35em;
  color: var(--md-default-fg-color);
  font-weight: 700;
}

/* Chinese type metrics. Han glyphs fill their em box, so the Latin line height
 * reads as cramped; headings set in a Latin display face at 800 fall through to
 * a CJK face where that weight closes up the strokes. The size stays at the
 * Latin one — a step up on top of the fuller em box makes the column heavy.
 *
 * Scoped away from pages carrying .locale-notice: their body text is English,
 * and Latin copy under Chinese metrics reads as loose.
 */
html[lang="zh"] .md-typeset:not(:has(> .locale-notice)) {
  line-height: 1.75;
}

html[lang="zh"] .md-typeset:not(:has(> .locale-notice)) h1,
html[lang="zh"] .md-typeset:not(:has(> .locale-notice)) h2,
html[lang="zh"] .md-typeset:not(:has(> .locale-notice)) h3,
html[lang="zh"] .md-typeset:not(:has(> .locale-notice)) h4 {
  font-weight: 700;
}

/* Inline code sits in the middle of Chinese sentences far more often than in
 * English ones; at the larger Chinese body size it needs less box around it.
 * Inline only — unscoped, this took the padding off code blocks too.
 */
html[lang="zh"] .md-typeset:not(:has(> .locale-notice)) code:not(pre > code) {
  font-size: 0.8em;
  padding: 0.04em 0.24em;
}

/* Underlines otherwise cut into the descender-free baseline of Han glyphs. */
html[lang="zh"] .md-typeset a {
  text-underline-offset: 0.18em;
}

html[lang="zh"] .md-nav,
html[lang="zh"] .md-nav__title {
  line-height: 1.5;
}

/* Sequence diagrams. The fence sets the type a size up from mermaid's default, which the
 * diagram can afford once it fits the column; a wider one scrolls rather than shrinking
 * the page. The autonumber bubble defaults to near-black, which reads as a blob at this
 * size, so it takes the structural violet. */
.md-typeset .mermaid {
  overflow-x: auto;
  --md-mermaid-sequence-number-bg-color: var(--tf-violet);
}

.md-typeset .mermaid text.sequenceNumber {
  font-size: 12px !important;
  font-weight: 700;
}

/* Sequence diagrams. The fence sets the type a size up from mermaid's default, which the
 * diagram can afford once it fits the column; a wider one scrolls rather than shrinking
 * the page. The autonumber bubble defaults to near-black, which reads as a blob at this
 * size, so it takes the structural violet. */
.md-typeset .mermaid {
  overflow-x: auto;
  --md-mermaid-sequence-number-bg-color: var(--tf-violet);
}

.md-typeset .mermaid text.sequenceNumber {
  font-size: 12px !important;
  font-weight: 700;
}

/* Flowcharts. Two roles to tell apart at a glance: the layers dynamo traces, and the
 * opaque node's interior. Colour comes from the palette rather than from the diagram
 * source, so both schemes stay right and the .md stays readable. The boundary edge is the
 * one thick link on the page. */
.md-typeset .mermaid g.node.traced > rect {
  fill: color-mix(in srgb, var(--tf-violet), transparent 88%);
  stroke: var(--tf-violet);
}

.md-typeset .mermaid g.node.opaque > rect {
  fill: color-mix(in srgb, var(--tf-teal), transparent 92%);
  stroke: var(--tf-rule);
  stroke-dasharray: 5 3;
}

.md-typeset .mermaid .edgeLabel {
  font-size: 12px;
  font-weight: 700;
}

.md-typeset .mermaid .edgeLabel .label foreignObject > div {
  color: var(--tf-violet);
}

/* The call-path figure on the torch.compile page. Four layers of one call, every row the
 * same width — a diagram engine sizes each box to its text, which reads as clutter when
 * the rows are meant to be read as a stack. Colour separates the two roles: violet for
 * what dynamo traces, a dashed teal for the opaque node's interior. */
.md-typeset figure.callpath {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 1.2em 0;
}

.md-typeset figure.callpath .cp-step {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.5rem 0.8rem;
  border-radius: 0.2rem;
  font-size: 0.75rem;
  line-height: 1.5;
}

.md-typeset figure.callpath .cp-step > code {
  background: none;
  padding: 0;
  font-size: 0.78rem;
  font-weight: 700;
}

.md-typeset figure.callpath .cp-traced {
  border: 1px solid var(--tf-violet);
  background: color-mix(in srgb, var(--tf-violet), transparent 92%);
}

.md-typeset figure.callpath .cp-traced > code {
  color: var(--tf-violet);
}

.md-typeset figure.callpath .cp-opaque {
  border: 1px dashed var(--tf-rule);
  background: color-mix(in srgb, var(--tf-teal), transparent 95%);
}

.md-typeset figure.callpath .cp-opaque > code {
  color: var(--tf-teal);
}

/* The boundary itself: a rule across the stack with its name sitting on it. */
.md-typeset figure.callpath .cp-boundary {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.15rem 0;
  color: var(--tf-violet);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.md-typeset figure.callpath .cp-boundary::before,
.md-typeset figure.callpath .cp-boundary::after {
  flex: 1;
  height: 2px;
  background: color-mix(in srgb, var(--tf-violet), transparent 55%);
  content: "";
}

.md-typeset figure.callpath figcaption {
  margin-top: 0.3rem;
  color: var(--md-default-fg-color--light);
  font-size: 0.7rem;
  line-height: 1.6;
  text-align: left;
}
