/* Git Code Review, on top of the Failover LB stylesheet.
   Only the pieces that site does not already have: the pipeline diagrams, the
   build walkthrough and a few finding shaped bits of chrome. */

:root{
  --gcr-crit:#d4183d; --gcr-high:#e8590c; --gcr-med:#b8860b;
  --gcr-low:#4c6ef5;  --gcr-ok:#2b8a3e;

  /* This file was written against --border and --border-strong.  The
     stylesheet underneath calls them --line and --line-strong and has never
     defined the other two, and an undefined custom property inside a border
     shorthand throws the whole declaration away.  So the frame on the pipeline
     diagram, the boxes in the stat band, the walkthrough, the rules between
     rows of the comparison table and the outline on every screenshot were all
     simply not drawn.  Aliased here rather than in fifteen places, and by
     reference so both themes still work. */
  --border: var(--line);
  --border-strong: var(--line-strong);

  /* Same story, same cause.  Without these, `color:var(--muted)` fell back to
     the inherited colour, so nothing on this page was ever actually muted, and
     `background:var(--surface)` fell back to transparent, which is why the
     sticky header on the comparison table had rows scrolling through it. */
  --text: var(--fg);
  --muted: var(--fg-muted);
  --surface: var(--bg-raised);
  --surface-2: var(--bg-inset);
  --accent: var(--brand);
  --gcr-brand: var(--brand);
}
:root[data-theme=dark],
@media (prefers-color-scheme:dark){}

/* An icon dropped into prose, a heading or a list sizes to the text around
   it.  A bare svg with only a viewBox fills whatever contains it, which on a
   hero heading is the whole column. */
.eyebrow svg, h2 svg, h3 svg, h4 svg, p svg, li svg, td svg, .lede svg{
  width:1.05em;height:1.05em;flex:none;vertical-align:-.14em;margin-right:.15em}
.card-icon svg{width:22px;height:22px}

/* ---- severity chips ---------------------------------------------------- */
.sev{display:inline-block;padding:.12em .6em;border-radius:999px;
     font-size:var(--step--2);font-weight:650;letter-spacing:.01em;
     border:1px solid currentColor;line-height:1.5}
.sev-critical{color:var(--gcr-crit)} .sev-high{color:var(--gcr-high)}
.sev-medium{color:var(--gcr-med)}    .sev-low{color:var(--gcr-low)}
.sev-ok{color:var(--gcr-ok)}

/* ---- the numbers band -------------------------------------------------- */
.stat-band{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
           margin:2rem 0}
.stat-band .stat{text-align:center;padding:1.1rem .75rem;border:1px solid var(--border);
                 border-radius:var(--radius);background:var(--surface)}
.stat-band .n{font-size:var(--step-4);font-weight:700;line-height:1.05;
              font-variant-numeric:tabular-nums}
.stat-band .l{font-size:var(--step--1);color:var(--muted);margin-top:.3rem}

/* ---- pipeline diagrams -------------------------------------------------- */
.pipe-wrap{border:1px solid var(--border);border-radius:var(--radius);
           background:var(--surface);padding:1.25rem;margin:1.5rem 0;overflow-x:auto}
.pipe-wrap svg{display:block;width:100%;height:auto;min-width:680px}
/* A drawing with four boxes in it reads perfectly well at the width of a
   documentation column, and a page that scrolls sideways to show somebody a
   diagram has lost the argument before it starts. */
.pipe-wrap.pipe-fit{overflow-x:visible}
.pipe-wrap.pipe-fit svg{min-width:0}
.pipe-legend{display:flex;flex-wrap:wrap;gap:1rem;margin-top:.9rem;
             font-size:var(--step--1);color:var(--muted)}
.pipe-legend span{display:inline-flex;align-items:center;gap:.4rem}
.pipe-legend i{width:.85rem;height:.85rem;border-radius:3px;display:inline-block}

/* Diagram palette, readable in both themes. */
.d-node{fill:var(--surface-2,#f4f5f8);stroke:var(--border-strong,#b9bfcc);stroke-width:1.5}
.d-label{fill:var(--text);font-size:12.5px;font-family:inherit;font-weight:600}
.d-sub{fill:var(--muted);font-size:11px;font-family:inherit}
/* The band heading over each row of a diagram, and the note under it.  Both
   have to be sized here: an unsized SVG text takes the page font size, which
   on the pipeline diagram ran the note past the right hand edge of the
   viewBox and cut the end of the sentence off. */
.d-band{fill:var(--text);font-size:12px;font-family:inherit;font-weight:700;
        letter-spacing:.02em}
.d-note{fill:var(--muted);font-size:11.5px;font-family:inherit}
.d-flow{stroke:var(--border-strong,#98a2b3);stroke-width:2;fill:none;marker-end:url(#arrow)}
.d-bad{stroke:var(--gcr-crit);stroke-width:2.2;fill:none;marker-end:url(#arrowbad);
       stroke-dasharray:6 4}
.d-good{stroke:var(--gcr-ok);stroke-width:2.2;fill:none;marker-end:url(#arrowgood)}
.d-gate{fill:rgba(43,138,62,.10);stroke:var(--gcr-ok);stroke-width:1.6}
.d-risk{fill:rgba(212,24,61,.10);stroke:var(--gcr-crit);stroke-width:1.6;stroke-dasharray:5 3}
.d-risk-label{fill:var(--gcr-crit);font-size:11.5px;font-weight:650;font-family:inherit}
.d-gate-label{fill:var(--gcr-ok);font-size:11.5px;font-weight:650;font-family:inherit}
:root[data-theme=dark] .d-node{fill:#161a23;stroke:#39404f}

/* ---- the build walkthrough --------------------------------------------- */
.walk{border:1px solid var(--border);border-radius:var(--radius);
      background:var(--surface);overflow:hidden;margin:1.5rem 0}
.walk-stage{position:relative;padding:1.25rem;overflow-x:auto}
.walk-stage svg{display:block;width:100%;height:auto;min-width:720px}
.walk-bar{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap;
          padding:.85rem 1.25rem;border-top:1px solid var(--border);
          background:var(--surface-2,rgba(0,0,0,.02))}
.walk-steps{display:flex;gap:.4rem;flex-wrap:wrap;flex:1}
.walk-steps button{font:inherit;font-size:var(--step--1);padding:.32rem .7rem;
                   border-radius:999px;border:1px solid var(--border-strong);
                   background:transparent;color:var(--muted);cursor:pointer}
.walk-steps button[aria-current=true]{background:var(--accent,#4739e0);
                   border-color:var(--accent,#4739e0);color:#fff}
.walk-caption{padding:1rem 1.25rem;border-top:1px solid var(--border);
              font-size:var(--step--1);min-height:5.5rem}
.walk-caption h4{margin:0 0 .35rem;font-size:var(--step-0)}
.walk-caption p{margin:0;color:var(--muted)}
.walk .w-step{opacity:.22;transition:opacity .45s ease}
.walk .w-step.on{opacity:1}
.walk .w-pulse{opacity:0}
.walk .w-step.on .w-pulse{opacity:1;animation:gcrPulse 1.6s ease-in-out infinite}
@keyframes gcrPulse{0%,100%{r:5;opacity:.9}50%{r:9;opacity:.25}}
@media (prefers-reduced-motion:reduce){
  .walk .w-step{opacity:1}
  .walk .w-step.on .w-pulse{animation:none}
}

/* ---- comparison table --------------------------------------------------- */
.cmp-table{width:100%;border-collapse:collapse;font-size:var(--step--1)}
/* The wrapper is for narrow screens.  On a wide one it must not be a scroll
   container: `overflow-x:auto` makes overflow-y `auto` as well, and a sticky
   row inside then resolves against that box rather than the viewport, so it
   never actually sticks. */
.cmp-scroll{overflow-x:auto}
@media (min-width:1200px){ .cmp-scroll{overflow:visible} }
.cmp-table th,.cmp-table td{padding:.6rem .7rem;border-bottom:1px solid var(--border);
                            vertical-align:top;text-align:left}
.cmp-table thead th{background:var(--surface);
                    border-bottom:2px solid var(--border-strong)}
.cmp-table td.score{text-align:center;white-space:nowrap}
.stars i{font-style:normal;color:var(--border-strong);font-size:.95em}
.stars i.on{color:#e8a317}
.verdict{font-size:var(--step--2);font-weight:650;padding:.1em .55em;border-radius:999px;
         border:1px solid currentColor}
.v-ahead{color:var(--gcr-ok)} .v-behind{color:var(--gcr-crit)} .v-level{color:var(--muted)}
.cmp-why{color:var(--muted);max-width:60ch}
.cmp-more{margin-top:.3rem}
.cmp-more summary{cursor:pointer;color:var(--gcr-brand,#4739e0);font-size:var(--step--1);list-style:none;display:inline-block}
.cmp-more summary::-webkit-details-marker{display:none}
.cmp-more summary::after{content:" +";font-weight:600}
.cmp-more[open] summary::after{content:" \2212"}
.cmp-more[open] summary{margin-bottom:.4rem}
.cmp-more summary:hover{text-decoration:underline}
/* The band that opens a section carries the product names as well, so a row
   halfway down a long section still says which column belongs to whom without
   scrolling back to the top. */
/* This is the row that sticks, rather than the table head, because it is the
   one that answers both questions at once: which section you are in and which
   column belongs to whom. */
.cmp-section th{background:var(--surface-2,rgba(0,0,0,.03));text-align:left;
                vertical-align:bottom;position:sticky;top:var(--nav-h);z-index:2;
                box-shadow:0 1px 0 var(--line)}
.cmp-section th:first-child{font-weight:700;font-size:var(--step-0);color:var(--text)}
.cmp-section th:not(:first-child){font-weight:650;font-size:var(--step--2);
                color:var(--muted);letter-spacing:.01em}
.cmp-section .cmp-verdict-head{text-align:left}

/* ---- screenshot gallery ------------------------------------------------- */
.shots{display:grid;gap:1.5rem;grid-template-columns:repeat(auto-fit,minmax(330px,1fr))}
.shot{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;
      background:var(--surface)}
.shot img{display:block;width:100%;height:auto;border-bottom:1px solid var(--border)}
.shot figcaption{padding:.7rem .9rem;font-size:var(--step--1);color:var(--muted)}
.shot figcaption b{color:var(--text);display:block;font-size:var(--step-0);
                   margin-bottom:.15rem}
.shot-wide{grid-column:1/-1}

/* ---- misc --------------------------------------------------------------- */
.lede{font-size:var(--step-1);color:var(--muted);max-width:62ch}
.two-col{display:grid;gap:2rem;grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.plain-english{border-left:3px solid var(--accent,#4739e0);padding:.15rem 0 .15rem 1rem;
               margin:1.25rem 0;color:var(--muted)}
.plain-english b{color:var(--text)}

/* Features index: the one line of honesty on each card. */
.feature-limit {
  margin: var(--sp-3) 0 0;
  padding-top: var(--sp-3);
  border-top: 1px dashed var(--line);
  font-size: var(--step--2);
  color: var(--fg-faint);
  line-height: 1.5;
}
.feature-limit span {
  display: inline-block;
  font-weight: 660;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 0.68rem;
  color: var(--warn);
  margin-right: 0.35rem;
}
.next-prev a strong { color: var(--fg-strong); font-weight: 640; }

/* A feature page is prose, not a landing page: smaller headings, tighter rhythm. */
.feature-prose { max-width: 68ch; }
.feature-prose h2 {
  font-size: var(--step-2);
  margin-top: var(--sp-7);
  margin-bottom: var(--sp-3);
}
.feature-prose h2:first-child { margin-top: 0; }
.feature-prose .note { margin-top: var(--sp-7); }

/* The numbered stages on How it works, as two columns on a wide screen.
   A single 68ch column of prose in a 1200px wrap left about 450px of the page
   doing nothing, which on a page whose whole job is to explain the shape of
   the thing looked like an accident.  So the heading moves into a rail on the
   left and the prose sits beside it: the block uses the width, and the line
   length stays somewhere a person can actually read.

   Not called `steps`.  That is the numbered list on Getting started and on
   every how-to page, and it sets `margin:0` on its paragraphs. */
.stages { display: grid; gap: var(--sp-7); margin-top: var(--sp-6); }
.stage { display: grid; gap: var(--sp-4); }
.stage > h2 {
  font-size: var(--step-2);
  margin: 0;
  scroll-margin-top: calc(var(--nav-h) + 24px);
}
.stage-body { max-width: 74ch; }
.stage-body p { margin: 0 0 var(--sp-4); }
.stage-body > :last-child { margin-bottom: 0; }
@media (min-width: 72rem) {
  .stages { gap: var(--sp-8); }
  /* Only this wide.  Splitting sooner makes the prose column narrower than the
     single column it replaced, which is the opposite of the point. */
  .stage {
    grid-template-columns: minmax(12rem, 18rem) minmax(0, 1fr);
    gap: var(--sp-6);
    align-items: start;
  }
  /* The rule runs under the whole row rather than under the prose alone, so
     the rail reads as part of the stage rather than as a floating heading. */
  .stage + .stage { border-top: 1px solid var(--line); padding-top: var(--sp-7); }
}
/* The limits every feature page ends with.  Same rail as the sections above it
   so the page keeps one spine, with the warning colour carried on the heading
   rather than only on the box. */
.stage-warn { color: var(--warn); display: flex; align-items: flex-start; gap: .45rem; }
/* Nudged onto the first line rather than centred against a heading that wraps
   to two, which leaves it floating between them. */
.stage-warn svg { width: 1em; height: 1em; flex: none; margin-top: .2em; }
.stages + .next-prev { margin-top: var(--sp-7); }

/* Screenshots: the frame and the zoom are the site's own.  Two up rather than
   three, because a screenshot of a dense interface is unreadable at a third of
   the page and the point of the page is to be able to read it. */
.shot-grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
  margin-top: var(--sp-5);
  align-items: start;
}
@media (min-width: 900px) { .shot-grid { grid-template-columns: 1fr 1fr; } }
.shot-grid figure.shot { margin: 0; }
.shot-grid figure.shot figcaption {
  margin-top: var(--sp-3);
  font-size: var(--step--1);
  line-height: 1.55;
  text-align: left;
  color: var(--fg-muted, var(--muted));
}
.shot-grid figure.shot figcaption strong { color: var(--fg-strong, var(--text)); }

/* Numbered steps.  The stylesheet underneath already numbers them, with a
   badge and a connector line down the list, so this only sets the text.  It
   used to lay out a second badge of its own as well, which is why every step
   on Getting started and on every how-to guide carried two numbers. */
.steps { margin: var(--sp-5) 0 0; }
.steps h3 { margin: 0 0 0.25rem; font-size: var(--step-0); }
.steps p { margin: 0; }
.steps pre.code { margin: var(--sp-3) 0 0; }

/* Roadmap list. */
.road { list-style: none; margin: var(--sp-5) 0 0; padding: 0; display: grid; gap: var(--sp-4); }
.road-item {
  border: 1px solid var(--line, var(--border));
  border-left: 3px solid var(--line-strong, #b9bfcc);
  border-radius: var(--radius);
  padding: var(--sp-4) var(--sp-5);
  background: var(--bg-raised, var(--surface));
}
.road-next { border-left-color: var(--gcr-brand, #4739e0); }
.road-head { display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap; }
.road-head h3 { margin: 0 0 var(--sp-2); font-size: var(--step-0); }
.road-badge {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--surface-2, rgba(0,0,0,.05));
  color: var(--muted);
}
.road-next .road-badge { background: rgba(71,57,224,.12); color: var(--gcr-brand, #4739e0); }
.road-item p { margin: 0; }

/* Documentation body: rendered from the project's own markdown. */
.doc-body { min-width: 0; }
.doc-body h1 { margin-bottom: var(--sp-3); }
.doc-body .lead { margin-bottom: var(--sp-6); }
.doc-body blockquote {
  margin: 0 0 var(--sp-5);
  padding: var(--sp-3) var(--sp-5);
  border-left: 3px solid var(--gcr-brand, #4739e0);
  background: var(--surface-2, rgba(0,0,0,.03));
  border-radius: 0 var(--radius) var(--radius) 0;
  color: var(--muted);
}
.doc-body blockquote p { margin: 0; }
.doc-body hr { border: 0; border-top: 1px solid var(--line, var(--border)); margin: var(--sp-7) 0; }
.toc li.toc-3 a { padding-left: 1.4rem; font-size: 0.94em; }
.doc-body h2 { font-size: var(--step-2); margin-top: var(--sp-7); }
.doc-body h3 { font-size: var(--step-1); margin-top: var(--sp-6); }
.doc-body h4 { font-size: var(--step-0); }

/* Questions. */
.qa { margin-top: var(--sp-5); border-top: 1px solid var(--line, var(--border)); }
.qa details { border-bottom: 1px solid var(--line, var(--border)); }
.qa summary {
  cursor: pointer;
  padding: var(--sp-4) 2rem var(--sp-4) 0;
  font-weight: 620;
  color: var(--fg-strong, var(--text));
  list-style: none;
  position: relative;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary::after {
  content: "+";
  position: absolute;
  right: 0.25rem;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1.25rem;
  font-weight: 400;
  color: var(--muted);
}
.qa details[open] summary::after { content: "\2212"; }
.qa summary:hover { color: var(--gcr-brand, #4739e0); }
.qa details p {
  margin: 0 0 var(--sp-4);
  max-width: 74ch;
  color: var(--muted);
  line-height: 1.65;
}

/* The search box has its own clear button, so hide the browser's. */
.search-shell input[type="search"]::-webkit-search-cancel-button,
.search-shell input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }

/* A screen recording, framed the way the screenshots are.  Sized by its own
   aspect ratio so the page does not jump when the poster arrives, and never
   wider than the column it sits in. */
.clip { margin: 0; }
.clip video {
  width: 100%; height: auto; aspect-ratio: 1440 / 900; display: block;
  border: 1px solid var(--border); border-radius: 10px; background: #0b0d12;
}
.clip figcaption {
  margin-top: var(--sp-3); color: var(--muted); font-size: .95rem;
  max-width: 68ch;
}
/* The same clip as a file.  Plenty of these installations are on a network
   that will not stream anything, so the recording has to be takeable with
   you. */
.clip-get {
  display: inline-flex; align-items: center; gap: .4rem;
  margin-left: .5rem; white-space: nowrap; font-weight: 500;
}
.clip-get svg { width: 14px; height: 14px; }

/* The changelog: a label and a sentence, rather than a bulleted list of
   sentence fragments nobody can scan. */
.changelog { margin: var(--sp-4) 0 0; }
.changelog dt { font-weight: 600; margin-top: var(--sp-4); }
.changelog dd { margin: var(--sp-1) 0 0; color: var(--muted); max-width: 74ch; }

/* ------------------------------------------------------------ site search
   The dialog behind the magnifier in the header.  Same component as the
   sister sites, so it is deliberately the same markup and the same class
   names: somebody who has seen one of these has seen all of them. */
.site-search {
  border: 0;
  padding: 0;
  background: transparent;
  width: min(680px, calc(100vw - 2rem));
  max-height: none;
  margin: 10vh auto auto;
  color: var(--fg);
}
.site-search::backdrop { background: rgba(5, 7, 12, 0.55); backdrop-filter: blur(3px); }
.ss-box { background: var(--bg-raised); border: 1px solid var(--line-strong); border-radius: var(--radius-lg); box-shadow: var(--shadow-3); overflow: hidden; }
.ss-field { display: flex; align-items: center; gap: 0.6rem; padding: 0.8rem 1rem; border-bottom: 1px solid var(--line); }
.ss-field > svg { width: 20px; height: 20px; color: var(--fg-muted); flex: none; }
.ss-field input { flex: 1; min-width: 0; border: 0; background: transparent; font: inherit; font-size: var(--step-0); color: var(--fg-strong); outline: none; }
.ss-field input::-webkit-search-cancel-button { display: none; }
.ss-close { border: 1px solid var(--line); background: var(--bg-inset); color: var(--fg-muted); border-radius: 6px; font-size: var(--step--2); padding: 0.2rem 0.45rem; cursor: pointer; }
.ss-results { list-style: none; margin: 0; padding: 0.4rem; max-height: min(60vh, 520px); overflow-y: auto; }
.ss-results a { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.1rem 0.75rem; padding: 0.6rem 0.75rem; border-radius: var(--radius-sm); text-decoration: none; color: var(--fg); }
.ss-results [aria-selected="true"] a, .ss-results a:hover { background: var(--brand-soft); }
.ss-t { font-weight: 600; color: var(--fg-strong); }
.ss-s { font-size: var(--step--2); color: var(--fg-faint); white-space: nowrap; align-self: center; }
.ss-d { grid-column: 1 / -1; font-size: var(--step--1); color: var(--fg-muted); line-height: 1.45; }
.ss-results mark { background: color-mix(in oklab, var(--brand) 22%, transparent); color: inherit; border-radius: 3px; padding: 0 1px; }
.ss-foot { margin: 0; padding: 0.55rem 1rem; border-top: 1px solid var(--line); font-size: var(--step--2); color: var(--fg-faint); }
@media (max-width: 560px) {
  .site-search { margin-top: 0.75rem; }
  .ss-s { display: none; }
}
/* Four buttons in the header on the smallest phones is one too many, and the
   menu holds Install it there anyway. */
@media (max-width: 400px) {
  .nav-tools { gap: 0.3rem; }
  .nav-tools .btn-sm { display: none; }
}
