/* The site's own styles, for what unfold's compiled classes cannot express.
 *
 * Every other style on the site is a class that unfold compiled. The template
 * class check enforces that, and it reads this file too. A rule earns a place
 * here only where a class cannot do the job, such as a pseudo-element or a
 * transition from `display: none`. A utility that unfold left out also earns
 * a rule, where a template asks for it by name. Such a rule takes Tailwind's
 * name for the utility, so the two agree if unfold compiles it later.
 *
 * This file loads before unfold's stylesheet. A rule here that ties with one
 * of unfold's on specificity loses.
 */

/* A changelist's row links read as links, with an underline and the
 * open-in-new glyph from the icon font unfold loads. Unfold paints the link
 * `text-important`, the colour of the text around it, so nothing else marks
 * it as a link.
 *
 * A `@display(header=True)` column puts a `<strong>` title and a `<p>` caption
 * in one link. There, only the title gets the style. Otherwise the underline
 * runs through the caption and the glyph goes onto a line of its own. */
#result_list a.text-important:not(:has(strong)),
#result_list a.text-important strong {
  text-decoration: underline;
  text-decoration-color: color-mix(in oklch, currentColor 40%, transparent);
  text-underline-offset: 3px;
}

#result_list a.text-important:hover:not(:has(strong)),
#result_list a.text-important:hover strong {
  text-decoration-color: currentColor;
}

#result_list a.text-important:not(:has(strong))::after,
#result_list a.text-important strong::after {
  content: "open_in_new";
  font-family: "Material Symbols Outlined";
  font-size: 0.875em;
  line-height: 1;
  margin-left: 0.25em;
  vertical-align: -0.1em;
}

/* A sidebar group's list eases in when the group opens. Alpine's `x-show`
 * changes `display`, and only `@starting-style` lets a transition start from
 * `display: none`. Closing stays instant. Alpine sets `display: none` before a
 * transition can run, so an animation on close needs a change to the group's
 * markup, not a rule. */
ol[x-show="navigationOpen || filter"] {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 150ms ease-out,
    transform 150ms ease-out,
    display 150ms allow-discrete;

  @starting-style {
    opacity: 0;
    transform: translateY(-0.25rem);
  }
}

/* List markers. Tailwind's preflight removes them, and unfold compiled no
 * `list-*` utility. Without these rules, a set of rules or a numbered
 * procedure must write its own bullets or digits. Indent with `pl-*`, which
 * unfold did compile. */
.list-disc {
  list-style-type: disc;
}

.list-decimal {
  list-style-type: decimal;
}

/* A stacking context for the preview tables. Unfold does not compile
 * `isolate`, and the templates use it. The sticky `<thead>` of a table is
 * `z-100` and the sidebar is `z-60`. Both values are unfold's. Without a
 * stacking context, the header paints over the sidebar below `xl`. */
.isolate {
  isolation: isolate;
}

/* The sidebar slides in and out. It does not appear and vanish. Unfold shows
 * and hides it with `x-show` on a wrapper, and sets the wrapper's width
 * inline. A transition from `display: none` needs `@starting-style`, which
 * also runs the slide on every page load. So the wrapper stays rendered.
 *
 * These rules find Alpine's inline `display: none` by attribute and override
 * it. A closed wrapper has no width. The wrapper is a spacer beside the
 * content, so its width moves the page. The panel, `#nav-sidebar`, is fixed
 * inside the wrapper. When the sidebar closes, the panel slides off to the
 * left and is hidden from focus. The open width and the `display` are inline
 * styles, so the override needs `!important`. No transition runs at first
 * paint, so a page loads with the sidebar where it was. */
div:has(> div > #nav-sidebar) {
  transition: width 200ms ease-out;
}

div:has(> div > #nav-sidebar)[style*="display: none"] {
  display: block !important;
  width: 0 !important;
}

#nav-sidebar {
  transition:
    transform 200ms ease-out,
    visibility 200ms;
}

div[style*="display: none"] > div > #nav-sidebar {
  transform: translateX(-100%);
  visibility: hidden;
}

/* A grid header cell keeps its primary tint in dark mode. Unfold's table
 * component paints every `<th>` `dark:bg-white/[.02]`. That rule comes later
 * in unfold's stylesheet than `dark:bg-primary-500/20`, so the grid's tint
 * loses the tie on a `<th>`. This selector matches the cell by both, so its
 * higher specificity wins. The value is the one unfold's utility paints. */
.dark th[class~="dark:bg-primary-500/20"] {
  background-color: color-mix(in oklab, var(--color-primary-500) 20%, transparent);
}

/* An explainer is a native `<dialog>`. The browser centres an open dialog
 * with `margin: auto`. Tailwind's preflight sets every margin to zero, so this
 * rule puts the margin back. No class reaches the backdrop, because it is a
 * pseudo-element. It gets the tint and the blur of unfold's own modal
 * overlay. */
dialog {
  margin: auto;
}
dialog::backdrop {
  background-color: rgb(0 0 0 / 0.2);
  backdrop-filter: blur(4px);
}
.dark dialog::backdrop {
  background-color: rgb(0 0 0 / 0.6);
}

/* A popover takes the colour of the text around it. The browser paints a
 * popover's text `CanvasText`, which follows `color-scheme`. Unfold's dark
 * mode is a `.dark` class and leaves `color-scheme` at `normal`, so in dark
 * mode that text is black on a dark panel. */
[popover] {
  color: inherit;
}

/* A column filter opens under its head's button, with their left edges in
 * line, as unfold's dropdowns do. Near an edge of the window it flips. Only
 * one filter is open at a time, and `sortAndFilter` marks its button
 * `aria-expanded`, so one anchor name serves every head. A browser without
 * anchor positioning centres the filter in the window. */
[data-filter-head][aria-expanded="true"] {
  anchor-name: --open-filter;
}

th > form[popover] {
  margin: auto;

  @supports (anchor-name: --a) {
    position-anchor: --open-filter;
    position-area: bottom span-right;
    position-try-fallbacks: flip-inline, flip-block, flip-block flip-inline;
    inset: auto;
    margin: 0.25rem 0 0;
  }
}

/* The Loader Lens row menu opens under its Actions button, with their right
 * edges in line, as unfold's row actions menu does. It is placed as a
 * column filter is. */
[data-actions][aria-expanded="true"] {
  anchor-name: --open-row-menu;
}

nav[popover][aria-label="Actions"] {
  margin: auto;

  @supports (anchor-name: --a) {
    position-anchor: --open-row-menu;
    position-area: bottom span-left;
    position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
    inset: auto;
    margin: 0.25rem 0 0;
  }
}

/* A Config Tweaker help panel opens under its `info` button, with their left
 * edges in line, or their right edges with `data-align="end"`. No script marks
 * the open button, so `:has` finds it by the open panel after it. */
[popovertarget]:has(+ :popover-open) {
  anchor-name: --open-help;
}

[popovertarget] + div[popover] {
  margin: auto;

  @supports (anchor-name: --a) {
    position-anchor: --open-help;
    position-area: bottom span-right;
    position-try-fallbacks: flip-inline, flip-block, flip-block flip-inline;
    inset: auto;
    margin: 0.25rem 0 0;
  }
}

[popovertarget] + div[popover][data-align="end"] {
  @supports (anchor-name: --a) {
    position-area: bottom span-left;
  }
}

/* A column filter's list of values scrolls when a column has many values,
 * such as Provider. Unfold compiled no `max-h` of this size. */
.max-h-64 {
  max-height: 16rem;
}

/* The Loader Lens files dialog marks a file that arrived but did not load.
 * Unfold compiles no yellow background. */
.bg-yellow-500 {
  background-color: var(--color-yellow-500);
}

/* A table box as tall as the window, less the toolbar above it. */
.max-h-\[calc\(100vh-4rem\)\] {
  max-height: calc(100vh - 4rem);
}

/* A sticky head loses the border under its row, because a collapsed border
 * belongs to the table, not to the cell. A shadow moves with the cell. */
thead.sticky th {
  box-shadow: inset 0 -1px 0 var(--color-base-200);
}
.dark thead.sticky th {
  box-shadow: inset 0 -1px 0 var(--color-base-800);
}

/* The Loader Lens dims its body while htmx fetches a new list.
 * htmx marks the request with a class that no utility can match. */
#loader-lens-body.htmx-request {
  opacity: 0.5;
  transition: opacity 150ms ease-out;
}

/* The Loader Lens strip is an SVG. Unfold compiles no stroke colours. */
.stroke-green-500 {
  stroke: var(--color-green-500);
}
.stroke-yellow-500 {
  stroke: var(--color-yellow-500);
}
.stroke-red-500 {
  stroke: var(--color-red-500);
}
.stroke-base-300 {
  stroke: var(--color-base-300);
}
.dark .dark\:stroke-base-600 {
  stroke: var(--color-base-600);
}
