:root {
  --bulma-code: #353535;
}

/* System dark mode (when data-theme is not set) */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bulma-code: #ebecf0;
  }
}

/* Force dark mode */
[data-theme="dark"] {
  --bulma-code: #ebecf0;
}

/* Force light mode */
[data-theme="light"] {
  --bulma-code: #353535;
}

#theme-toggle-button {
  border: none;
  border-radius: 0px;
}

#theme-toggle-button:hover {
  background-color: rgba(0, 0, 0, 0.05);
}

[data-theme="dark"] #theme-toggle-button:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

pre {
  white-space: pre-wrap;
  word-break: break-all;
}

/* Log widget styles */
.log-list {
  font-family: monospace;
  max-height: 75vh;
  overflow-y: scroll;
}
.log-data {
  flex: 1;
  white-space: pre-wrap;
  font-size: 16px;
}
.log-list li {
  transition: background-color 300ms linear;
}
.log-list li:nth-child(odd) {
  background: rgba(0,0,0,0.0125);
}
.log-list li:hover {
  background: white;
  outline: 1px solid rgba(0,0,100,0.25);
}
.log-list li:hover .timestamp {
  background: none;
}
.log-line {
  display: flex;
  flex-flow: row;
}
.timestamp, .log-data {
  padding: 0.25ex 1ch;
}
.timestamp {
  background: rgba(0,0,0,0.05);
  user-select: none;
  min-width: 9ch; /* digits of "3600.00 s" */
  text-align: right;
  text-decoration: none;
  color: inherit;
}
.log-list li:target {
  background: rgba(255,255,0,0.1);
}
.log-list li:target .timestamp {
  background: rgba(255,255,0,0.15);
}

/* Pricing currency toggle */
.pricing-currency-radio {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* Hide all price/currency elements by default; show when currency matches */
.price, span.currency-chf, span.currency-usd, span.currency-eur {
  display: none;
}
#pricing-chf:checked ~ * .price.currency-chf { display: block; }
#pricing-usd:checked ~ * .price.currency-usd { display: block; }
#pricing-eur:checked ~ * .price.currency-eur { display: block; }
#pricing-chf:checked ~ * span.currency-chf { display: inline; }
#pricing-usd:checked ~ * span.currency-usd { display: inline; }
#pricing-eur:checked ~ * span.currency-eur { display: inline; }

/* Highlight active toggle label */
#pricing-chf:checked ~ * label[for="pricing-chf"],
#pricing-usd:checked ~ * label[for="pricing-usd"],
#pricing-eur:checked ~ * label[for="pricing-eur"] {
  background-color: var(--bulma-code);
  color: var(--bulma-scheme-main);
  border-color: var(--bulma-code);
}

.pricing-toggle label {
  cursor: pointer;
}

/* Tone down inline link colors to use the --bulma-code accent */
:root {
  --bulma-link-text: var(--bulma-code);
  --bulma-link-text-hover: var(--bulma-code);
  --bulma-link-text-active: var(--bulma-code);
}

.content a, .box a {
  text-decoration: underline;
  text-underline-offset: 0.15em;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
}

.content a:hover, .box a:hover {
  text-decoration-color: currentColor;
}

/* Accessible link colors on dark backgrounds */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .box a {
    color: var(--bulma-code);
  }
}
[data-theme="dark"] .box a {
  color: var(--bulma-code);
}

.instructions {
  margin-top: 2rem;
  opacity: 0.2;
  font-size: 0.75rem;
  transition: opacity 0.2s;
}

.instructions:hover {
  opacity: 1;
}

/* Spin the running-status icon while a job is running */
@keyframes icon-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
.icon-spin {
  display: inline-block;
  animation: icon-spin 1.5s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .icon-spin {
    animation: none;
  }
}

/* An already-built run: a lighter, softer green than success, to mark a pass
   that cost no work. Lightened further in dark mode where the background is
   dark. */
.has-text-cached {
  color: #5cc98e !important;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .has-text-cached {
    color: #86d6a4 !important;
  }
}
[data-theme="dark"] .has-text-cached {
  color: #86d6a4 !important;
}

/* Cap prose line length for readability */
.content p,
.content li {
  max-width: 80ch;
}

/* The API reference ships no dark theme, and it is not in a shadow tree, so on
   a dark page its own dark text would sit on our dark background. Give it the
   light surface its colours assume instead of a half-applied theme. A no-op in
   light mode, where the page is already this colour. */
.swagger-ui {
  background: #fff;
  border-radius: 6px;
}

/* The reference's version and spec badges, which it renders as a pre with white
   text inside a coloured pill. Both bulma and copiable-block.css style every
   pre on the page with a background of their own, which paints over the pill
   and leaves the white text on light grey. */
.swagger-ui .info .title small pre {
  background: none;
  overflow: visible;
}

/* Suite timing page.

   Every phase colour on that page lives here, once, as custom properties on
   the .timing-phase-* classes. The timeline bars, the legend swatches and the
   table rows all carry the class and read the properties, so they cannot drift
   apart and dark mode is defined in one place. jobTypeClass in
   Timing/Phase.hs is what puts the class on each element. */
:root {
  --phase-config-fill: #a8d4f0;
  --phase-config-stroke: #7db8d8;
  --phase-eval-fill: #e8d44d;
  --phase-eval-stroke: #c4b23a;
  --phase-build-fill: #6bc278;
  --phase-build-stroke: #4fa35e;
  --phase-test-fill: #e8a64c;
  --phase-test-stroke: #c48a3a;
  --phase-deploy-fill: #b088c4;
  --phase-deploy-stroke: #8e6a9e;
  /* How much of the phase colour a table row is washed with. Low enough that
     body text keeps its contrast against the scheme background. */
  --phase-tint-strength: 22%;
  --phase-tint-strength-lit: 38%;
  --profile-fail-colour: #cc3333;
  --profile-retry-colour: #666666;
  --profile-gap-colour: #dddddd;
  --profile-gap-line-colour: #cccccc;
  --profile-grid-line-colour: #e0e0e0;
  --profile-grid-label-colour: #666666;
  --profile-bar-hover-colour: #333333;
}

/* The pastels above are picked against a white page. On the dark scheme they
   glare, so the fills are deepened and the greys are inverted towards the dark
   background. The tint is weaker because it washes a dark surface, where a
   little colour goes much further. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --phase-config-fill: #3f7fa6;
    --phase-config-stroke: #6aa8c8;
    --phase-eval-fill: #a08f2a;
    --phase-eval-stroke: #c8b64a;
    --phase-build-fill: #3f8a52;
    --phase-build-stroke: #5faa70;
    --phase-test-fill: #a97430;
    --phase-test-stroke: #cf9448;
    --phase-deploy-fill: #77588c;
    --phase-deploy-stroke: #9b7cb0;
    --phase-tint-strength: 16%;
    --phase-tint-strength-lit: 28%;
    --profile-fail-colour: #e06060;
    --profile-retry-colour: #a8b0ba;
    --profile-gap-colour: #3f444b;
    --profile-gap-line-colour: #4a5058;
    --profile-grid-line-colour: #3a3f46;
    --profile-grid-label-colour: #9aa2ad;
    --profile-bar-hover-colour: #e6e6e6;
  }
}
[data-theme="dark"] {
  --phase-config-fill: #3f7fa6;
  --phase-config-stroke: #6aa8c8;
  --phase-eval-fill: #a08f2a;
  --phase-eval-stroke: #c8b64a;
  --phase-build-fill: #3f8a52;
  --phase-build-stroke: #5faa70;
  --phase-test-fill: #a97430;
  --phase-test-stroke: #cf9448;
  --phase-deploy-fill: #77588c;
  --phase-deploy-stroke: #9b7cb0;
  --phase-tint-strength: 16%;
  --phase-tint-strength-lit: 28%;
  --profile-fail-colour: #e06060;
  --profile-retry-colour: #a8b0ba;
  --profile-gap-colour: #3f444b;
  --profile-gap-line-colour: #4a5058;
  --profile-grid-line-colour: #3a3f46;
  --profile-grid-label-colour: #9aa2ad;
  --profile-bar-hover-colour: #e6e6e6;
}

.timing-phase-config {
  --phase-fill: var(--phase-config-fill);
  --phase-stroke: var(--phase-config-stroke);
}
.timing-phase-eval {
  --phase-fill: var(--phase-eval-fill);
  --phase-stroke: var(--phase-eval-stroke);
}
.timing-phase-build {
  --phase-fill: var(--phase-build-fill);
  --phase-stroke: var(--phase-build-stroke);
}
.timing-phase-test {
  --phase-fill: var(--phase-test-fill);
  --phase-stroke: var(--phase-test-stroke);
}
.timing-phase-deploy {
  --phase-fill: var(--phase-deploy-fill);
  --phase-stroke: var(--phase-deploy-stroke);
}

/* Timeline SVG. The chart is inlined into the page, so these reach it. */
.profile-svg {
  transform-origin: left top;
}
.profile-bar {
  fill: var(--phase-fill);
  stroke: var(--phase-stroke);
  cursor: pointer;
}
/* Two classes, so this beats the single-class phase rule whichever order they
   end up in. */
.profile-bar.profile-bar-failed {
  --phase-stroke: var(--profile-fail-colour);
}
.profile-bar:hover {
  stroke: var(--profile-bar-hover-colour);
  stroke-width: 2;
}
.profile-grid-line {
  stroke: var(--profile-grid-line-colour);
}
.profile-grid-label {
  fill: var(--profile-grid-label-colour);
}
.profile-gap-line {
  stroke: var(--profile-gap-line-colour);
}
.profile-hatch-gap {
  stroke: var(--profile-gap-colour);
}
.profile-hatch-fail {
  stroke: var(--profile-fail-colour);
}
.profile-hatch-retry {
  stroke: var(--profile-retry-colour);
}

/* Timeline legend */
.timing-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 1rem;
  font-size: 0.75rem;
}
.timing-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}
.timing-swatch {
  display: inline-block;
  width: 0.9em;
  height: 0.9em;
  border-radius: 3px;
  /* An overlay swatch carries no phase, so it has no phase colour to fall back
     on; it paints itself below. */
  border: 1px solid var(--phase-stroke, transparent);
  background-color: var(--phase-fill, transparent);
}
/* The three overlays the chart draws on top of a bar, as the same 45-degree
   hatch the SVG patterns use. Two classes, so these beat the swatch rule
   whichever order they end up in. */
.timing-swatch.timing-swatch-failed {
  border-color: var(--profile-fail-colour);
  background: repeating-linear-gradient(45deg, var(--profile-fail-colour) 0 2px, transparent 2px 5px);
}
.timing-swatch.timing-swatch-retried {
  border-color: var(--profile-retry-colour);
  background: repeating-linear-gradient(45deg, var(--profile-retry-colour) 0 2px, transparent 2px 5px);
}
.timing-swatch.timing-swatch-gap {
  border-color: var(--profile-gap-line-colour);
  background: repeating-linear-gradient(45deg, var(--profile-gap-colour) 0 2px, transparent 2px 5px);
}

/* Phase table. The row wears the phase's colour so a row and its bars in the
   timeline read as the same thing. Both selectors name the table and the cell
   element so they outrank bulma's own `.table td` and `.table.is-bordered td`,
   which set the background and the border width these rules replace. */
.table tr.timing-row > td {
  background-color: color-mix(in srgb, var(--phase-fill) var(--phase-tint-strength), transparent);
}
/* The total, not a phase: a neutral wash and a rule above it, so it reads as
   the sum of the rows rather than another one of them. */
.table tr.timing-row-suite > td {
  background-color: color-mix(in srgb, currentColor 7%, transparent);
  border-top: 2px solid color-mix(in srgb, currentColor 40%, transparent);
}

/* The zoom buttons and the legend share a row under the Timeline heading. */
.timing-timeline-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1.5rem;
}
.profile-container {
  overflow-x: auto;
  border: 1px solid var(--profile-grid-line-colour);
  padding: 8px;
}

/* Hover pairing between the legend and what it names. timing.julius puts
   .timing-lit on everything sharing the hovered element's data-marks. */
.profile-bar,
.profile-gap-marker,
.timing-legend-item,
.timing-swatch,
.table tr.timing-row > td {
  transition: background-color 120ms linear, transform 120ms ease-out;
}
.timing-legend-item {
  padding: 0 0.3em;
  border-radius: 4px;
}
.timing-legend-item.timing-lit {
  background-color: color-mix(in srgb, currentColor 14%, transparent);
}
/* Grown rather than re-bordered, so lighting an entry shifts nothing around it. */
.timing-legend-item.timing-lit .timing-swatch {
  transform: scale(1.25);
}
.profile-bar.timing-lit {
  stroke-width: 2;
}
/* The gap band has no stroke of its own, so it gets one to be picked out. */
.profile-gap-marker.timing-lit {
  stroke: var(--profile-gap-line-colour);
  stroke-width: 2;
}
.table tr.timing-row.timing-lit > td {
  background-color: color-mix(in srgb, var(--phase-fill) var(--phase-tint-strength-lit), transparent);
}

/* The hover pairing is legible without the movement: the lit legend entry
   still takes its background, the lit bar still takes its heavier stroke. */
@media (prefers-reduced-motion: reduce) {
  .profile-bar,
  .profile-gap-marker,
  .timing-legend-item,
  .timing-swatch,
  .table tr.timing-row > td {
    transition: none;
  }
  .timing-legend-item.timing-lit .timing-swatch {
    transform: none;
  }
}

/* Focus-visible only, so a tap or a click does not leave a ring behind. */
.timing-legend-item:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 1px;
}
