/*
 * Documentation styling that follows design/docs-ui-spec.md: the repobs application's palette and shapes (flat, square,
 * rule-framed surfaces; labels in sentence-case semibold Geist; Geist Mono for code and indices) in the page shape of
 * the EnergyAtlas documentation sites (a serif italic line in the hero, two-part grids), on Material for MkDocs.
 * Sizes are in rem so that they scale with Material's root font size (1rem = 20px at the base size, so 0.6rem = 12px).
 * Keep the token values in step with apps/web/src/theme/tokens.css.
 */

/* ---------------------------------------------------------------- Tokens */

:root {
  --font-sans: "Geist", system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "Cascadia Code", Consolas, monospace;
  /* The second line of the landing headline only (spec 0.4). */
  --font-serif: "Cormorant Garamond", Georgia, serif;

  --md-text-font: "Geist";
  --md-code-font: "Geist Mono";

  --ui-transition: 150ms ease;

  /* Horizontal margin of the article inside the content column; full-bleed strips and grids cancel it. */
  --ui-gutter: 0.8rem;
}

@media screen and (min-width: 76.25em) {
  :root {
    --ui-gutter: 1.2rem;
  }
}

[data-md-color-scheme="slate"] {
  --ui-bg-base: #000000;
  --ui-bg-raised: #1a1a1a;
  --ui-bg-hover: #111418;
  --ui-bg-selected: #0c1a29;
  --ui-text-primary: #e5e5e5;
  --ui-text-secondary: #b3b3b3;
  --ui-text-muted: #999999;
  --ui-border-subtle: #404040;
  --ui-border-interactive: #6b6b6b;
  --ui-accent: #4da3ff;
  --ui-accent-tint: rgb(77 163 255 / 10%);
  --ui-success: #28a745;
  --ui-warning: #ffc107;
  --ui-danger: #f44336;
}

[data-md-color-scheme="default"] {
  --ui-bg-base: #ffffff;
  --ui-bg-raised: #f8fafc;
  --ui-bg-hover: #f1f5f9;
  --ui-bg-selected: #e7eff7;
  --ui-text-primary: #18202c;
  --ui-text-secondary: #3f4b5b;
  --ui-text-muted: #5f6b7a;
  --ui-border-subtle: #cfd8e5;
  --ui-border-interactive: #768599;
  --ui-accent: #125dae;
  --ui-accent-tint: rgb(18 93 174 / 8%);
  --ui-success: #188038;
  --ui-warning: #946300;
  --ui-danger: #c5221f;
}

/* Material's own variables, mapped onto the tokens for both schemes. */
[data-md-color-scheme="slate"],
[data-md-color-scheme="default"] {
  --ui-button-bg: color-mix(in srgb, var(--ui-text-primary) 8%, var(--ui-bg-base));
  --ui-button-bg-hover: color-mix(in srgb, var(--ui-text-primary) 14%, var(--ui-bg-base));

  --md-default-bg-color: var(--ui-bg-base);
  --md-default-fg-color: var(--ui-text-primary);
  --md-default-fg-color--light: var(--ui-text-secondary);
  --md-default-fg-color--lighter: var(--ui-text-muted);
  --md-default-fg-color--lightest: var(--ui-border-subtle);

  --md-primary-fg-color: var(--ui-bg-base);
  --md-primary-fg-color--light: var(--ui-bg-raised);
  --md-primary-fg-color--dark: var(--ui-bg-base);
  --md-primary-bg-color: var(--ui-text-primary);
  --md-primary-bg-color--light: var(--ui-text-secondary);

  --md-accent-fg-color: var(--ui-accent);
  --md-accent-fg-color--transparent: var(--ui-accent-tint);
  --md-accent-bg-color: var(--ui-bg-base);
  --md-accent-bg-color--light: var(--ui-bg-raised);

  --md-typeset-color: var(--ui-text-secondary);
  --md-typeset-a-color: var(--ui-accent);
  --md-typeset-mark-color: var(--ui-bg-selected);
  --md-typeset-table-color: var(--ui-border-subtle);
  --md-typeset-table-color--light: var(--ui-accent-tint);

  --md-code-bg-color: var(--ui-bg-raised);
  --md-code-fg-color: var(--ui-text-primary);

  --md-admonition-bg-color: transparent;
  --md-admonition-fg-color: var(--ui-text-secondary);

  --md-footer-bg-color: var(--ui-bg-base);
  --md-footer-bg-color--dark: var(--ui-bg-base);
  --md-footer-fg-color: var(--ui-text-primary);
  --md-footer-fg-color--light: var(--ui-text-secondary);
  --md-footer-fg-color--lighter: var(--ui-text-muted);

  --md-shadow-z1: none;
  --md-shadow-z2: none;
  --md-shadow-z3: none;

  background-color: var(--ui-bg-base);
}

/* ------------------------------------------------------------ Page frame */

/* Reserve the scrollbar's width on every page, so moving between short and long pages does not shift the layout. */
html {
  scrollbar-gutter: stable;
}

.md-grid {
  max-width: 76rem;
}

.md-main__inner {
  margin-top: 0;
}

/* The content column is bounded by two thin vertical rules, like the panes of the application. */
@media screen and (min-width: 60em) {
  .md-content {
    border-left: 1px solid var(--ui-border-subtle);
    border-right: 1px solid var(--ui-border-subtle);
    min-height: calc(100vh - 4.8rem);
  }
}

.md-sidebar {
  padding-top: 1.6rem;
}

.md-content__inner {
  padding-top: 1.2rem;
}

/*
 * A page that hides a sidebar (the landing page hides both) keeps the sidebar's width as an empty margin, without its
 * rule, so its text lines up with the text of every other page. Strips and grids still run from frame to frame.
 */
.md-content {
  --ui-inset-left: 0rem;
  --ui-inset-right: 0rem;
}

@media screen and (min-width: 76.25em) {
  .md-sidebar--primary[hidden] ~ .md-content {
    --ui-inset-left: 12.1rem;
  }

  .md-sidebar--secondary[hidden] ~ .md-content {
    --ui-inset-right: 12.1rem;
  }
}

/* Outranks Material's [dir=ltr] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner margins. */
[dir] .md-main__inner > .md-content > .md-content__inner.md-typeset,
[dir] .md-main__inner > .md-content > .md-path {
  margin-left: calc(var(--ui-gutter) + var(--ui-inset-left));
  margin-right: calc(var(--ui-gutter) + var(--ui-inset-right));
}

/* -------------------------------------------------------- Header and tabs */

/* The header is the application's ribbon: the base surface, one bottom rule, the wordmark bold in the text colour. */
.md-header,
.md-header--shadow {
  border-bottom: 1px solid var(--ui-border-subtle);
  box-shadow: none;
}

.md-header__title {
  color: var(--ui-text-primary);
  font-weight: 650;
  letter-spacing: -0.01em;
}

/* No mark in the header or the phone drawer: the wordmark stands alone (spec 0.1). */
.md-header__button.md-logo,
.md-nav__button.md-logo {
  display: none;
}

.md-header__button:not([hidden]):is(:focus, :hover) {
  opacity: 1;
  color: var(--ui-accent);
}

/* The loading bar of instant navigation: a thin accent rule along the top edge. */
.md-progress {
  background-color: var(--ui-accent);
}

/* The tab bar shares the header's surface, as on the EnergyAtlas sites, with one bottom rule. */
.md-tabs {
  background-color: var(--ui-bg-base);
  border-bottom: 1px solid var(--ui-border-subtle);
  color: var(--ui-text-muted);
}

.md-tabs__item {
  height: 2rem;
  padding-left: 0.2rem;
  padding-right: 0.2rem;
}

.md-tabs__link {
  align-items: center;
  color: var(--ui-text-muted);
  display: flex;
  font-size: 0.6rem;
  font-weight: 600;
  height: 1.3rem;
  margin-top: 0.35rem;
  opacity: 1;
  padding: 0 0.5rem;
  transition: color var(--ui-transition), background-color var(--ui-transition), box-shadow var(--ui-transition);
}

.md-tabs__link:is(:focus, :hover) {
  background-color: var(--ui-bg-base);
  box-shadow: inset 0 0 0 1px var(--ui-border-interactive);
  color: var(--ui-text-primary);
}

/* The selected tab: an inverted block inside a thin accent outline drawn inset with a gap, as in the application. */
.md-tabs__item--active .md-tabs__link,
.md-tabs__item--active .md-tabs__link:is(:focus, :hover) {
  background-color: var(--ui-text-primary);
  box-shadow: inset 0 0 0 1px var(--ui-accent), inset 0 0 0 3px var(--ui-bg-base);
  color: var(--ui-bg-base);
  padding: 0 0.6rem;
}

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

/* A square field with a plain edge on the header's surface. */
@media screen and (min-width: 60em) {
  .md-search__form {
    background-color: var(--ui-bg-base);
    border: 1px solid var(--ui-border-interactive);
    border-radius: 0;
    height: 1.7rem;
    transition: border-color var(--ui-transition);
  }

  .md-search__form:hover {
    background-color: var(--ui-bg-base);
    border-color: var(--ui-text-muted);
  }

  [data-md-toggle="search"]:checked ~ .md-header .md-search__form {
    background-color: var(--ui-bg-base);
    border-color: var(--ui-accent);
    border-radius: 0;
    box-shadow: none;
  }

  .md-search__output {
    border: 1px solid var(--ui-border-interactive);
    border-top: 0;
    border-radius: 0;
    box-shadow: var(--ui-shadow-popover);
  }

  .md-search__input + .md-search__icon,
  .md-search__input::placeholder {
    color: var(--ui-text-muted);
  }
}

[data-md-color-scheme="slate"] {
  --ui-shadow-popover: 0 8px 24px rgb(0 0 0 / 55%);
}

[data-md-color-scheme="default"] {
  --ui-shadow-popover: 0 6px 16px rgb(0 0 0 / 14%);
}

.md-search__input {
  font-family: var(--font-sans);
  font-size: 0.7rem;
}

.md-search__input::placeholder {
  font-size: 0.65rem;
}

.md-search-result__meta {
  background-color: var(--ui-bg-raised);
  border-bottom: 1px solid var(--ui-border-subtle);
  color: var(--ui-text-muted);
  font-size: 0.6rem;
  font-weight: 600;
}

.md-search-result__link:is(:focus, :hover),
.md-search-result__more > summary:is(:focus, :hover) > div {
  background-color: var(--ui-accent-tint);
}

/* ----------------------------------------------------------- Breadcrumbs */

.md-path {
  font-size: 0.6rem;
  font-weight: 600;
  margin-left: var(--ui-gutter);
  margin-right: var(--ui-gutter);
  padding-top: 1.2rem;
}

.md-path__list {
  gap: 0.4rem;
}

.md-path__item:not(:first-child) {
  gap: 0.4rem;
}

.md-path__item:not(:first-child)::before {
  background: none;
  color: var(--ui-text-muted);
  content: "/";
  font-weight: 400;
  height: auto;
  -webkit-mask-image: none;
  mask-image: none;
  width: auto;
}

.md-path__link {
  color: var(--ui-text-muted);
}

.md-path__link:is(:focus, :hover) {
  color: var(--ui-accent);
}

.md-path ~ .md-content__inner {
  padding-top: 0.4rem;
}

/* ------------------------------------------------------------ Sidebars */

.md-nav {
  font-size: 0.68rem;
}

.md-nav__link {
  color: var(--ui-text-secondary);
  transition: color var(--ui-transition);
}

.md-nav__link:is(:focus, :hover),
.md-nav__item .md-nav__link--active:is(:focus, :hover) {
  color: var(--ui-text-primary);
}

.md-nav__item .md-nav__link--active,
.md-nav__item .md-nav__link--active code {
  color: var(--ui-accent);
}

/* Section titles and the "Table of contents" title use the label style. */
.md-nav__title,
.md-nav__item--section > .md-nav__link,
.md-nav__item--section > .md-nav__link[for] {
  color: var(--ui-text-muted);
  font-size: 0.6rem;
  font-weight: 600;
}

@media screen and (min-width: 76.25em) {
  .md-nav__item--section > .md-nav__link {
    margin-bottom: 0.3rem;
  }

  /* The active page carries a thin accent edge, as the application marks a selection. */
  .md-nav--primary .md-nav__link--active:not(.md-nav__container) {
    box-shadow: -0.45rem 0 0 -0.4rem var(--ui-accent);
  }

  .md-nav--secondary {
    border-left: 1px solid var(--ui-border-subtle);
    padding-left: 0.6rem;
  }
}

.md-nav--secondary .md-nav__title {
  background: none;
  box-shadow: none;
}

/* The phone drawer: the raised surface for its title bar. A page that hides its navigation sidebar (the landing page)
   still gets the drawer below the tabs breakpoint, so the menu button never opens an empty screen. */
@media screen and (max-width: 76.234375em) {
  .md-sidebar--primary[hidden] {
    display: block;
  }

  .md-nav--primary .md-nav__title {
    background-color: var(--ui-bg-raised);
    border-bottom: 1px solid var(--ui-border-subtle);
  }

  .md-nav--primary .md-nav__title[for="__drawer"] {
    color: var(--ui-accent);
    font-size: 0.8rem;
    font-weight: 700;
  }
}

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

.md-typeset {
  font-size: 0.75rem;
  line-height: 1.6;
}

.md-typeset :is(h1, h2, h3, h4, h5, h6) {
  color: var(--ui-text-primary);
  font-family: var(--font-sans);
}

.md-typeset h1 {
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin: 0 0 1rem;
}

.md-typeset h2 {
  font-size: 1.2rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  line-height: 1.2;
  margin: 2.4rem 0 0.7rem;
}

.md-typeset h3 {
  font-size: 0.95rem;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: 1.8rem 0 0.5rem;
}

.md-typeset h4 {
  font-size: 0.8rem;
  font-weight: 650;
  line-height: 1.35;
  margin: 1.4rem 0 0.4rem;
}

.md-typeset :is(h5, h6) {
  color: var(--ui-text-muted);
  font-size: 0.6rem;
  font-weight: 600;
  text-transform: none;
}

@media screen and (max-width: 44.984375em) {
  .md-typeset h1 {
    font-size: 1.35rem;
  }

  .md-typeset h2 {
    font-size: 1.05rem;
    margin-top: 2rem;
  }
}

.md-typeset :is(strong, b) {
  color: var(--ui-text-primary);
}

.md-typeset a {
  text-decoration-color: transparent;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--ui-transition), text-decoration-color var(--ui-transition);
}

.md-typeset a:is(:focus, :hover) {
  color: var(--ui-accent);
  text-decoration-color: currentcolor;
}

.md-typeset :focus-visible,
.md-tabs__link:focus-visible,
.md-nav__link:focus-visible {
  outline: 2px solid var(--ui-accent);
  outline-offset: 1px;
}

.md-typeset .headerlink {
  color: var(--ui-text-muted);
  font-weight: 400;
}

.md-typeset hr {
  border-bottom: 1px solid var(--ui-border-subtle);
}

.md-typeset img {
  border: 1px solid var(--ui-border-subtle);
  border-radius: 0;
}

.md-typeset kbd {
  border-radius: 0;
  box-shadow: inset 0 -1px 0 var(--ui-border-interactive);
  font-family: var(--font-mono);
}

/* Long-form prose keeps a readable measure; tables, code, figures and grids use the full column. */
.md-typeset > :is(p, ul, ol, dl, blockquote, .admonition, details, h1, h2, h3, h4) {
  max-width: 46rem;
}

/* ---------------------------------------------------------------- Code */

.md-typeset code {
  border-radius: 0;
  font-size: 0.85em;
  padding: 0.1em 0.3em;
}

.md-typeset pre > code {
  border: 1px solid var(--ui-border-subtle);
  padding: 0.8em 1em;
}

.md-typeset .highlight {
  border-radius: 0;
}

.md-clipboard {
  color: var(--ui-text-muted);
}

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

/* The application's data table: a raised header row in the label style, rules between rows, no zebra striping. */
.md-typeset table:not([class]) {
  border: 1px solid var(--ui-border-subtle);
  border-radius: 0;
  font-size: 0.68rem;
}

.md-typeset table:not([class]) th {
  background-color: var(--ui-bg-raised);
  border-bottom: 1px solid var(--ui-border-subtle);
  color: var(--ui-text-muted);
  font-size: 0.6rem;
  font-weight: 600;
  min-width: 3rem;
  vertical-align: bottom;
  white-space: nowrap;
}

.md-typeset table:not([class]) :is(th, td) {
  padding: 0.5em 0.9em;
}

.md-typeset table:not([class]) :is(th, td) + :is(th, td) {
  border-left: 1px solid var(--ui-border-subtle);
}

.md-typeset table:not([class]) td {
  border-top: 1px solid var(--ui-border-subtle);
}

.md-typeset table:not([class]) tbody tr {
  transition: background-color var(--ui-transition);
}

.md-typeset table:not([class]) tbody tr:hover {
  background-color: var(--ui-accent-tint);
  box-shadow: none;
}

.md-typeset table:not([class]) code {
  white-space: nowrap;
}

/* In wide tables (five or more columns, such as the generated API index) the last column holds prose: keep it readable
   and let the table scroll inside its container instead of squeezing it to a word per line. */
.md-typeset table:not([class]):has(th:nth-child(5)) td:last-child {
  min-width: 16rem;
}

/* ----------------------------------------------------------- Admonitions */

/* [class] outranks Material's per-type rules, so one --ui-state drives the title and icon of every type.
   The box is ruled evenly on all sides: no accent stripe on the left edge (spec 0.15). */
.md-typeset :is(.admonition, details)[class] {
  --ui-state: var(--ui-accent);

  background-color: transparent;
  border: 1px solid var(--ui-border-subtle);
  border-radius: 0;
  box-shadow: none;
  font-size: 0.7rem;
}

.md-typeset :is(.admonition, details):is(.success, .check, .done)[class] {
  --ui-state: var(--ui-success);
}

.md-typeset :is(.admonition, details):is(.warning, .caution, .attention)[class] {
  --ui-state: var(--ui-warning);
}

.md-typeset :is(.admonition, details):is(.danger, .error, .failure, .fail, .missing, .bug)[class] {
  --ui-state: var(--ui-danger);
}

.md-typeset :is(.admonition, details):is(.example, .quote, .cite)[class] {
  --ui-state: var(--ui-text-muted);
}

.md-typeset :is(.admonition, details)[class] > :is(.admonition-title, summary) {
  background-color: var(--ui-bg-raised);
  border-bottom: 1px solid var(--ui-border-subtle);
  color: var(--ui-state);
  font-size: 0.6rem;
  font-weight: 600;
  margin: 0 -0.6rem;
  padding-bottom: 0.45rem;
  padding-top: 0.45rem;
}

.md-typeset :is(.admonition, details)[class] > :is(.admonition-title, summary)::before {
  background-color: var(--ui-state);
  height: 0.8rem;
  top: 0.5rem;
  width: 0.8rem;
}

.md-typeset :is(.admonition, details)[class] > :is(.admonition-title, summary)::after {
  color: var(--ui-state);
}

/* ------------------------------------------------------------- Buttons */

/* The application's button: square, an interactive edge, a raised fill; primary is an inverted block. */
.md-typeset .md-button {
  background-color: var(--ui-button-bg);
  border: 1px solid var(--ui-border-interactive);
  border-radius: 0;
  color: var(--ui-text-primary);
  font-size: 0.65rem;
  font-weight: 600;
  padding: 0.45rem 0.8rem;
  text-decoration: none;
  transition: color var(--ui-transition), background-color var(--ui-transition), border-color var(--ui-transition);
}

.md-typeset .md-button:is(:focus, :hover) {
  background-color: var(--ui-button-bg-hover);
  border-color: var(--ui-accent);
  color: var(--ui-text-primary);
}

.md-typeset .md-button--primary {
  background-color: var(--ui-text-primary);
  border-color: var(--ui-text-primary);
  color: var(--ui-bg-base);
}

.md-typeset .md-button--primary:is(:focus, :hover) {
  background-color: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-bg-base);
}

.md-top {
  background-color: var(--ui-button-bg);
  border: 1px solid var(--ui-border-interactive);
  border-radius: 0;
  box-shadow: none;
  color: var(--ui-text-primary);
  font-size: 0.6rem;
  font-weight: 600;
}

.md-top:is(:focus, :hover) {
  background-color: var(--ui-button-bg-hover);
  border-color: var(--ui-accent);
  color: var(--ui-text-primary);
}

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

.md-footer {
  border-top: 1px solid var(--ui-border-subtle);
}

.md-footer__direction {
  color: var(--ui-text-muted);
  font-size: 0.6rem;
  font-weight: 600;
  opacity: 1;
}

.md-footer__title {
  font-weight: 650;
}

.md-footer__link:is(:focus, :hover) {
  color: var(--ui-accent);
  opacity: 1;
}

.md-footer-meta {
  background-color: var(--ui-bg-raised);
  border-top: 1px solid var(--ui-border-subtle);
}

.md-copyright {
  color: var(--ui-text-muted);
  font-size: 0.6rem;
}

/* -------------------------------------------------------- Section strips */

/*
 * Set per heading with attr_list ({ .ui-strip data-index="01" data-note="..." }), so anchors and the table of contents
 * keep working. Strips run from frame to frame: they cancel the gutter and insets and add them back as padding.
 */
.md-typeset h2.ui-strip {
  align-items: center;
  /* The page's own surface between two rules, as on the EnergyAtlas sites (spec 0.11). */
  background-color: transparent;
  border-bottom: 1px solid var(--ui-border-subtle);
  border-top: 1px solid var(--ui-border-subtle);
  color: var(--ui-text-primary);
  display: flex;
  font-size: 0.6rem;
  font-weight: 600;
  gap: 0.5rem;
  letter-spacing: 0;
  line-height: 1.3;
  margin: 2.8rem calc(-1 * (var(--ui-gutter) + var(--ui-inset-right))) 1.4rem
    calc(-1 * (var(--ui-gutter) + var(--ui-inset-left)));
  max-width: none;
  min-height: 1.6rem;
  padding: 0.35rem calc(var(--ui-gutter) + var(--ui-inset-right)) 0.35rem calc(var(--ui-gutter) + var(--ui-inset-left));
  position: relative;
}

.md-typeset h2.ui-strip[data-index]::before {
  color: var(--ui-text-muted);
  content: attr(data-index) "\00a0/";
  font-family: var(--font-mono);
  font-weight: 500;
}

.md-typeset h2.ui-strip[data-note]::after {
  color: var(--ui-text-muted);
  content: attr(data-note);
  font-weight: 400;
  margin-left: auto;
  text-align: right;
}

.md-typeset h2.ui-strip .headerlink {
  margin-left: 0;
}

/* A strip followed directly by a grid shares its bottom rule with the grid. */
.md-typeset h2.ui-strip + .grid {
  border-top: 0;
  margin-top: -1.4rem;
}

@media screen and (max-width: 44.984375em) {
  .md-typeset h2.ui-strip[data-note]::after {
    display: none;
  }
}

/* ------------------------------------------------------- Grids of cells */

/*
 * Material's `grid cards` markup as one shared-border grid. The outer div draws the top and bottom rules frame to frame;
 * the list is the grid (inset like the text) and clips each cell's right and bottom rule, so only internal rules show.
 */
.md-typeset .grid.cards {
  border-bottom: 1px solid var(--ui-border-subtle);
  border-top: 1px solid var(--ui-border-subtle);
  display: block;
  margin: 1.4rem calc(-1 * (var(--ui-gutter) + var(--ui-inset-right))) 1.4rem
    calc(-1 * (var(--ui-gutter) + var(--ui-inset-left)));
  max-width: none;
  padding: 0 var(--ui-inset-right) 0 var(--ui-inset-left);
}

.md-typeset .grid.cards > :is(ul, ol) {
  counter-reset: ui-cell;
  display: grid;
  gap: 0;
  grid-template-columns: 1fr;
  list-style: none;
  margin: 0;
  overflow: hidden;
  padding: 0;
}

/* As many columns of at least 14rem as fit: the landing's two cells share a row, a reading order runs three or four. */
@media screen and (min-width: 30em) {
  .md-typeset .grid.cards > :is(ul, ol) {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  }
}

/* Where an empty sidebar margin moves the grid in from the frame, the grid closes its outer edges with its own rules. */
@media screen and (min-width: 76.25em) {
  .md-sidebar--primary[hidden] ~ .md-content .md-typeset .grid.cards > :is(ul, ol) {
    border-left: 1px solid var(--ui-border-subtle);
    margin-left: -1px;
  }

  .md-sidebar--secondary[hidden] ~ .md-content .md-typeset .grid.cards > :is(ul, ol) {
    border-right: 1px solid var(--ui-border-subtle);
    margin-right: -1px;
  }
}

.md-typeset .grid.cards > :is(ul, ol) > li {
  border: 0;
  border-radius: 0;
  box-shadow: 1px 0 0 var(--ui-border-subtle), 0 1px 0 var(--ui-border-subtle);
  counter-increment: ui-cell;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 1rem var(--ui-gutter) 1.2rem;
  position: relative;
  transition: background-color var(--ui-transition);
}

.md-typeset .grid.cards > :is(ul, ol) > li:is(:hover, :focus-within) {
  background-color: var(--ui-bg-hover);
  border-color: transparent;
  box-shadow: 1px 0 0 var(--ui-border-subtle), 0 1px 0 var(--ui-border-subtle);
}

/* A cell whose title is a link is a link as a whole; other links in the cell stay above it with their own targets. */
.md-typeset .grid.cards > :is(ul, ol) > li > p:first-of-type > a:only-of-type::after {
  content: "";
  inset: 0;
  position: absolute;
}

.md-typeset .grid.cards > :is(ul, ol) > li a:not(p:first-of-type > a:only-of-type) {
  position: relative;
  z-index: 1;
}

.md-typeset .grid.cards > :is(ul, ol) > li:has(> p:first-of-type > a:only-of-type):hover > p:first-of-type > a {
  color: var(--ui-accent);
}

/* The stretched link gives the cell its focus ring. */
.md-typeset .grid.cards > :is(ul, ol) > li > p:first-of-type > a:only-of-type:focus-visible {
  outline: none;
}

.md-typeset .grid.cards > :is(ul, ol) > li > p:first-of-type > a:only-of-type:focus-visible::after {
  outline: 2px solid var(--ui-accent);
  outline-offset: -2px;
}

/* The cell index: A, B, C in a list; 01, 02, 03 in a numbered list. */
.md-typeset .grid.cards > :is(ul, ol) > li::before {
  color: var(--ui-text-muted);
  content: counter(ui-cell, upper-alpha);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 500;
  margin-bottom: 0.8rem;
}

.md-typeset .grid.cards > ol > li::before {
  content: counter(ui-cell, decimal-leading-zero);
}

.md-typeset .grid.cards > :is(ul, ol) > li > :first-child {
  margin-top: 0;
}

.md-typeset .grid.cards > :is(ul, ol) > li > p {
  font-size: 0.7rem;
  margin: 0;
  max-width: 34rem;
}

/* The first line of a cell is its title. */
.md-typeset .grid.cards > :is(ul, ol) > li > p:first-of-type {
  color: var(--ui-text-primary);
  font-size: 0.85rem;
  font-weight: 650;
  letter-spacing: -0.01em;
  line-height: 1.25;
  margin-bottom: 0.4rem;
}

.md-typeset .grid.cards > :is(ul, ol) > li > p:first-of-type a {
  color: inherit;
}

/* The landing's part cells are larger, as on the EnergyAtlas sites; reading orders (numbered) stay compact. */
.md-typeset .grid.cards > ul > li {
  padding: 1.4rem var(--ui-gutter) 1.6rem;
}

.md-typeset .grid.cards > ul > li > p:first-of-type {
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin-bottom: 0.6rem;
}

.md-typeset .grid.cards > ol > li > p:first-of-type {
  font-size: 0.95rem;
}

/* A cell's button sits at its foot, so the buttons of a row line up. */
.md-typeset .grid.cards > :is(ul, ol) > li > p:last-child:has(> .md-button) {
  margin-top: auto;
  padding-top: 1.2rem;
}

.md-typeset .grid.cards > :is(ul, ol) > li > p:first-of-type a:is(:focus, :hover) {
  color: var(--ui-accent);
}

/* ------------------------------------------------------ Product landing page */

/*
 * The landing page is a product page in the manner of energyatlas.io (design/docs-ui-spec.md, 0.7). It opens on the film
 * alone, letterboxed in black; the header, its section links and the hero appear as the page scrolls. Its content is
 * wrapped in .ui-product, and every rule that changes the page's chrome keys on it, so instant navigation (which swaps
 * only the content) never leaves the header or the frame out of step.
 */
[data-md-color-scheme="slate"] {
  --ui-media-glow: rgb(255 255 255 / 22%);
}

[data-md-color-scheme="default"] {
  --ui-media-glow: rgb(0 0 0 / 35%);
}

/* The header lies over the page, hidden while the film fills the screen; any scroll, or focus inside it, brings it in. */
body:has(.ui-product) .md-header {
  left: 0;
  position: fixed;
  right: 0;
  top: 0;
  transform: translateY(-100%);
  transition: transform 200ms ease;
}

:root[data-ui-scrolled] body:has(.ui-product) .md-header,
body:has(.ui-product) .md-header:focus-within {
  transform: none;
}

body:has(.ui-product) .md-tabs {
  display: none;
}

/* The header keeps the wordmark: Material would swap in the page's navigation title ("Home") under the headline. */
body:has(.ui-product) .md-header__title--active .md-header__topic:first-child {
  opacity: 1;
  pointer-events: auto;
  transform: none;
  z-index: 0;
}

body:has(.ui-product) .md-header__title--active .md-header__topic + .md-header__topic {
  opacity: 0;
  pointer-events: none;
}

/* The header's links return to the top; Material's back-to-top button would sit over the hero. */
body:has(.ui-product) .md-top {
  display: none;
}

/* No page frame and no rules on the product page. The page, not the content column, clips what the screenshots'
   glow spills sideways, so the glow is never cut at the column's edge. */
body:has(.ui-product) .md-content {
  border: 0;
}

body:has(.ui-product) .md-main {
  overflow-x: clip;
}

/* The section links in the header line. */
.ui-product-nav {
  display: none;
}

@media screen and (min-width: 60em) {
  body:has(.ui-product) .ui-product-nav {
    align-items: center;
    display: flex;
    gap: 1.2rem;
    margin: 0 0.8rem;
  }
}

.ui-product-nav a {
  color: var(--ui-text-muted);
  font-size: 0.65rem;
  font-weight: 600;
  transition: color var(--ui-transition), border-color var(--ui-transition);
  white-space: nowrap;
}

.ui-product-nav a:is(:focus, :hover) {
  color: var(--ui-text-primary);
}

.ui-product-nav a.ui-product-nav__download {
  border: 1px solid var(--ui-border-interactive);
  color: var(--ui-text-primary);
  padding: 0.25rem 0.6rem;
}

.ui-product-nav a.ui-product-nav__download:is(:focus, :hover) {
  border-color: var(--ui-accent);
}

/* The opening: the film fills the window; what the film does not cover is black. No frame, no caption. */
.ui-opening {
  align-items: center;
  background-color: #000000;
  display: flex;
  height: 100vh;
  height: 100svh;
  justify-content: center;
  scroll-margin-top: 0;
}

.ui-opening {
  position: relative;
}

.ui-opening video {
  background-color: #000000;
  border: 0;
  cursor: pointer;
  display: block;
  height: 100%;
  object-fit: contain;
  outline: 0;
  width: 100%;
}

/* The film fades out when it ends or is skipped, and back in when the page returns to it. */
.ui-opening video {
  transition: opacity 700ms ease;
}

.ui-opening[data-state="faded"] video {
  opacity: 0;
}

/* While the page waits for the film, it does not scroll (opening.js holds it once per session). */
:root[data-ui-film-hold],
:root[data-ui-film-hold] body {
  overflow: hidden;
}

.ui-opening video:focus-visible {
  outline: 2px solid var(--ui-accent);
  outline-offset: -2px;
}

/* The film has no player controls. While the page waits for it, trying to scroll shows Skip. The opening is always black,
   so the button keeps light-on-black colours in both themes. */
.ui-film-skip {
  background-color: rgb(0 0 0 / 60%);
  border: 1px solid rgb(255 255 255 / 55%);
  bottom: 2.4rem;
  color: #ffffff;
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: 600;
  left: 50%;
  padding: 0.5rem 1.2rem;
  position: absolute;
  transform: translateX(-50%);
  transition: border-color var(--ui-transition), background-color var(--ui-transition);
}

.ui-film-skip[hidden] {
  display: none;
}

.ui-film-skip:is(:focus-visible, :hover) {
  background-color: rgb(0 0 0 / 80%);
  border-color: #ffffff;
}

.ui-film-skip:focus-visible {
  outline: 2px solid var(--ui-accent);
  outline-offset: 2px;
}

/* The hero stays still under the header for a short scroll (its stage is taller than it), then moves on with the page. */
.md-typeset .ui-hero-stage::after {
  content: "";
  display: block;
  height: 30vh;
}

.md-typeset .ui-hero {
  container-type: inline-size;
  padding: 2.4rem 0 1.6rem;
  position: sticky;
  top: 2.4rem;
}

.md-typeset .ui-hero h1 {
  font-size: clamp(2.6rem, 11cqi, 4.6rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  margin: 0 0 0.8rem;
  max-width: none;
}

.md-typeset .ui-hero h1 .headerlink {
  display: none;
}

.md-typeset .ui-hero p {
  color: var(--ui-text-secondary);
  font-size: 0.85rem;
  line-height: 1.55;
  margin: 0 0 1.4rem;
  max-width: 36rem;
}

/* The serif italic (spec 0.4): the hero's tagline, the closing line and the feature leads. */
.md-typeset p.ui-tagline {
  color: var(--ui-text-primary);
  font-family: var(--font-serif);
  font-size: clamp(1.4rem, 4.4cqi, 2.1rem);
  font-style: italic;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.15;
  margin: 0 0 1.4rem;
  max-width: none;
}

.md-typeset p.ui-tagline em {
  font-style: inherit;
}

.md-typeset :is(.ui-hero, .ui-closing) p:last-child {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0;
}

/* Feature rows: a title, then a real screenshot beside its icon, lead and three points. */
.md-typeset :is(.ui-features, #documentation) {
  scroll-margin-top: 3.2rem;
}

.md-typeset h3.ui-feature-title {
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 3.2rem 0 1.2rem;
  scroll-margin-top: 3.2rem;
}

.md-typeset h3.ui-feature-title .headerlink {
  display: none;
}

.md-typeset .ui-feature {
  align-items: center;
  display: grid;
  gap: 1.2rem 2.4rem;
  grid-template-columns: minmax(0, 1fr);
  margin: 0 0 1.2rem;
}

@media screen and (min-width: 60em) {
  .md-typeset .ui-feature {
    grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  }

  /* The local-and-read-only row has no picture: its icon stands beside the text. */
  .md-typeset .ui-feature--plain {
    align-items: start;
    grid-template-columns: auto minmax(0, 1fr);
  }
}

.md-typeset .ui-feature > p {
  margin: 0;
}

/* Screenshots as on energyatlas.io: all 16:9, rounded at the top, a soft glow, fading out towards the bottom. The
   paragraph around each one makes room for the glow and carries the fade. */
.md-typeset .ui-feature > p:has(> img.ui-feature__media) {
  /* At least the glow's blur plus its spread, so the mask never cuts the glow's edge. */
  --ui-glow-space: 4rem;
  margin: calc(-1 * var(--ui-glow-space));
  mask-image: linear-gradient(to bottom, #000000 calc(78% - var(--ui-glow-space) / 2), transparent calc(100% - var(--ui-glow-space)));
  padding: var(--ui-glow-space);
}

.md-typeset img.ui-feature__media {
  aspect-ratio: 16 / 9;
  border-radius: 1rem 1rem 0 0;
  box-shadow: 0 0 3rem 4px var(--ui-media-glow);
  display: block;
  object-fit: cover;
  object-position: top left;
  width: 100%;
}

/* Each screenshot comes in both themes (`#only-light`, `#only-dark`, Material's markers); the page shows the one of its
   own theme. Restated here because `display: block` above outranks Material's own rule. */
[data-md-color-scheme="default"] .md-typeset img.ui-feature__media[src$="#only-dark"],
[data-md-color-scheme="slate"] .md-typeset img.ui-feature__media[src$="#only-light"] {
  display: none;
}

.md-typeset .ui-feature__text ul {
  margin: 0.4rem 0 0;
}

.md-typeset .ui-feature__text li {
  font-size: 0.75rem;
  margin-bottom: 0.3rem;
}

.md-typeset p.ui-feature__lead {
  color: var(--ui-text-primary);
  font-family: var(--font-serif);
  font-size: 1.25rem;
  font-style: italic;
  font-weight: 500;
  line-height: 1.2;
  margin: 0.8rem 0 0.6rem;
}

.md-typeset p.ui-feature__lead em {
  font-style: inherit;
}

/* The hand-drawn icons (design/icons/): ink in the text colour, the one accent mark in the theme's accent. */
.md-typeset .ui-icon {
  color: var(--ui-text-primary);
  display: block;
  height: 3.6rem;
  width: 3.6rem;
}

.md-typeset :is(.ui-icon, .ui-icon-backdrop) svg {
  display: block;
  height: 100%;
  overflow: visible;
  width: 100%;
}

.md-typeset .ui-icon .ink {
  fill: currentColor;
}

.md-typeset .ui-icon .accent {
  fill: var(--ui-accent);
  transform-box: fill-box;
  transform-origin: center;
}

/* Documentation cards as energyatlas.io's product cards: no rules; an icon, an underlined title and a short text; on
   hover a torn-paper wash sweeps in with a faint, oversized copy of the icon, and the icon's accent pulses. */
.md-typeset .ui-cards {
  display: grid;
  gap: 0;
  grid-template-columns: minmax(0, 1fr);
  margin: 3.2rem 0 0;
}

@media screen and (min-width: 45em) {
  .md-typeset .ui-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.md-typeset a.ui-card {
  color: var(--ui-text-primary);
  display: flex;
  flex-direction: column;
  isolation: isolate;
  min-height: 15rem;
  padding: 1.8rem 1.6rem;
  position: relative;
  text-decoration: none;
}

.md-typeset a.ui-card .ui-icon {
  height: 4rem;
  margin-bottom: 1.4rem;
  width: 4rem;
}

.md-typeset .ui-card__title {
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.25em;
}

.md-typeset .ui-card__mark {
  color: var(--ui-accent);
  display: inline-block;
  text-decoration: none;
}

.md-typeset .ui-card__text {
  color: var(--ui-text-secondary);
  font-size: 0.7rem;
  line-height: 1.55;
  margin-top: 0.6rem;
  max-width: 26rem;
}

.md-typeset .ui-card__wash {
  background: linear-gradient(140deg, transparent 30%, color-mix(in srgb, var(--ui-accent) 16%, transparent) 100%),
    color-mix(in srgb, var(--ui-text-primary) 8%, transparent);
  clip-path: inset(0 100% 0 0);
  inset: 0;
  mask-image: url("../shapes/card-wash.svg");
  mask-repeat: no-repeat;
  mask-size: 100% 100%;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  position: absolute;
  transform: translate(2px, -2px) rotate(-1.6deg) scale(1.03, 1.04);
  z-index: -1;
}

.md-typeset a.ui-card:nth-child(2) .ui-card__wash {
  transform: translate(-2px, 3px) rotate(1.8deg) scale(1.04, 1.03);
}

.md-typeset .ui-icon-backdrop {
  aspect-ratio: 1;
  left: 72%;
  opacity: 0.14;
  position: absolute;
  top: 70%;
  transform: translate(-50%, -50%);
  width: 70%;
}

.md-typeset .ui-icon-backdrop :is(.ink, .accent) {
  fill: var(--ui-accent);
}

.md-typeset a.ui-card:is(:hover, :focus-visible) .ui-card__wash {
  animation: ui-wash-sweep 240ms linear both;
  opacity: 1;
}

.md-typeset a.ui-card:is(:hover, :focus-visible) .ui-card__title {
  text-decoration-thickness: 2px;
}

.md-typeset a.ui-card:focus-visible {
  outline: 2px solid var(--ui-accent);
  outline-offset: -2px;
}

@media (hover: hover) and (pointer: fine) {
  .md-typeset a.ui-card:hover .ui-icon .accent {
    animation: ui-icon-pulse 1.2s ease-in-out infinite;
  }
}

@keyframes ui-wash-sweep {
  from {
    clip-path: inset(0 100% 0 0);
  }

  to {
    clip-path: inset(0 0 0 0);
  }
}

@keyframes ui-icon-pulse {
  0%,
  100% {
    transform: scale(1);
  }

  50% {
    transform: scale(1.18);
  }
}

/* The closing call to action. */
.md-typeset .ui-closing {
  container-type: inline-size;
  padding: 3.2rem 0 2.4rem;
}

/* -------------------------------------------------------------- Motion */

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}
