/* style.css */

:root {
  /* Color palette */
  /* #121212 */
  --bg-1: rgb(18, 18, 18);
  /* #080A0F */
  --page-bg: rgb(0, 10, 15);
  /* #2E7BE4 */
  --accent: rgb(46, 123, 228);
  /* #4893FF */
  --accent-hover: rgb(72, 147, 255);
  /* #D08700 */
  --highlight: rgb(208, 135, 0);
  /* #E1A700 */
  --highlight-hover: rgb(225, 167, 0);
  /* Developer marker. Deliberately not a tint of the accent or of the highlight: it has to be told
     apart from both at a glance, which is what makes it a third signal color. */
  /* #E24E9E */
  --developer: rgb(226, 78, 158);
  /* #FF6FBB */
  --developer-hover: rgb(255, 111, 187);

  /* #E0E0E0 */
  --text-primary: rgb(224, 224, 224);
  /* #090E14 */
  --readonly-bg: rgb(9, 14, 20);
  --panel-bg: rgba(255, 255, 255, 0.02);
  --panel-border: rgba(255, 255, 255, 0.12);

  /* Typography & layout */
  --radius: 6px;
  /* Uniform height for form controls (inputs, button-style radios, selects)
     and the read-only note fields ("No components selected." etc.). The WA
     token is overridden here so all wa-* controls follow the same height. */
  --control-height: 1.88rem;
  --wa-form-control-height: var(--control-height);
  font-family: "Inter", sans-serif;
  font-size: clamp(14px, 1.1vw, 17px);
}

/* -------------------------------------------------------------------------- */
/* Global                                                                      */
/* -------------------------------------------------------------------------- */

html,
body {
  margin: 0;
  padding: 0;
  line-height: 1.5;
}

body {
  font-size: 0.95rem;
}

/* Headings: add vertical spacing above (esp. for h2) */
h1 {
  font-size: 1.8rem;
  margin: 0.6rem 0 0.8rem 0;
}

h2 {
  font-size: 1.4rem;
  margin: 1.35rem 0 0.6rem 0;
}

h3 {
  font-size: 1rem;
  margin: 1.0rem 0 0.5rem 0;
}

/* Without an explicit rule h4 inherits a larger size than h3 and inverts the hierarchy. */
h4 {
  font-size: 0.92rem;
  margin: 0.85rem 0 0.4rem 0;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  color: var(--accent);
}

.nowrap {
  white-space: nowrap;
}

/* MathJax block */
.math {
  font-size: 0.95rem;
  overflow-x: auto;
}

/* Emphasized equation block (the target equation of the model): quiet accent tint and frame. */
.math-framed {
  margin: 1.25rem 0;
  padding: 0.1rem 1rem;
  background-color: rgba(46, 123, 228, 0.07);
  border: 1px solid rgba(46, 123, 228, 0.45);
  border-radius: var(--radius);
}

/* -------------------------------------------------------------------------- */
/* Page container                                                              */
/* -------------------------------------------------------------------------- */

.page-container {
  width: min(95vw, 840px);
  margin: 2rem auto;
  padding: 1rem 1.5rem;
  background: var(--page-bg);
  border-radius: var(--radius);
}

.page-topline {
  display: flex;
  justify-content: flex-end;
}

.build-info {
  font-size: 0.72rem;
  color: rgba(224, 224, 224, 0.55);
  text-align: right;
  /* Two right-aligned lines, commit above build time. The line break is a newline in the text
     rather than an element, so `pre-line` is what makes it render. */
  white-space: pre-line;
  line-height: 1.35;
}

/* The developer-mode marker is the one part of the badge that has to be noticed, since it announces
   that the page shows solver internals. It takes `--developer`, the same color as the badges on the
   individual developer-only widgets, so that the header states the mode in the color those badges
   then repeat. */
.build-info-dev {
  color: var(--developer-hover);
}

/* -------------------------------------------------------------------------- */
/* Global loading overlay                                                      */
/* -------------------------------------------------------------------------- */

.page-spinner {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-1);
  transition: opacity 0.2s ease;
}

.page-spinner.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.page-spinner-dial {
  width: 2.5rem;
  height: 2.5rem;
  border: 3px solid var(--panel-border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: page-spinner-turn 0.8s linear infinite;
}

@keyframes page-spinner-turn {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-spinner-dial {
    animation-duration: 2.4s;
  }
}

/* -------------------------------------------------------------------------- */
/* Tab navigation                                                              */
/* -------------------------------------------------------------------------- */

#mainTabs {
  /* No track and no active-tab indicator: the orange backing below already marks the active tab,
     and the strip under the bar competed with it. */
  --track-width: 0;
  margin-top: 0.5rem;
}

/* Both tab strips: the section tabs, and the flash/DGT tabs inside the simulation panel. They are
   styled as one so the two levels cannot drift apart. The filled tab marks the selection by
   itself, so the component's own indicator track would only draw a second, competing rule
   underneath it. */
#mainTabs,
#simModeTabs {
  --track-width: 0;
}

/* Both tab strips use the same control-bar treatment: orange background, compact padding, and a
   visible frame so they read as navigation instead of plain text. */
#mainTabs,
#simModeTabs {
  margin-top: 0.25rem;
  margin-bottom: 1rem;
  --tab-frame-width: 1px;
  padding: 0;
  border: var(--tab-frame-width) solid var(--highlight);
  border-radius: var(--radius);
  background: transparent;
}

/* The strip is a band rather than bare text, so that it reads as the divider between the heading
   above it and the panel below. */
#mainTabs::part(tabs),
#simModeTabs::part(tabs) {
  background: transparent;
  border: 0;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
  border-radius: var(--radius);
  overflow: hidden;
  margin: calc(-1 * var(--tab-frame-width)) calc(-1 * var(--tab-frame-width)) 0 calc(-1 * var(--tab-frame-width));
  padding: 0;
  border-bottom: none;
}

/* Keep the bars compact: the WebAwesome default padding makes them about twice as tall as they
   need to be for one-line labels. */
#mainTabs wa-tab::part(base),
#simModeTabs wa-tab::part(base) {
  padding: 0.34rem 0.9rem;
  margin: 0;
  font-size: 0.98rem;
  letter-spacing: 0.01em;
  color: #fff;
  border-radius: var(--radius);
}

#simModeTabs wa-tab[active]::part(base),
#simModeTabs wa-tab[aria-selected='true']::part(base),
#simModeTabs wa-tab:hover::part(base) {
  color: #fff !important;
}

#mainTabs wa-tab:hover::part(base),
#simModeTabs wa-tab:hover::part(base) {
  background: rgba(208, 135, 0, 0.18);
  border-radius: var(--radius);
}

/* Both tab strips use white text on the highlighted tab for consistency and readability. */
#mainTabs wa-tab[active]::part(base),
#mainTabs wa-tab[aria-selected='true']::part(base) {
  background: var(--highlight);
  color: #fff !important;
  font-weight: 600;
  border-radius: var(--radius);
}

#simModeTabs wa-tab[active]::part(base),
#simModeTabs wa-tab[aria-selected='true']::part(base) {
  background: var(--highlight);
  color: #fff !important;
  font-weight: 600;
  border-radius: var(--radius);
}

/* The two ways a tab reports being selected have to be excluded together: the nested group marks
   its selection through `aria-selected` alone, so testing `active` by itself would let the hover
   tint paint over the fill of the very tab that is open. */
#mainTabs wa-tab:not([active]):not([aria-selected='true']):hover::part(base),
#simModeTabs wa-tab:not([active]):not([aria-selected='true']):hover::part(base) {
  background: rgba(255, 255, 255, 0.06);
  border-radius: var(--radius);
}

/* Main section panels: add a little room below the top tab bar, but do not force a flex layout,
   otherwise a synthetic gap appears between the heading and the form (`Configuration`/`Examples`). */
#mainTabs wa-tab-panel::part(base) {
  padding-top: 0.55rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

/* The nested simulation-mode panels keep a flex column so their internal rows stay evenly spaced,
   and get the same top inset below the Flash/DGT tab bar. */
#simModeTabs wa-tab-panel::part(base) {
  display: flex;
  flex-direction: column;
  gap: 1.15rem;
  padding-top: 0.55rem;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

/* The Run/Cancel row is the first action block in the DGT panel, so give it a little breathing
   room under the mode tabs. */
#simModeTabs wa-tab-panel[name='dgt'] .results-actions:first-of-type {
  margin-top: 0.25rem;
}

/* A tab hidden with the `hidden` attribute has to actually disappear.
   `wa-tab` sets its own `display` on `:host`, and an author rule in a shadow root outranks the
   user-agent rule `[hidden] { display: none }` — so the attribute alone leaves the tab on screen,
   full width and clickable, while its panel is correctly gone. A document-level rule outranks
   `:host` in turn, which is what this is. Written for the sweep tab, which was gated on developer
   mode and is no longer; kept because any future gate on a tab needs it to work at all. */
wa-tab[hidden] {
  display: none;
}

/* The same for a radio, and for the same reason — `wa-radio` sets its own `display` on `:host`, so
   the attribute alone leaves the choice on screen. This one gates rather than decorates: the
   two-dimensional symmetries are hidden in user mode because the backend refuses them, and a
   disabled choice still offered is a choice offered (`doc/userVisibleSurface.md`). It also carries
   the shape options, which are hidden per symmetry in `syncInitialConfigurationControlsForSymmetry`. */
wa-radio[hidden] {
  display: none;
}

/* The panels carry the page headings, which bring their own top spacing. */
wa-tab-panel>:first-child,
wa-tab-panel>section:first-child>:first-child {
  margin-top: 0;
}

/* Explicit spacing below both tab bars: apply it to the first visible block inside each panel,
   which is robust even when the component's internal parts differ by WA version. */
#mainTabs > wa-tab-panel > :first-child,
#simModeTabs > wa-tab-panel > :first-child {
  margin-top: 0.55rem;
}

/* -------------------------------------------------------------------------- */
/* Form & layout                                                               */
/* -------------------------------------------------------------------------- */

.input-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Labels */
label {
  display: block;
  margin: 0.8rem 0 0.2rem;
  font-weight: 600;
}

.label-normal {
  font-weight: 400;
}

.label-normal.has-tooltip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.label-normal.has-tooltip .tooltip-icon {
  margin-left: auto;
}

.output-label {}

.tooltip-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 0.35rem;
  width: 1.3em;
  height: 1.3em;
  border: 1px solid var(--accent);
  border-radius: 50%;
  font-size: 0.9em;
  font-weight: 700;
  line-height: 1;
  color: #fff;
  background: var(--accent);
  cursor: help;
  user-select: none;
}

.tooltip-icon:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

wa-tooltip.inline-tooltip {
  display: contents;
}

/* Being `display: contents`, a tooltip inherits the type of whatever it sits in. Attached to a
   section heading it would therefore come out in the heading's bold, while the ones on labels are
   body weight; the text is the same kind of remark in both places and should read alike. */
h2 > wa-tooltip.inline-tooltip,
h3 > wa-tooltip.inline-tooltip {
  font-weight: 400;
}

/* Layout helpers */
.two-col-grid {
  display: grid;

  /* Important: minmax(0,1fr) prevents overflow on narrow screens. */
  grid-template-columns: max-content minmax(0, 1fr);

  column-gap: 1rem;
  row-gap: 0.2rem;
  align-items: center;
}

/* Center labels against their fields; the global label margins are for the
   stacked (mobile) layout and are restored in the media query below. */
.two-col-grid>label {
  margin-block: 0;
}

/* Also apply the same overflow-safe sizing to the results grid */
.result-fields {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 1rem;
  row-gap: 0.2rem;
  margin-top: 0.75rem;
}

/* Critical for CSS grid: allow children to shrink (prevents mobile overflow) */
.two-col-grid>*,
.result-fields>* {
  min-width: 0;
}

.indent {
  margin-left: 2em;
}

.section-heading {
  margin-top: 0.5rem;
  font-weight: 400;
}

.section-heading.has-tooltip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* -------------------------------------------------------------------------- */
/* Average densities widget                                                   */
/* -------------------------------------------------------------------------- */

.avg-density-toolbar {
  margin-top: 0.5rem;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.2rem;
}

.avg-density-add-row {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  align-items: center;
  column-gap: 1rem;
  row-gap: 0.2rem;
}

.avg-density-add-label {
  /* Centered against the controls; margins return in the stacked layout. */
  margin: 0;
}

.avg-density-title-group {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
  align-self: flex-start;
}

.avg-density-heading {
  margin-top: 0;
}

.avg-density-controls {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.45rem;
  min-width: 0;
  width: 100%;
}

.avg-density-select {
  width: 100%;
  min-width: 0;
  display: block;
}

.avg-density-select::part(combobox) {
  box-shadow: none;
}

.avg-density-select:focus-within::part(combobox) {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

.avg-density-body {
  margin-top: 0.35rem;
}

.avg-density-row {
  display: grid;
  grid-template-columns: minmax(12rem, max-content) auto minmax(0, 1fr);
  column-gap: 1rem;
  row-gap: 0.2rem;
  align-items: center;
}

.avg-density-row + .avg-density-row {
  margin-top: 0.15rem;
}

.avg-density-row > * {
  min-width: 0;
}

.avg-density-row-label {
  margin: 0.8rem 0 0.2rem;
}

.avg-density-row-input {
  width: 100%;
}

.avg-density-empty-note {
  width: 100%;
  box-sizing: border-box;
  min-height: var(--control-height);
  /* Small block padding so min-height (not padding) sets the height. */
  padding: 0.15rem 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: rgba(224, 224, 224, 0.72);
  background: var(--readonly-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  box-shadow: none;
  pointer-events: none;
  user-select: none;
}

/* -------------------------------------------------------------------------- */
/* Inputs                                                                      */
/* -------------------------------------------------------------------------- */

wa-input {
  width: 100%;
  min-width: 0;
  display: block;
}

/* Focus ring: ONLY outside (no outline). */
wa-input:focus-within::part(base) {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

/* Unit suffix styling inside WA input (slotted content) */
.unit-suffix {
  color: rgba(224, 224, 224, 0.8);
  opacity: 0.9;
  font-size: 0.9em;
  padding-right: 0.1rem;
  white-space: nowrap;
}

/* Dimensionless fields: do not reserve space / do not show any separator. */
wa-input.no-unit::part(end),
wa-input.no-unit::part(suffix) {
  display: none;
}

/* Radio labels */
wa-radio::part(label) {
  color: var(--text-primary);
}

/* Checked button-style radio: quiet accent tint instead of the gray brand fill. */
wa-radio[appearance='button']:state(checked) {
  background-color: rgba(46, 123, 228, 0.22);
  border-color: var(--accent);
}

wa-radio[appearance='button']:state(checked)::part(label) {
  color: #fff;
}

.two-col-grid>wa-radio-group {
  align-self: center;
  justify-self: stretch;
  display: block;
  width: 100%;
  min-width: 0;
}

/* Force WA radio-group internals to stretch full column width */
.two-col-grid>wa-radio-group::part(base),
.two-col-grid>wa-radio-group::part(form-control),
.two-col-grid>wa-radio-group::part(control),
.two-col-grid>wa-radio-group::part(button-group) {
  width: 100%;
  min-width: 0;
  display: block;
}

.two-col-grid>wa-radio-group::part(button-group) {
  display: flex;
}

.two-col-grid>wa-radio-group wa-radio {
  flex: 1 1 0;
}

/* Symbol/input pairs for the two domain lengths that share one row. The volume they are linked to
   is a row of its own above the sub-tabs and carries its symbol in its label instead. */
.domain-size-fields {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto minmax(0, 1fr);
  column-gap: 0.5rem;
  row-gap: 0.35rem;
  align-items: center;
  width: 100%;
  min-width: 0;
}

.two-col-grid>.domain-size-fields {
  align-self: center;
  justify-self: stretch;
}

.domain-symbol {
  color: var(--text-primary);
  font-weight: 600;
  line-height: 1;
}

@media (max-width: 700px) {
  .domain-size-fields {
    grid-template-columns: auto minmax(0, 1fr);
  }
}

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

button.btn {
  margin-top: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.3rem;
  line-height: 1;
  padding: 0.4rem 1rem;

  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  font-weight: 600;
  transition: background 0.15s, opacity 0.15s;
}

button.btn:hover {
  background: var(--accent-hover);
}

wa-button.btn {
  display: inline-block;
  line-height: 1;
}

/* Make WA buttons ~50% smaller (height + padding), including internal label padding. */
wa-button.btn::part(base) {
  min-height: 1.25rem !important;
  height: auto !important;

  padding-block: 0.26rem !important;
  padding-inline: 0.5rem !important;
  line-height: 1 !important;

  border-radius: var(--radius);
  font-weight: 600;

  background: var(--accent);
  color: #fff;
  border: none;

  transition: background 0.15s, opacity 0.15s;
}

/* Remove any internal padding/margins that can dominate vertical size (varies by WA version). */
wa-button.btn::part(label),
wa-button.btn::part(content),
wa-button.btn::part(prefix),
wa-button.btn::part(suffix) {
  padding: 0 !important;
  margin: 0 !important;
  line-height: 1 !important;
}

wa-button.btn:hover::part(base) {
  background: var(--accent-hover);
}

wa-button.avg-density-icon-btn::part(base) {
  min-width: 1.7rem !important;
  width: 1.7rem !important;
  padding-inline: 0 !important;
}

button.highlight-button {
  background: var(--highlight);
  color: #fff;
}

button.highlight-button:hover {
  background: var(--highlight-hover);
}

wa-button.highlight-button::part(base) {
  background: var(--highlight);
  color: #fff;
}

wa-button.highlight-button:hover::part(base) {
  background: var(--highlight-hover);
}

button.btn.is-disabled,
button.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

wa-button.btn[disabled]::part(base) {
  opacity: 0.45;
  cursor: not-allowed;
}

.results-actions,
.button-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.example-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.example-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* `display: flex` above would otherwise defeat the `hidden` attribute that keeps the two-dimensional
   examples out of user mode (see revealDeveloperOnlyControls in js/main.js). */
.example-row[hidden] {
  display: none;
}

/* Round icon button that loads one example (see addBenchmarkButtons in js/main.js). */
wa-button.example-load-btn::part(base) {
  width: 1.7rem !important;
  height: 1.7rem !important;
  min-width: 1.7rem !important;
  min-height: 1.7rem !important;
  padding: 0 !important;
  border-radius: 50% !important;
}

/* Marks an example that loads a non-default symmetry or boundary condition (see
   EXAMPLE_BENCHMARKS in js/main.js) -- outlined like .dev-badge/.maturity-badge, in the plain
   accent color since it qualifies neither developer-only content nor an experimental feature. */
.example-variant-badge {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--accent);
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--accent-hover);
}

.file-input {
  display: none;
}

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

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  color: var(--accent-hover);
  text-decoration: underline;
}

/* -------------------------------------------------------------------------- */
/* Citations and references                                                    */
/* -------------------------------------------------------------------------- */

.cite-rendered {
  white-space: nowrap;
}

.cite-rendered .cite-link {
  font-weight: 600;
}

.cite-rendered .cite-missing {
  color: var(--highlight);
  font-weight: 700;
}

.references-list {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.reference {
  margin: 0;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  background: var(--panel-bg);
}

.reference.is-hidden,
.references-empty.is-hidden {
  display: none;
}

.reference-row {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  column-gap: 0.65rem;
}

.reference-number {
  color: var(--accent);
  font-weight: 700;
}

.reference-content {
  min-width: 0;
}

.reference-text {
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.reference-actions {
  margin-top: 0.45rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.reference-export-btn {
  min-height: 1.45rem;
  padding: 0.15rem 0.5rem;
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  background: var(--readonly-bg);
  color: var(--text-primary);
  cursor: pointer;
  font: inherit;
  font-size: 0.78rem;
  line-height: 1.2;
}

.reference-export-btn:hover {
  border-color: var(--accent);
  color: var(--accent-hover);
}

.references-empty {
  margin: 0.65rem 0;
  color: rgba(224, 224, 224, 0.75);
}

/* -------------------------------------------------------------------------- */
/* Results                                                                     */
/* -------------------------------------------------------------------------- */

.results {
  margin-top: 1.5rem;
}

.output-field {
  font: inherit;
  background: var(--readonly-bg);
  border-radius: var(--radius);
  padding: 0.25rem 0.5rem;
  user-select: text;
  pointer-events: auto;
}

.output-field:focus {
  outline: none;
}

/* Read-only output fields (WA inputs) */
wa-input.wa-output::part(base) {
  background: var(--readonly-bg);
  outline: none;
  box-shadow: none;
}

wa-input.wa-output:focus-within::part(base) {
  outline: none;
  box-shadow: none;
}

wa-input.wa-output::part(input),
wa-input.wa-output::part(control) {
  outline: none;
  box-shadow: none;
}

wa-input.wa-output:focus,
wa-input.wa-output:focus-visible {
  outline: none;
  box-shadow: none;
}

/* Rich read-only output fields (project-local element that renders MathJax/HTML, styled like wa-input). */
wa-output-rich {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  box-sizing: border-box;
  min-height: var(--wa-form-control-height, 2.5rem);
  padding: 0 var(--wa-form-control-padding-inline, 0.75rem);
  border: var(--wa-form-control-border-width, 1px) solid var(--wa-form-control-border-color, #444);
  border-radius: var(--wa-form-control-border-radius, 0.375rem);
  background: var(--readonly-bg);
  font-size: var(--wa-form-control-font-size, inherit);
  color: var(--wa-form-control-value-color, inherit);
  white-space: nowrap;
}

/* Value area of a rich output field; scrolls horizontally if the content overflows. Keep the
   vertical axis clipped: `overflow-x: auto` alone would also turn the vertical axis into a
   scroll container, and subpixel rounding of MathJax output then shows a stray vertical
   scrollbar thumb on Chrome for Android. */
wa-output-rich .rich-content {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  white-space: nowrap;
}

/* Copy-to-clipboard symbol at the right edge of a rich output field (after the unit). */
wa-output-rich .copy-button {
  flex: 0 0 auto;
  border: none;
  background: none;
  padding: 0 0.1rem;
  font: inherit;
  line-height: 1;
  color: rgba(224, 224, 224, 0.8);
  opacity: 0.9;
  cursor: pointer;
}

wa-output-rich .copy-button:hover {
  color: var(--accent-hover);
}

/* -------------------------------------------------------------------------- */
/* Plot areas                                                                  */
/* -------------------------------------------------------------------------- */

.plot-toolbar {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.4rem;
}

.plot-area .plot-toolbar {
  margin: 0 0 0.5rem 0;
}

.plot-toolbar.is-hidden {
  display: none;
}

.plot-toolbar label,
.plot-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  font-weight: 400;
}

/* A toggle a view has nothing to switch is hidden rather than offered as a dead control. It has to
   come after the rule above: both match at the same specificity, so the later one wins. */
.plot-toggle.is-hidden {
  display: none;
}

.plot-area {
  margin: 1rem auto 0 auto;
  width: 100%;
  max-width: 100%;
  border-radius: var(--radius);
  padding: 0.75rem 0.75rem 0.9rem 0.75rem;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  box-sizing: border-box;
  min-height: 520px;
  height: auto;
  display: block;
}

.plot-canvas {
  width: 100%;
  min-height: 520px;
  height: 520px;
}

.plot-panel-heading {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0 0 0.5rem 0;
  font-size: 1rem;
  font-weight: 600;
}

.plot-tooltip-text {
  font-weight: 400;
}

.plot-area-with-title {
  --plot-title-block-height: 2.1rem;
  --plot-body-height: 520px;
  --plot-legend-space: 24px;
  min-height: calc(var(--plot-title-block-height) + var(--plot-body-height) + var(--plot-legend-space));
}

.plot-area-with-title .plot-canvas {
  min-height: var(--plot-body-height);
  height: var(--plot-body-height);
}

@media (min-width: 900px) {
  .plot-area {
    max-width: 840px;
  }
}

.plot-area.is-hidden {
  display: none;
}

.plot-canvas.js-plotly-plot,
.plot-canvas .plot-container {
  width: 100% !important;
  height: 100% !important;
}

/* -------------------------------------------------------------------------- */
/* Formula tabs                                                               */
/* -------------------------------------------------------------------------- */

.formula-tab-wrap {
  text-align: center;
}

.formula-tab-group {
  display: inline-block;
  width: max-content;
  max-width: 100%;
}

.formula-tab-group wa-tab {
  font-size: 0.82rem;
}

.formula-tab-group wa-tab::part(base) {
  padding: 0.1rem 0.4rem;
}

.formula-tab-group::part(tabs) {
  margin-bottom: 0.05rem;
}

.formula-tab-group .math {
  text-align: center;
  margin: 0.05rem 0 0;
}

.formula-tab-group::part(body) {
  padding-top: 0;
}

.formula-tab-group wa-tab-panel {
  margin-top: -0.25rem;
}

.formula-tab-group wa-tab-panel::part(base) {
  padding-top: 0;
  padding-bottom: 0;
}

.formula-tab-label {
  display: block;
  width: 100%;
  font-weight: 400;
}

/* -------------------------------------------------------------------------- */
/* Symbol table: ONLY white top/mid/bottom rules (no row separators in tbody)  */
/* -------------------------------------------------------------------------- */

.symbol-table {
  width: 100%;
  margin-top: 1.5rem;
  font-size: 0.9rem;

  /* Use separate to avoid any inherited row-border artifacts */
  border-collapse: separate;
  border-spacing: 0;

  background: transparent;

  border-top: 1px solid #fff;
  /* top rule */
  border-bottom: 1px solid #fff;
  /* bottom rule */
}

/* Mid rule directly under header */
.symbol-table thead {
  display: table-header-group;
}

.symbol-table thead tr {
  border: 0 !important;
}

.symbol-table thead th {
  border-bottom: 1px solid #fff !important;
  /* mid rule */
}

/* If the header row uses <td> cells (e.g. to avoid bold headers),
   give them the same mid rule as <th>. */
.symbol-table thead td {
  border-bottom: 1px solid #fff !important;
}


/* Hard reset: no borders anywhere else */
.symbol-table th,
.symbol-table td,
.symbol-table tr,
.symbol-table thead,
.symbol-table tbody,
.symbol-table tfoot {
  border: 0 !important;
  background: transparent;
}

.symbol-table th,
.symbol-table td {
  padding: 0.25rem 0.5rem;
  text-align: left;
}

.symbol-table th {
  font-weight: 600;
}

/* Extra guard: prevent any row separators from other stylesheets */
.symbol-table tbody tr {
  border: 0 !important;
  box-shadow: none !important;
}

/* -------------------------------------------------------------------------- */
/* Validation page                                                             */
/* -------------------------------------------------------------------------- */

.under-construction {
  margin: 0.6rem 0 1rem 0;
}

.note-text {
  font-size: 0.85rem;
  color: rgba(224, 224, 224, 0.7);
}

/* Accent rule separating the benchmark sections. The former table gave the cases an implicit
   boundary; as prose sections they need an explicit one. */
.ruled-heading {
  margin-top: 2.6rem;
  padding-top: 1.4rem;
  border-top: 2px solid rgba(46, 123, 228, 0.55);
}

/* Parameter list of a benchmark section: a label column sized to its content and a value column
   taking the rest, so the values line up down the page. Replaces the former table row, and wraps
   to stacked pairs where the two columns no longer fit. */
.bench-spec {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.3rem 1rem;
  margin: 1rem 0 0.9rem 0;
  font-size: 0.9rem;
}

.bench-spec dt {
  color: rgba(224, 224, 224, 0.6);
}

.bench-spec dd {
  margin: 0;
}

@media (max-width: 34rem) {
  .bench-spec {
    grid-template-columns: 1fr;
    gap: 0 0;
  }

  .bench-spec dd {
    margin-bottom: 0.55rem;
  }
}

/* Prompt and load button of a benchmark section. The button carries the same label as its twin in
   the button row of the simulation tab, so the two are recognizable as the same control; the
   sentence in front of it supplies the context the button row gets from its surroundings. */
.bench-load {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.3rem 0.6rem;
  margin: 0.9rem 0 1rem 0;
}

/* Replica of the Run button of the simulation tab, shown inline in the introduction so that the
   sentence points at the control the reader will look for. It carries the `inert` attribute rather
   than `disabled`: inert takes it out of the tab order, out of the accessibility tree, and out of
   pointer events, but leaves the appearance untouched — the picture has to match the button in its
   ready state, which `disabled` would dim. The hover declarations only guard against a pointer
   state slipping through; inert already suppresses it. */
wa-button.bench-run-sample {
  vertical-align: middle;
  margin: 0 0.15rem;
}

wa-button.bench-run-sample::part(base),
wa-button.bench-run-sample:hover::part(base) {
  height: auto;
  min-height: 0;
  padding: 0.1rem 0.55rem;
  font-size: 0.85rem;
  cursor: default;
  background: var(--highlight);
  color: #fff;
}

/* -------------------------------------------------------------------------- */
/* k_ij table: NO lines, and ALL columns same width (incl. label column)       */
/* -------------------------------------------------------------------------- */

.kij-container {
  margin-top: 0.15rem;
  width: 100%;
  display: flex;
  justify-content: center;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.kij-empty-note {
  width: 100%;
  box-sizing: border-box;
  min-height: var(--control-height);
  /* Small block padding so min-height (not padding) sets the height. */
  padding: 0.15rem 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: rgba(224, 224, 224, 0.72);
  background: var(--readonly-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  box-shadow: none;
  pointer-events: none;
  user-select: none;
}

.kij-table {
  width: 100%;
  max-width: 100%;

  /* Equal-width columns */
  table-layout: fixed;

  border-collapse: separate;
  border-spacing: 0;

  background: transparent;

  border-spacing: 2px 2px;
}

/* No borders anywhere */
.kij-table,
.kij-table th,
.kij-table td,
.kij-table tr,
.kij-table thead,
.kij-table tbody {
  /* Cell borders, not data borders */
  border: 0 !important;
  background: transparent;
}

/* Table cells. */
.kij-table th,
.kij-table td {
  padding: 0.05rem 0.05rem;
  text-align: center;
  /* Allow focus ring to overlay adjacent cells */
  overflow: visible;
  line-height: 1;
  font-weight: normal;
}

/* Labels: allow wrapping; vertically centered */
.kij-table tbody th {
  text-align: center;
  white-space: normal;
  overflow-wrap: anywhere;
  vertical-align: middle;
}

/* Inputs: explicitly constrain height/size (otherwise they won't shrink) */
.kij-input {
  width: 100%;
  box-sizing: border-box;
  min-width: 0;

  height: 1.55rem;
  min-height: 1.55rem;

  padding: 0.05rem 0.05rem;
  text-align: center;
  line-height: 1;
  font-size: 0.85em;
  appearance: none;
  -webkit-appearance: none;
}

.kij-input:focus {
  outline: none;
  box-shadow: 0 0 0 2px var(--accent);
}

.kij-readonly {
  background: var(--readonly-bg);
}

/* -------------------------------------------------------------------------- */
/* Copy table: read-only values, each in a field of the k_ij matrix's kind      */
/* -------------------------------------------------------------------------- */

/* The caption line above the table, holding the "Copy table" action at its right end. The caption
   claims the space between the two, so that the action stays right-aligned in a line that has no
   caption at all — which is how the flash result shows it. */
.copy-table-head {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 0.75rem;
  margin: 0.9rem 0 0.35rem 0;
}

.copy-table-caption {
  margin-right: auto;
  font-size: 0.85rem;
  color: rgba(224, 224, 224, 0.72);
}

.copy-table-action {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  height: 1.55rem;
  padding: 0 0.55rem;
  box-sizing: border-box;
  font: inherit;
  font-size: 0.8rem;
  line-height: 1;
  white-space: nowrap;
  color: rgba(224, 224, 224, 0.72);
  background: var(--readonly-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  cursor: pointer;
}

.copy-table-action:hover {
  color: var(--accent-hover);
  border-color: rgba(46, 123, 228, 0.55);
}

.copy-table-action.is-copied {
  color: var(--highlight-hover);
  background: rgba(208, 135, 0, 0.10);
  border-color: var(--highlight);
}

/* A column per component plus the fixed ones outgrows the page from about four components on, and
   the cells do not wrap. The table scrolls inside its own wrapper rather than pushing the whole
   page sideways, which would move every other block of the panel with it. */
.copy-table-wrap {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.copy-table {
  /* No `max-width`: it would cap the table at its wrapper and let the columns be compressed past
     their floor, which is the truncation the floor exists to prevent. Without it the table grows to
     the width its columns need and the wrapper scrolls. */
  width: 100%;

  /* Automatic layout, so that the heading column can take its width from its widest label. What
     keeps the value columns equal under it is the colgroup below, not the algorithm. */
  table-layout: auto;

  border-collapse: separate;
  border-spacing: 2px;
  background: transparent;
  font-size: 0.85rem;
}

/* Column widths, in three parts.

   The heading column asks for a width of 1%, which no label fits into, so the automatic layout
   falls back to the width of its widest one — the labels do not wrap (see `.copy-table tbody th`
   below), so that is the label itself, and the column is exactly as wide as it has to be.

   The value columns all ask for the same width. Whatever is left after the heading column is
   distributed in proportion to what the columns asked for, and equal requests share it equally, so
   the value columns stay equally wide whether there is room to spare or not.

   `.copy-cell` carries a minimum width, which is what a column can never be compressed below. A
   table that no longer fits therefore grows past its wrapper, which then scrolls: a value column
   narrow enough to cut "7.9753e-9" down to "7.9753…" is worse than a scroll bar, and with one
   column per component the flash reaches that width from about five components on. */
.copy-table col {
  width: 12rem;
}

.copy-table col.copy-table-namecol {
  width: 1%;
}

/* No borders anywhere: the cell frames carry the structure. */
.copy-table,
.copy-table th,
.copy-table td,
.copy-table tr,
.copy-table thead,
.copy-table tbody {
  border: 0;
  background: transparent;
}

.copy-table th,
.copy-table td {
  padding: 0.05rem;
  font-weight: normal;
  /* Allow the focus ring of a cell to overlay its neighbors. */
  overflow: visible;
}

/* The floor of a value column: the width below which the layout may not compress it, and hence the
   point from which the table grows past its wrapper instead. It sits on the cell rather than on the
   field inside it, because this is the width the column algorithm reads. */
.copy-table tbody td {
  min-width: 7rem;
}

.copy-table thead th {
  padding-bottom: 0.3rem;
  line-height: 1.2;
  text-align: center;
  vertical-align: bottom;
  color: rgba(224, 224, 224, 0.78);
}

.copy-table thead th:first-child,
.copy-table tbody th {
  text-align: left;
}

/* The labels of the heading column set its width, so they must not wrap: a label broken over two
   lines would make the column narrower than the widest label, which is the width it is meant to
   have. */
.copy-table thead th:first-child,
.copy-table tbody th {
  white-space: nowrap;
}

.copy-table tbody th {
  padding-right: 0.5rem;
  vertical-align: middle;
}

/* The unit, on its own line under the symbol it belongs to. */
.copy-unit {
  display: block;
  font-size: 0.85em;
  color: rgba(224, 224, 224, 0.45);
}

/* One value: the read-only field of the k_ij matrix, with the copy symbol at its right edge. */
.copy-cell {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  height: 1.55rem;
  padding: 0 0.3rem;
  box-sizing: border-box;
  background: var(--readonly-bg);
  border: 1px solid var(--panel-border);
  border-radius: var(--radius);
  font-variant-numeric: tabular-nums;
}

.copy-cell-value {
  flex: 1 1 auto;
  min-width: 0;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.copy-cell.is-empty .copy-cell-value {
  color: rgba(224, 224, 224, 0.5);
}

.copy-cell-copy {
  flex: 0 0 auto;
  width: 1.05rem;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background: none;
  font: inherit;
  line-height: 1;
  color: rgba(224, 224, 224, 0.35);
  cursor: pointer;
}

/* The whole cell reacts, so that what the click will take is unmistakable. */
.copy-cell:hover {
  border-color: rgba(46, 123, 228, 0.55);
}

.copy-cell:hover .copy-cell-copy,
.copy-cell-copy:focus-visible {
  color: var(--accent-hover);
}

/* Confirmation of a copy, in the color the form uses for a field that has just changed. */
.copy-cell.is-copied {
  background: rgba(208, 135, 0, 0.10);
  border-color: var(--highlight);
}

.copy-cell.is-copied .copy-cell-copy {
  color: var(--highlight-hover);
}

/* -------------------------------------------------------------------------- */
/* Mobile layout: stack label + field to avoid horizontal overflow              */
/* -------------------------------------------------------------------------- */

@media (max-width: 520px) {

  .two-col-grid,
  .result-fields {
    grid-template-columns: 1fr;
  }

  /* Stacked layout: restore the label margins for group separation. */
  .two-col-grid>label,
  .avg-density-add-label {
    margin-block: 0.8rem 0.2rem;
  }

  .indent {
    margin-left: 0;
  }

  .avg-density-toolbar {
    gap: 0.35rem;
  }

  .avg-density-add-row {
    grid-template-columns: 1fr;
  }

  .avg-density-controls {
    width: 100%;
  }

  .avg-density-select {
    min-width: 0;
  }

  .avg-density-row {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .avg-density-row-label {
    grid-column: 1 / -1;
    margin-bottom: 0;
  }

  /* Stacked layout: the help icons of the section headings sit at the right
     edge, like those of the input labels. */
  .avg-density-title-group {
    align-self: stretch;
  }

  .avg-density-title-group .tooltip-icon,
  .section-heading.has-tooltip .tooltip-icon {
    margin-left: auto;
  }
}

/* -------------------------------------------------------------------------- */
/* Flash animation                                                             */
/* -------------------------------------------------------------------------- */

.flash {
  outline: 2px solid var(--highlight);
  outline-offset: 0px;
  border-radius: var(--radius);
  animation: flashOut 1.4s ease-out forwards;
}

wa-input.flash::part(base) {
  animation: waFlashOut 1.4s ease-out forwards;
}

wa-button.flash::part(base) {
  animation: waFlashOut 1.4s ease-out forwards;
}

wa-input.flash:focus-within::part(base) {
  animation: waFlashOut 1.4s ease-out forwards;
}

@keyframes waFlashOut {
  0% {
    border-color: var(--highlight);
    box-shadow: 0 0 0 2px rgba(208, 135, 0, 0.75);
  }

  55% {
    border-color: var(--highlight);
    box-shadow: 0 0 0 2px rgba(208, 135, 0, 0.75);
  }

  100% {
    box-shadow: none;
  }
}

@keyframes flashOut {
  0% {
    outline-color: var(--highlight);
  }

  55% {
    outline-color: var(--highlight);
  }

  100% {
    outline-color: transparent;
  }
}

/* -------------------------------------------------------------------------- */
/* Developer-only widgets                                                      */
/* -------------------------------------------------------------------------- */

/* Content that only developer mode gets to see is named rather than merely tinted: a pill reading
   "developer", shaped like the maturity badge of the phase equilibrium panel and drawn in
   `--developer`, the third signal color of the palette. On an output row the pill sits after the
   label text and needs no toggling, because the row itself is hidden in user mode. On a plot panel
   -- which exists in both modes and only some of whose curves are developer-only -- the heading
   carries the pill and `render.js` unhides it for the runs that actually contain those curves. */
.dev-badge {
  display: inline-block;
  flex: 0 0 auto;
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--developer);
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--developer-hover);
}

/* `display: inline-block` above would otherwise defeat the `hidden` attribute. */
.dev-badge[hidden] {
  display: none;
}

/* A label with a tooltip is a flex row and already spaces its children by `gap`. */
.label-normal:not(.has-tooltip) .dev-badge {
  margin-left: 0.45rem;
}

/* -------------------------------------------------------------------------- */
/* Future WA widget hook                                                       */
/* -------------------------------------------------------------------------- */

.wa-card-hook {
  display: none;
}

/* -------------------------------------------------------------------------- */
/* Bulk phase equilibrium panel                                                */
/* -------------------------------------------------------------------------- */

/* Qualification of a result that is shown but not settled -- an unreached tolerance, an
   unconfirmed phase count. It takes the palette highlight rather than a warning hue of its own;
   the tint on the left edge carries it without flooding the panel. */
.section-note {
  margin: 0.7rem 0 0 0;
  padding: 0.4rem 0.7rem;
  border-left: 3px solid var(--highlight);
  background: rgba(208, 135, 0, 0.06);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 0.85rem;
  color: rgba(224, 224, 224, 0.85);
}

/* Marks a calculation whose method is still maturing. Outlined rather than filled: it qualifies
   the panel, it does not announce it. */
.maturity-badge {
  align-self: center;
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--highlight);
  border-radius: 999px;
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  color: var(--highlight-hover);
}

/* The coexisting phases are a `.copy-table` like the component data; only the note below them and
   the experimental badge above belong to this panel alone. */
