/* Only the samples page: the explorer in the panel, the grid of days, the facts of a branch and the code.
   The frame and the panel are site.css, the sheet's text docs.css. */
/* ==== TOKENS ==== */
:root {
  --ok: #3fb950;          /* a run that passed */
  --bad: var(--refuted);  /* a run that failed */
  --sleep: #8ec5e0;       /* what a pass fades to: ice, a project nobody touches freezes */
  --rot: #4a1010;         /* what a failure fades to: a project nobody fixed rots */
  --empty: var(--panel);  /* a day before the first run */
}
:root[data-theme="light"] { --ok: #1f9d4c; --bad: #cf3b2e; --sleep: #74b3d6; --rot: #5c1414; --empty: var(--l-panel-2); }
@media (prefers-color-scheme: light) {
  :root[data-theme="auto"] { --ok: #1f9d4c; --bad: #cf3b2e; --sleep: #74b3d6; --rot: #5c1414; --empty: var(--l-panel-2); }
}

/* ==== THE EXPLORER ==== */
/* Folders are buttons, files are links: a folder changes only the panel, a file is a page with an
   address. Both look like the entries of the documents' shelf. */
#explorer button.dir {
  display: block; width: 100%; text-align: left; padding: 0.32rem 0.6rem; border: 0; border-radius: 6px;
  background: none; font: inherit; font-size: 0.95rem; color: var(--text); cursor: pointer;
}
#explorer button.dir:hover { background: var(--panel); }
#explorer button.dir.up { color: var(--muted); }
#explorer .hint { margin-left: 0.5rem; font-size: 0.8rem; color: var(--muted); }
#explorer a.file, #explorer button.dir { font-family: "IBM Plex Mono", monospace; font-size: 0.85rem; overflow-wrap: anywhere; }
/* the path in one line, scrolled sideways; when its start is out of sight the left edge fades */
#crumbs { display: flex; align-items: baseline; gap: 0.15rem; margin: 0 0 0.5rem; overflow-x: auto; scrollbar-width: none;
  font-family: "IBM Plex Mono", monospace; font-size: 0.8rem; }
#crumbs::-webkit-scrollbar { display: none; }
#crumbs.cut { mask-image: linear-gradient(to right, transparent 0, #000 1.5rem); }
#crumbs button { flex: none; white-space: nowrap; border: 0; background: none; padding: 0.15rem 0.3rem; border-radius: 4px;
  font: inherit; color: var(--focus-text); cursor: pointer; }
#crumbs button.here { color: var(--text); }
#crumbs button:hover { background: var(--panel); }
#crumbs .sep { flex: none; color: var(--muted); }
#branches .dot { display: inline-block; width: 0.5rem; height: 0.5rem; border-radius: 50%; margin-right: 0.5rem; vertical-align: 0.05em; }
.dot.ok { background: color-mix(in oklab, var(--sleep) var(--fade, 0%), var(--ok)); }
.dot.bad { background: color-mix(in oklab, var(--rot) var(--fade, 0%), var(--bad)); }
/* not known yet: a ring of the dot's size, turning; no reports at all: an empty ring */
:root:not(.js) .dot.wait { display: none; }
.dot.wait, .dot.none { box-sizing: border-box; border: 1.5px solid var(--muted); }
.dot.wait { border-top-color: transparent; }
@media (prefers-reduced-motion: no-preference) { .dot.wait { animation: dot-wait 0.9s linear infinite; } }
@keyframes dot-wait { to { transform: rotate(1turn); } }
/* on a phone a tap needs room: the entries grow to a finger's height */
@media (pointer: coarse) {
  #explorer button.dir, #explorer a.file, #branches a { padding-block: 0.6rem; }
}

/* ==== THE DAYS ==== */
/* A year of days, a column per week as in the contribution grid of a GitHub profile, months over the
   columns and weekdays beside the rows. On a narrow screen the grid scrolls inside its own box;
   samples.js opens it with today in view. */
.days-summary { display: flex; flex-wrap: wrap; gap: 0.2rem 1.2rem; margin: 0 0 0.7rem; font-size: 0.9rem; color: var(--muted); }
.days-summary span:first-child { color: var(--text); }
.days-scroll { overflow-x: auto; padding: 0.3rem 0 0.6rem; }
.days-wrap { width: max-content; }
.days { --cell: 12px; display: grid; gap: 3px; width: max-content;
  grid-template-columns: 1.8rem repeat(var(--weeks), var(--cell)); grid-template-rows: 1rem repeat(7, var(--cell)); }
.days .m { grid-row: 1; font-size: 0.7rem; color: var(--muted); white-space: nowrap; line-height: 1rem; }
.days .w { grid-column: 1; font-size: 0.65rem; color: var(--muted); line-height: var(--cell); }
.day { display: block; width: var(--cell); height: var(--cell); padding: 0; border: 0; border-radius: 3px; background: var(--empty); }
/* without a run a pass freezes to blue and a failure rots to dark red, over 30 days */
.day.ok { background: color-mix(in oklab, var(--sleep) var(--fade), var(--ok)); }
.day.bad { background: color-mix(in oklab, var(--rot) var(--fade), var(--bad)); }
/* the weeks ahead are the same empty cells, fading out to the right */
.day.future { opacity: calc(0.9 - var(--far) * 0.9); }
button.day { cursor: pointer; transition: transform 0.12s ease, box-shadow 0.12s ease; }
button.day:hover, button.day.on, button.day:focus-visible { transform: scale(1.6); z-index: 2; position: relative;
  box-shadow: 0 0 0 1px var(--ground), 0 2px 8px rgba(0, 0, 0, 0.35); outline: none; }
.day.today { box-shadow: 0 0 0 1px var(--text); }

/* When a sample's data comes, its days take their colours in a wave from the oldest week; the cells keep
   their size and place. Today pulses softly once the grid stands. */
@media (prefers-reduced-motion: no-preference) {
  .days.fill .day.ok, .days.fill .day.bad { animation: day-fill 0.5s ease both; animation-delay: calc(var(--n) * 8ms); }
  .day.today { animation: today 2.4s ease-in-out 1s infinite; }
  .days.fill .day.today { animation: day-fill 0.5s ease both, today 2.4s ease-in-out 1s infinite; animation-delay: calc(var(--n) * 8ms), 1s; }
}
@keyframes day-fill { from { background: var(--empty); } }
@keyframes today { 50% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 45%, transparent); } }

/* the card of a day */
/* over the whole page: placed by samples.js at the day, kept inside the window */
.day-card { position: fixed; z-index: 50; width: 15rem; padding: 0.7rem 0.85rem; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--panel); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); font-size: 0.85rem; }
.day-card[hidden] { display: none; }
.day-card { transition: opacity 0.3s ease; }
.day-card.fading { opacity: 0; }
.day-card .dc-date { color: var(--muted); font-size: 0.8rem; }
.day-card .dc-head { margin: 0.15rem 0 0.5rem; font-size: 1rem; }
.day-card .quiet { font-weight: 500; color: var(--muted); }
.day-card dl { display: grid; grid-template-columns: auto 1fr; gap: 0.2rem 0.8rem; margin: 0 0 0.5rem; }
.day-card dt { color: var(--muted); }
.day-card dd { margin: 0; text-align: right; }
.day-card .dc-new { display: block; font-size: 0.75rem; color: var(--focus-text); }
.day-card .dc-ages { display: grid; gap: 0.1rem; padding-top: 0.45rem; border-top: 1px solid var(--line); color: var(--muted); font-size: 0.8rem; }
.day-card .dc-run { display: block; margin-top: 0.5rem; font-size: 0.8rem; }

/* ==== THE LAST RUN ==== */
.run-head { min-height: 1.7rem; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.3rem 1rem; margin: 0.4rem 0 1rem; color: var(--muted); }
.run-head .result { font-weight: 600; font-size: 1.05rem; }
.run-head a { margin-left: auto; }
/* on a phone the line of the run takes two rows; the frame keeps the room for them */
@media (max-width: 480px) { .run-head { min-height: 3.4rem; } }
.meters { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: 0.8rem; margin: 0 0 1.4rem; }
.meter { border: 1px solid var(--line); border-radius: var(--radius); padding: 0.75rem 0.9rem 0.8rem; background: var(--panel); }
.meter-title { font-size: 0.8rem; color: var(--muted); }
/* one line of the value's size, the same in the frame and with the data */
.meter-value { height: 2.4rem; display: flex; align-items: baseline; gap: 0.4rem; margin: 0.15rem 0 0.5rem; font-size: 1.5rem; font-weight: 600; }
.meter-value small { font-size: 0.85rem; font-weight: 400; color: var(--muted); }
.meter-value small.bad { color: var(--bad); }
.meter-value .delta { margin-left: auto; font-size: 0.8rem; font-weight: 500; color: var(--muted); }
.meter-value .delta.up { color: var(--ok); }
.meter-value .delta.down { color: var(--bad); }
.meter-bar { display: flex; height: 6px; border-radius: 3px; overflow: hidden; background: var(--empty); }
.meter-bar i { display: block; height: 100%; }
.meter-bar .fill { background: var(--focus); }
.meter-bar .ok { background: var(--ok); }
.meter-bar .bad { background: var(--bad); }
.spark { display: block; width: 100%; height: 24px; margin-top: 0.5rem; }
.spark polyline { fill: none; stroke: var(--focus); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.result.ok { color: var(--ok); }
.result.bad { color: var(--bad); }
#static-branches li { margin-bottom: 0.6rem; }
.origin { font-size: 0.9rem; color: var(--muted); }
/* the row of the release a day was regenerated from, lit for a moment when that day is clicked */
tr.lit td { animation: lit 2.4s ease; }
@keyframes lit { 0%, 40% { background: color-mix(in srgb, var(--focus) 22%, transparent); } }

/* ==== CODE ==== */
#doc.busy { opacity: 0.55; transition: opacity 0.15s; }
/* the code scrolls sideways in its box, as code in a document does; the page itself scrolls down */
.doc pre.code { padding: 0; overflow-x: auto; }
.doc pre.code code { display: block; padding: 1rem 1.1rem; font-size: 0.82rem; line-height: 1.6; white-space: pre; }
/* the page's own colours behind the code; the theme colours only the tokens */
.hljs { background: transparent !important; }

/* ==== THE SKELETON ==== */
/* With scripts on, the overview's shape stands in its place until the reports are here, so nothing
   jumps when they arrive; the plain list is for a reader or a crawler without scripts. */
.skeleton { display: none; }
.js .skeleton { display: block; }
.js #static-branches { display: none; }
.sk { border-radius: 6px; background: linear-gradient(90deg, var(--panel) 0%, var(--panel-2) 50%, var(--panel) 100%) 0 0 / 200% 100%; }
@media (prefers-reduced-motion: no-preference) { .sk { animation: sk 1.4s linear infinite; } }
@keyframes sk { to { background-position: -200% 0; } }
/* the skeleton is built of the overview's own elements, so their margins match; only the fill is drawn */
.sk { display: block; }
.sk-t { display: inline-block; height: 0.85em; vertical-align: middle; }
.sk-days { width: 772px; max-width: 100%; height: 141px; }
.sk-meter { height: 102px; border-radius: var(--radius); }
.sk-table { height: 125px; }
#files .sk-file { height: 1.1rem; margin: 0.45rem 0.6rem; list-style: none; }
#files .sk-file:nth-child(3n) { width: 55%; }
#files .sk-file:nth-child(3n+1) { width: 75%; }

/* ==== NEWER DATA ==== */
/* the note over a veil: the page under it stays as it was until OK */
#update { border: 1px solid var(--line); border-radius: var(--radius); padding: 1.2rem 1.4rem; background: var(--panel); color: var(--text);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35); }
#update::backdrop { background: color-mix(in srgb, var(--ground) 60%, transparent); backdrop-filter: blur(2px); }
#update p { margin: 0 0 1rem; }
#update button { font: inherit; padding: 0.4rem 1.2rem; border-radius: 8px; border: 1px solid var(--line); background: var(--focus); color: #1b1b1b; cursor: pointer; }

/* ==== THE DESCRIPTION ==== */
/* the sample's description arrives after the frame: its paragraph keeps the room of the longest one */
#branch + p { min-height: 3.4em; }
@media (max-width: 480px) { #branch + p { min-height: 6.6em; } }
