:root {
  --bg: #0b0f18;
  --panel: #161a25;
  --panel-2: #1f2430;
  --border: #2c3341;
  --text: #dadee8;
  --dim: #81899c;
  --accent: #83bdf8;
  --ok: #4eb068;
  --bad: #e45d58;
  --warn: #e1a035;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
}
code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; color: #c8cedb; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
.dim { color: var(--dim); }

/* The hamburger is a checkbox, not a <details>: a closed disclosure hides its
   own content and author CSS cannot force it back, which is what blanked the
   desktop nav. Here both states are ours to set. */
.burger-btn { display: none; }

.topbar {
  display: flex; align-items: center; gap: 32px;
  padding: 12px 24px; background: var(--panel); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 10;
}
/* The brand is a link to the landing page, so it has to opt out of link colour. */
.brand { font-weight: 600; letter-spacing: .2px; }
a.brand { color: inherit; }
a.brand:hover { text-decoration: none; }
.brand .logo { display: block; width: 28px; height: 28px; }
/* display:contents so the two navs sit in the topbar's own flex row; the auto
   margin moves the second one and the user menu to the right together. */
.nav-group { display: contents; }
.topbar nav { display: flex; gap: 18px; }
/* Colour, not an underline: nav links are already obviously interactive, and the
   underline is a prose convention the global a:hover rule drags in here. */
.topbar nav a { color: var(--text); }
.topbar nav a:hover { color: var(--accent); text-decoration: none; }
.topbar .nav-meta { margin-left: auto; }
.topbar .nav-meta a { color: var(--dim); }
.topbar .nav-meta a:hover { color: var(--text); text-decoration: none; }
.topbar .user { margin-left: 0; }

.wrap { max-width: 1180px; margin: 0 auto; padding: 24px; }
h1 { font-size: 20px; margin: 4px 0 20px; font-weight: 600; }
h2 { font-size: 14px; margin: 0 0 12px; font-weight: 600; color: #e8ebf2; }
.h2-link { margin-left: 8px; font-size: 12px; font-weight: 400; }
.cell-sub { margin-top: 2px; font-size: 11px; color: var(--dim); }
.back { display: inline-block; margin-bottom: 8px; font-size: 13px; }

.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 20px; }
.tile { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 18px 20px; }
.tile-label { color: var(--dim); font-size: 12px; text-transform: uppercase; letter-spacing: .5px; }
.tile-value { font-size: 32px; font-weight: 650; margin-top: 6px; }
.tile-warn .tile-value { color: var(--warn); }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 20px; }
.card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 18px 20px; margin-bottom: 20px; }
.grid-2 canvas { max-height: 240px; } /* overview timeseries only; the waterfall sizes itself */
.chart-box { position: relative; height: 260px; } /* fixed-height wrapper for a standalone responsive chart */

table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border); }
th { color: var(--dim); font-weight: 500; font-size: 12px; text-transform: uppercase; letter-spacing: .4px; }
tr:last-child td { border-bottom: none; }
td code { white-space: nowrap; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.ts { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* build_id is a kaniko test name, up to ~95 characters, and sits in a nowrap
   code cell no column width can hold. Truncated with the full value in title. */
.trunc { max-width: 26ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Middle truncation. The tail never shrinks because that is where these ids
   differ; the head takes the ellipsis and gives up whatever width is short. */
.midtrunc { display: flex; max-width: 30ch; }
.midtrunc .mt-head { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.midtrunc .mt-tail { flex: 0 0 auto; white-space: nowrap; }
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--text); }
/* Fixed-width caret slot so the ▲/▼ appearing doesn't shift the column border. */
.caret { display: inline-block; width: 1em; margin-left: 4px; text-align: center; }
.bad { color: var(--bad); }

.heat {
  display: inline-block; padding: 1px 7px; border-radius: 5px;
  background: color-mix(in srgb, var(--bad) calc(var(--v) * 100%), transparent);
  color: #fff;
}

.badge { display: inline-block; padding: 1px 8px; border-radius: 20px; font-size: 11.5px; background: var(--panel-2); border: 1px solid var(--border); }
.badge.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 40%, var(--border)); }
.badge.bad { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, var(--border)); }
.btn { display: inline-block; padding: 3px 10px; border-radius: 6px; border: 1px solid var(--border); background: var(--panel-2); font-size: 12.5px; cursor: pointer; }
.btn:hover { border-color: var(--accent); text-decoration: none; }
/* align-items keeps the buttons their natural height: the flex td would otherwise
   stretch them to the row height whenever another cell wraps. */
.row-actions { display: flex; gap: 6px; justify-content: flex-end; align-items: center; white-space: nowrap; }
.pager { display: flex; gap: 12px; align-items: center; justify-content: flex-end; margin-top: 14px; }
/* A filter as the column title: the column name, and its value below in plain
   case. The row's other titles top-align so all names share a line. */
tr:has(> th.filter) > th { vertical-align: top; }
th.filter label { display: block; }
th.filter select {
  display: block; max-width: 200px; padding: 2px 4px; margin: 4px 0 0 -5px; border: 1px solid transparent; border-radius: 5px;
  font: inherit; text-transform: none; letter-spacing: 0; color: inherit; background: transparent; cursor: pointer;
}
th.filter select:hover { color: var(--text); border-color: var(--border); }
th.filter select.active { color: var(--text); background: var(--panel-2); border-color: var(--border); }
th.filter option, th.filter optgroup { text-transform: none; letter-spacing: 0; color: var(--text); background: var(--panel-2); }
.btn.disabled { opacity: .4; pointer-events: none; }

.meta dl { display: grid; grid-template-columns: repeat(2, 1fr); gap: 4px 32px; margin: 0; }
.meta dl > div { display: flex; gap: 10px; padding: 4px 0; border-bottom: 1px solid var(--border); }
.meta dt { color: var(--dim); min-width: 82px; }
.meta dd { margin: 0; }

/* Category colours (shared by summary bar, legend, waterfall) */
.cat-build       { background: #3fb950; }
.cat-network     { background: #2d6fbe; }
.cat-kaniko      { background: #996b00; }
.cat-untraced    { background: repeating-linear-gradient(135deg, #996b00 0 6px, #634300 6px 12px); }
.cat-unaccounted { background: #232936; }
/* Keep in step with CAT_COLOR.frame in app.js: the chart colours frames there,
   the legend swatch is drawn here. */
.cat-frame       { background: #5b6376; }

/* Summary "where the time went" stacked bar */
.summary-bar { display: flex; height: 22px; border-radius: 6px; overflow: hidden; background: var(--panel-2); }
.summary-bar .seg { height: 100%; }
.summary-bar .seg:hover { filter: brightness(1.15); }

.legend-summary { margin: 12px 0 0; }
.legend { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 14px; font-size: 12.5px; color: var(--dim); }
.legend .key { display: inline-flex; align-items: center; gap: 6px; }
.legend .sw { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }

/* The waterfall page runs wider than the default so the chart keeps room even
   with the Dockerfile panel beside it */
.wrap-wide { max-width: 1680px; }

/* Waterfall chart (Chart.js) — height is set by JS from the span count. Side by
   side with the Dockerfile source, which is capped narrow so the chart keeps the
   majority of the width; stacks below on narrow screens (see media query). */
.wf-layout { display: flex; gap: 16px; align-items: flex-start; }
.wf-chart { position: relative; flex: 1 1 0; min-width: 0; min-height: 120px; }

/* Dockerfile source panel, beside the chart: capped width, sticky so it stays in
   view while the tall waterfall scrolls; scrolls in both axes (long lines don't
   wrap); cross-linked with the chart on hover. */
.df-panel {
  flex: 0 1 auto; max-width: 460px;
  position: sticky; top: 8px;
  max-height: calc(100vh - 24px); overflow: auto;
  border: 1px solid var(--border); border-radius: 8px; background: var(--panel);
}
.df-head { position: sticky; top: 0; padding: 7px 12px; background: var(--panel); border-bottom: 1px solid var(--border); font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--dim); }
.df-code { padding: 8px 0; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }
.df-line { display: flex; padding: 1px 16px 1px 0; min-height: 1.5em; cursor: default; }
.df-line[data-hascmd] { cursor: pointer; }
.df-line:hover, .df-line.hl { background: rgba(131,189,248,0.16); box-shadow: inset 3px 0 0 var(--accent); }
.df-num { flex: 0 0 auto; width: 26px; padding-right: 10px; margin-right: 10px; text-align: right; color: var(--dim); border-right: 1px solid var(--border); user-select: none; }
.df-text { white-space: pre; color: #c8cedb; }

/* History page: Dockerfile heatmap — source tinted by build time, per-run stats
   pinned on the right, cache-buster flagged. */
.dfh { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }
.dfh-row { display: flex; align-items: center; gap: 12px; padding: 1px 12px 1px 0; min-height: 1.7em; }
.dfh-row .df-num { flex: 0 0 auto; }
.dfh-text { flex: 1 1 auto; min-width: 0; white-space: pre; overflow: hidden; text-overflow: ellipsis; color: #c8cedb; }
.dfh-row:not(.on) .dfh-text { color: var(--dim); }
.dfh-stats { flex: 0 0 auto; display: flex; align-items: center; gap: 12px; font-family: -apple-system, system-ui, sans-serif; font-size: 11.5px; color: var(--dim); }
.dfh-stat { white-space: nowrap; }
.dfh-stat.strong { color: #e0e4ec; font-weight: 600; }
.dfh-buster { white-space: nowrap; color: var(--bad); border: 1px solid color-mix(in srgb, var(--bad) 45%, var(--border)); border-radius: 20px; padding: 0 8px; font-size: 11px; }

@media (max-width: 900px) {
  .tiles, .grid-2 { grid-template-columns: 1fr; }
}

/* Waterfall stacks (Dockerfile below) before it gets too cramped side by side. */
@media (max-width: 1000px) {
  .wf-layout { flex-direction: column; }
  .df-panel { max-width: none; width: 100%; position: static; max-height: 60vh; }
}

@media (max-width: 640px) {
  .wrap { padding: 14px; }
  .topbar { gap: 14px; padding: 12px 14px; flex-wrap: wrap; }
  h1 { font-size: 18px; }
  .tile-value { font-size: 26px; }
  .meta dl { grid-template-columns: 1fr; }

  /* Wide content scrolls inside its own box so the page body never scrolls
     sideways: tables become horizontally scrollable, and the heatmap sizes its
     rows to content (full line + stats) and scrolls rather than truncating. */
  table { display: block; overflow-x: auto; white-space: nowrap; }
  .dfh { overflow-x: auto; }
  .dfh-row { width: max-content; min-width: 100%; }
  .dfh-text { flex: 0 0 auto; overflow: visible; text-overflow: clip; }
}

/* Facts panel that follows the pointer over the Dockerfile source. */
.df-facts {
  display: none;
  position: fixed;
  z-index: 40;
  max-width: 380px;
  padding: 6px 9px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
  pointer-events: none;
}


/* Side tile: a card that stops at a column width instead of spanning the page. */
.side-tile { max-width: 420px; }
.side-tile table { font-size: 12px; }
.side-tile td:last-child { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Dockerfile lines whose stage was eliminated: present in the source, never run. */
.df-line.unbuilt .df-text { opacity: 0.38; }
.df-line.unbuilt .df-num { opacity: 0.28; }

/* The build plan, verbatim as kaniko renders it for --dryrun. */
.plan { margin: 0; max-height: 340px; overflow: auto; font-size: 12px; line-height: 1.5;
        font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--text); }

/* Source panel tabs: Dockerfile as written, or the plan derived from it. */
.pane-tab { background: none; border: 0; padding: 2px 0; margin-right: 14px; cursor: pointer;
            font: inherit; font-size: 12px; color: var(--dim); border-bottom: 2px solid transparent; }
.pane-tab.active { color: var(--text); border-bottom-color: var(--accent); }

/* Signed-in user, pushed to the far right of the topbar. margin-left:auto rather
   than a fixed width so it stays put as the nav grows. */
.user { margin-left: auto; position: relative; font-size: 13px; }
.user-menu > summary {
  display: flex; align-items: center; gap: 8px;
  cursor: pointer; list-style: none; padding: 4px 8px 4px 4px;
  border: 1px solid transparent; border-radius: 999px;
}
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu > summary:hover { border-color: var(--border); background: var(--bg); }
.user-menu[open] > summary { border-color: var(--border); background: var(--bg); }
.avatar {
  display: grid; place-items: center; width: 24px; height: 24px; border-radius: 50%;
  background: var(--accent); color: var(--panel); font-size: 11px; font-weight: 700;
}
.user-name { max-width: 14ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-panel {
  position: absolute; right: 0; top: calc(100% + 6px); min-width: 210px; z-index: 20;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px; display: grid; gap: 6px;
}
.user-row { display: flex; justify-content: space-between; gap: 12px; }
.user-signout {
  margin-top: 4px; padding-top: 8px; border-top: 1px solid var(--border); color: var(--text);
}
/* The initial sits underneath as the fallback: if the remote avatar fails, the
   image is removed and the letter is already in place. */
.avatar { position: relative; overflow: hidden; }
.avatar img { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
/* Admin mode: a ring on the avatar. Same signal, no extra box in the bar. */
.avatar.is-admin { box-shadow: 0 0 0 2px var(--warn); }

.signin {
  max-width: 340px; margin: 9vh auto; padding: 24px;
  display: grid; gap: 18px; justify-items: center; text-align: center;
}
/* The sign-in page carries the full lockup rather than the topbar mark. */
.signin-brand { display: grid; justify-items: center; gap: 14px; }
.signin-mark { display: block; width: 104px; height: auto; }
.signin-word { display: block; width: 132px; height: auto; }
.signin-btn { display: flex; align-items: center; justify-content: center; gap: 10px; }
.provider-icon { width: 16px; height: 16px; flex: 0 0 auto; fill: currentColor; }
/* Signed in: the same control, marked good rather than replaced by prose. */
.signin-btn.is-signed-in { border-color: var(--ok); }
.signin-btn.is-signed-in:hover { border-color: var(--ok); filter: brightness(1.1); }
.motto { margin: -6px 0 0; font-size: 13px; color: var(--dim); font-style: italic; }
.signin-msg {
  margin: 0; padding: 8px 12px; font-size: 13px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
}
.signin-actions { display: grid; gap: 10px; width: 100%; }
.signin-btn {
  display: block; padding: 10px 16px; border-radius: 8px; font-size: 13px;
  background: var(--panel); border: 1px solid var(--border); color: var(--text);
}
.signin-btn:hover { border-color: var(--accent); }
/* A button, not a link: switching tenant changes session state, so it posts.
   Styled back to the plain row it reads as. */
.user-tenant-form { display: block; }
.user-tenant {
  display: block; width: 100%; padding: 4px 6px; border-radius: 6px; color: var(--text);
  background: none; border: 0; font: inherit; text-align: left; cursor: pointer;
}
.user-tenant:hover { background: var(--bg); }
.user-tenant.is-active { color: var(--accent); }
/* Reading someone else's tenant is marked wherever it can be reached or is in
   effect, so it is never mistaken for your own data. */
.user-tenant .foreign {
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--warn); border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--border));
  border-radius: 20px; padding: 0 6px;
}
.pending-count {
  display: inline-block; min-width: 16px; padding: 0 5px; border-radius: 20px;
  background: var(--warn); color: var(--panel); font-size: 11px; font-weight: 700; text-align: center;
}
.warn-msg { border-color: color-mix(in srgb, var(--warn) 45%, var(--border)); color: var(--warn); }

.access { max-width: 560px; }
.access-intro { text-align: left; }
.access-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; width: 100%; }
.access-item {
  display: grid; gap: 8px; padding: 12px; text-align: left;
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
}
.access-account { display: flex; gap: 8px; align-items: baseline; }
.access-forge { font-weight: 600; }
.access-form { display: grid; gap: 8px; }
.access-note {
  padding: 6px 8px; border-radius: 6px; font: inherit; font-size: 12.5px;
  background: var(--bg); border: 1px solid var(--border); color: var(--text);
}
.access-form button { cursor: pointer; }

.user-admin { margin-top: 4px; padding-top: 8px; border-top: 1px solid var(--border); }
.user-admin button {
  all: unset; cursor: pointer; color: var(--warn); font: inherit; width: 100%; text-align: left;
}
.user-signout button {
  all: unset; cursor: pointer; color: var(--text); font: inherit; width: 100%; text-align: left;
}

/* Docs and landing: the app renders both, so these live here rather than in a
   second stylesheet. */
.docs-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.docs-card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 14px 18px; }
.docs-meta { margin-bottom: 8px; font-size: 12px; }
.docs-notes { margin: 12px 0 0; padding-left: 18px; color: var(--dim); font-size: 12.5px; }

/* The snippet is wide and must not stretch the page: the pre scrolls on its own
   axis, and min-width:0 is what lets it shrink inside the card rather than
   forcing the card wider than the viewport. */
.docs-code {
  margin: 0; padding: 14px 16px; max-width: 100%; min-width: 0; overflow-x: auto;
  border-radius: 8px; background: var(--bg); border: 1px solid var(--border);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; line-height: 1.55;
}
.docs-code code { display: block; white-space: pre; color: inherit; background: none; padding: 0; }
/* A diff gutter as pseudo-content, so copying the snippet copies valid YAML. */
.docs-code .line::before { content: " "; flex: none; width: 2ch; color: #3fb950; user-select: none; }
.docs-code.chroma .line.hl { background-color: rgba(46, 160, 67, 0.15); }
.docs-code .line.hl::before { content: "+"; }

.prose h2 { font-size: 14px; margin: 22px 0 10px; }
.prose h2:first-child { margin-top: 0; }
.prose ol, .prose ul { padding-left: 20px; }
.prose li { margin: 4px 0; }
.prose blockquote {
  margin: 14px 0; padding: 8px 14px; color: var(--dim);
  border-left: 2px solid var(--border); background: var(--panel-2); border-radius: 0 6px 6px 0;
}
.prose code { background: var(--panel-2); padding: 1px 5px; border-radius: 4px; }

.landing { max-width: 1080px; margin: 0 auto; padding: 0 24px 64px; }
.hero {
  padding: 72px 0 40px;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 56px; align-items: center;
}
.hero-mark { display: grid; justify-items: center; }
.hero-crystal { display: block; width: 260px; height: auto; }
/* The wordmark is the heading, so the h1 carries no type of its own. */
.hero-brand { margin: 0 0 10px; line-height: 0; }
.hero-brand img { display: block; width: 236px; height: auto; }
.hero-tag {
  margin: 0 0 22px; color: var(--dim);
  font-size: 12px; text-transform: uppercase; letter-spacing: .16em;
}

/* The glacier backdrop. Fixed behind the page, above the body fill but under
   the content. It carries a --depth that app.js multiplies scroll by, so it
   drifts slower than the page and reads as something the content moves over. */
.glacier { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
/* The photographic layer sits deepest and moves least. Inset past the viewport
   so the parallax shift never exposes an edge, and masked so it fades out down
   the page rather than competing with the content below the hero. */
.glacier .ice {
  /* Taller than the viewport on purpose: it drifts up as the page scrolls, and
     a short layer would pull its own bottom edge into view. */
  position: absolute; left: -6%; right: -6%; top: -18%; bottom: -55%;
  /* The flat colour is the image's own mean tone. Until the file arrives the
     layer already paints the right value, so loading it adds texture rather
     than a visible jump in brightness. */
  background: #0f1724 url("/static/glacier.jpg") center / cover no-repeat;
  opacity: .85;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 46%, transparent 82%);
  mask-image: linear-gradient(180deg, #000 0%, #000 46%, transparent 82%);
  transform: translate3d(0, calc(var(--sy, 0) * var(--depth) * -1px), 0);
  will-change: transform;
}
/* Content rides above the backdrop; the topbar keeps its own higher layer. */
.landing, .wrap, .signin { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .glacier .ice { transform: none; }
}
@media (max-width: 900px) {
  .hero { grid-template-columns: 1fr; gap: 32px; }
  .hero { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .hero-mark { order: -1; justify-self: center; }
  .hero-crystal { width: 150px; }
  .hero-brand img { width: 180px; margin: 0 auto; }
  .hero-sub { margin-inline: auto; }
  .hero-actions { justify-content: center; }
}
.eyebrow { color: var(--accent); font-size: 12px; text-transform: uppercase; letter-spacing: .09em; margin: 0 0 14px; }
.hero h1 { font-size: 40px; line-height: 1.18; margin: 0 0 18px; font-weight: 650; letter-spacing: -.02em; }
.hero-sub { color: var(--dim); font-size: 16px; line-height: 1.6; margin: 0 0 28px; max-width: 60ch; }
.hero-actions { display: flex; gap: 12px; flex-wrap: wrap; }
.hero-btn {
  display: inline-block; padding: 10px 20px; border-radius: 8px; font-size: 13.5px; font-weight: 550;
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
}
.hero-btn:hover { text-decoration: none; filter: brightness(1.08); }
.hero-btn.ghost { background: transparent; color: var(--text); border-color: var(--border); }
.hero-btn.ghost:hover { border-color: var(--accent); }

/* The waterfall capture, unframed: the picture is the point, and a border
   around it is chrome pretending to be product. */
.shot { margin: 0; padding: 8px 0 44px; }
.shot-svg { display: block; width: 100%; height: auto; padding: 14px 10px 4px; }
.shot-legend { display: flex; flex-wrap: wrap; gap: 16px; padding: 0 18px 16px; font-size: 11.5px; color: var(--dim); }
.shot-legend .key { display: inline-flex; align-items: center; gap: 6px; }
.shot-legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.shot figcaption { margin-top: 12px; font-size: 12.5px; color: var(--dim); }

.section-title { font-size: 20px; font-weight: 600; margin: 0 0 22px; }
.features { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; padding: 44px 0; }
.feature h3 { font-size: 14px; margin: 0 0 8px; font-weight: 600; color: #e8ebf2; }
.feature p { color: var(--dim); font-size: 13.5px; line-height: 1.6; margin: 0; }
.feature code { font-size: 12px; }

.steps-section, .assurance { padding: 44px 0; border-top: 1px solid var(--border); }

/* One wide block, deliberately not a grid: it carries the argument the cards
   above cannot, so it should read as a paragraph rather than a fourth column. */
.statement { padding: 60px 0 64px; border-top: 1px solid var(--border); text-align: center; }
/* Heading, line, then the mark. A centred stack balances better than a row,
   where a small logo beside a wide paragraph leaves the section lopsided. */
.kaniko-link { display: block; width: max-content; margin: 24px auto 0; }
.kaniko-mark { display: block; height: 40px; width: auto; opacity: .85; }
.kaniko-link:hover .kaniko-mark { opacity: 1; }
/* No max-width: the claim is short and belongs on one line. */
.statement h2 {
  font-size: 30px; line-height: 1.25; font-weight: 640; letter-spacing: -.015em;
  margin: 0 auto 14px;
}
/* Centred, but the measure still caps at 66ch: a line that spans the full page
   is unreadable however wide the section is. */
.statement p { color: var(--dim); font-size: 16px; line-height: 1.7; margin: 0 auto; max-width: 66ch; }
.statement p:last-child { margin-bottom: 0; }
/* The snippet column is min-width:0 so the pre scrolls instead of widening the
   grid, which is what pushes a code block past the viewport. */
.steps { display: grid; grid-template-columns: minmax(260px, 1fr) minmax(0, 1.35fr); gap: 32px; align-items: start; }
.step-list { margin: 0; padding-left: 20px; color: var(--dim); font-size: 13.5px; line-height: 1.7; }
.step-list li { margin-bottom: 14px; }
.step-list strong { color: var(--text); }
.step-code { min-width: 0; }
.step-code .btn { margin-top: 12px; }
.assurance .features { padding: 0; }
.closing { padding: 52px 0 0; border-top: 1px solid var(--border); text-align: center; }
.closing h2 { font-size: 24px; margin: 0 0 22px; }
.closing .hero-actions { justify-content: center; }
.price-head { padding: 8px 0 34px; }
.price-head h1 { font-size: 34px; margin: 0 0 10px; letter-spacing: -.02em; }
.price-head .hero-sub { margin: 0; }

.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; align-items: stretch; }
.tier {
  position: relative; display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  padding: 22px 20px 20px;
}
/* The middle card carries the accent the topbar mark uses, so the recommended
   plan is the one thing on the page wearing brand colour. */
.tier.is-featured { border-color: var(--accent); }
.tier-flag {
  position: absolute; top: -9px; left: 20px;
  background: var(--accent); color: var(--bg);
  font-size: 10.5px; font-weight: 650; letter-spacing: .06em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 5px;
}
.tier h2 { font-size: 15px; margin: 0 0 12px; font-weight: 600; }
.tier-price { margin: 0 0 18px; display: flex; align-items: baseline; gap: 5px; }
.tier-price .amount { font-size: 32px; font-weight: 650; letter-spacing: -.02em; }
.tier-price .per { color: var(--dim); font-size: 13px; }
.tier-list { list-style: none; margin: 0 0 20px; padding: 0; flex: 1; }
.tier-list li {
  color: var(--dim); font-size: 13.5px; line-height: 1.5;
  padding: 7px 0 7px 20px; border-top: 1px solid var(--border); position: relative;
}
.tier-list li:first-child { border-top: 0; }
.tier-list li::before { content: "·"; position: absolute; left: 6px; color: var(--accent); font-weight: 700; }
.tier-list strong { color: var(--text); font-weight: 600; }
.tier .hero-btn { justify-content: center; text-align: center; }

.calc { padding: 46px 0 0; }
.calc h2 { font-size: 22px; margin: 0 0 16px; letter-spacing: -.01em; }
.calc-box { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px; }
.calc-field { display: flex; justify-content: space-between; align-items: baseline; font-size: 13px; color: var(--dim); }
.calc-field output { color: var(--text); font-size: 17px; font-weight: 650; font-variant-numeric: tabular-nums; }
.calc input[type=range] { width: 100%; margin: 10px 0 4px; accent-color: var(--accent); }
.calc-result { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding: 14px 0 16px; border-bottom: 1px solid var(--border); }
.calc-plan { font-size: 13px; color: var(--dim); }
.calc-total { display: flex; align-items: baseline; gap: 5px; font-size: 30px; font-weight: 650; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.calc-total .per { font-size: 13px; font-weight: 400; color: var(--dim); }
.rates { width: 100%; margin-top: 6px; font-size: 13px; }
.rates th { font-weight: 400; color: var(--dim); text-transform: none; letter-spacing: 0; font-size: 13px; padding-left: 0; }
.rates td { text-align: right; color: var(--text); padding-right: 0; }
.rates tr:last-child th, .rates tr:last-child td { border-bottom: none; }

.retention { padding: 52px 0 12px; }
.retention h2 { font-size: 22px; margin: 0 0 10px; letter-spacing: -.01em; }
.retention-lede { color: var(--dim); font-size: 14px; line-height: 1.65; margin: 0 0 26px; max-width: 72ch; }
.retention-lede strong { color: var(--text); font-weight: 600; }
  position: absolute; left: 0; top: 0; height: 100%; border-radius: 6px;
  display: flex; align-items: center; justify-content: flex-end;
}

.retention { padding: 52px 0 12px; }
.retention h2 { font-size: 22px; margin: 0 0 10px; letter-spacing: -.01em; }
.retention-lede { color: var(--dim); font-size: 14px; line-height: 1.65; margin: 0 0 26px; max-width: 72ch; }
.retention-lede strong { color: var(--text); font-weight: 600; }
.ret-chart { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px; }
.ret-row { display: grid; grid-template-columns: 96px 1fr 170px; align-items: center; gap: 14px; margin-bottom: 12px; }
.ret-name { font-size: 13px; font-weight: 600; }
.ret-track { position: relative; height: 26px; background: var(--panel-2); border-radius: 6px; }
.ret-bar { position: absolute; left: 0; top: 0; height: 100%; border-radius: 6px; }
.ret-trends { background: #35618f; }
.ret-traces { background: var(--accent); }
/* Labels sit outside the bars: on a linear scale the free trace window is under
   four per cent of the track and cannot hold its own text. */
.ret-labs { display: flex; gap: 14px; font-size: 12px; font-variant-numeric: tabular-nums; }
.ret-lab { display: inline-flex; align-items: center; gap: 6px; }
.ret-lab::before { content: ""; width: 9px; height: 9px; border-radius: 3px; }
.ret-lab.is-traces { color: var(--text); }
.ret-lab.is-traces::before { background: var(--accent); }
.ret-lab.is-trends { color: var(--dim); }
.ret-lab.is-trends::before { background: #35618f; }
.ret-axis-row { margin-bottom: 4px; }
.ret-axis { position: relative; height: 16px; }
.ret-gridline { position: absolute; top: -14px; width: 1px; height: 14px; background: var(--border); }
.ret-axis-label { position: absolute; top: 1px; transform: translateX(-50%); font-size: 10.5px; color: var(--dim); white-space: nowrap; }
/* The last tick sits at 100%, where half of a centred label hangs off the end. */
.ret-axis-label:last-child { transform: translateX(-100%); }
.ret-key { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; font-size: 11.5px; color: var(--dim); padding-top: 6px; }
.ret-key .key { display: inline-flex; align-items: center; gap: 6px; }
.ret-key i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.ret-key .sw-traces { background: var(--accent); }
.ret-key .sw-trends { background: #35618f; }

.price-faq { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px 26px; padding: 46px 0 8px; }

@media (max-width: 760px) {
  .hero h1 { font-size: 30px; }
  .steps { grid-template-columns: 1fr; }
  .tiers { grid-template-columns: 1fr; gap: 22px; }
  /* The track needs the full width here, so the name and the numbers share the
     line above it. */
  .ret-row { grid-template-columns: auto 1fr; gap: 6px 10px; }
  .ret-name { grid-column: 1; grid-row: 1; }
  .ret-labs { grid-column: 2; grid-row: 1; justify-content: flex-end; }
  .ret-track { grid-column: 1 / -1; grid-row: 2; }
  /* Every span is labelled on its own row, so the axis is only clutter at a
     width where its four labels land on top of each other. */
  .ret-axis-row { display: none; }
}

/* Snippet highlighting: chroma's class palette, emitted by docs.HighlightCSS. */
/* Background */ .bg { color: #e6edf3; background-color: #0d1117; }
/* PreWrapper */ .chroma { color: #e6edf3; background-color: #0d1117; -webkit-text-size-adjust: none; }
/* Error */ .chroma .err { color: #f85149 }
/* LineLink */ .chroma .lnlinks { outline: none; text-decoration: none; color: inherit }
/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
/* LineHighlight */ .chroma .hl { background-color: #6e7681 }
/* LineNumbersTable */ .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #737679 }
/* LineNumbers */ .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #6e7681 }
/* Line */ .chroma .line { display: flex; }
/* Keyword */ .chroma .k { color: #ff7b72 }
/* KeywordConstant */ .chroma .kc { color: #79c0ff }
/* KeywordDeclaration */ .chroma .kd { color: #ff7b72 }
/* KeywordNamespace */ .chroma .kn { color: #ff7b72 }
/* KeywordPseudo */ .chroma .kp { color: #79c0ff }
/* KeywordReserved */ .chroma .kr { color: #ff7b72 }
/* KeywordType */ .chroma .kt { color: #ff7b72 }
/* NameClass */ .chroma .nc { color: #f0883e; font-weight: bold }
/* NameConstant */ .chroma .no { color: #79c0ff; font-weight: bold }
/* NameDecorator */ .chroma .nd { color: #d2a8ff; font-weight: bold }
/* NameEntity */ .chroma .ni { color: #ffa657 }
/* NameException */ .chroma .ne { color: #f0883e; font-weight: bold }
/* NameLabel */ .chroma .nl { color: #79c0ff; font-weight: bold }
/* NameNamespace */ .chroma .nn { color: #ff7b72 }
/* NameProperty */ .chroma .py { color: #79c0ff }
/* NameTag */ .chroma .nt { color: #7ee787 }
/* NameVariable */ .chroma .nv { color: #79c0ff }
/* NameVariableClass */ .chroma .vc { color: #79c0ff }
/* NameVariableGlobal */ .chroma .vg { color: #79c0ff }
/* NameVariableInstance */ .chroma .vi { color: #79c0ff }
/* NameVariableMagic */ .chroma .vm { color: #79c0ff }
/* NameFunction */ .chroma .nf { color: #d2a8ff; font-weight: bold }
/* NameFunctionMagic */ .chroma .fm { color: #d2a8ff; font-weight: bold }
/* Literal */ .chroma .l { color: #a5d6ff }
/* LiteralDate */ .chroma .ld { color: #79c0ff }
/* LiteralString */ .chroma .s { color: #a5d6ff }
/* LiteralStringAffix */ .chroma .sa { color: #79c0ff }
/* LiteralStringBacktick */ .chroma .sb { color: #a5d6ff }
/* LiteralStringChar */ .chroma .sc { color: #a5d6ff }
/* LiteralStringDelimiter */ .chroma .dl { color: #79c0ff }
/* LiteralStringDoc */ .chroma .sd { color: #a5d6ff }
/* LiteralStringDouble */ .chroma .s2 { color: #a5d6ff }
/* LiteralStringEscape */ .chroma .se { color: #79c0ff }
/* LiteralStringHeredoc */ .chroma .sh { color: #79c0ff }
/* LiteralStringInterpol */ .chroma .si { color: #a5d6ff }
/* LiteralStringOther */ .chroma .sx { color: #a5d6ff }
/* LiteralStringRegex */ .chroma .sr { color: #79c0ff }
/* LiteralStringSingle */ .chroma .s1 { color: #a5d6ff }
/* LiteralStringSymbol */ .chroma .ss { color: #a5d6ff }
/* LiteralNumber */ .chroma .m { color: #a5d6ff }
/* LiteralNumberBin */ .chroma .mb { color: #a5d6ff }
/* LiteralNumberFloat */ .chroma .mf { color: #a5d6ff }
/* LiteralNumberHex */ .chroma .mh { color: #a5d6ff }
/* LiteralNumberInteger */ .chroma .mi { color: #a5d6ff }
/* LiteralNumberIntegerLong */ .chroma .il { color: #a5d6ff }
/* LiteralNumberOct */ .chroma .mo { color: #a5d6ff }
/* Operator */ .chroma .o { color: #ff7b72; font-weight: bold }
/* OperatorWord */ .chroma .ow { color: #ff7b72; font-weight: bold }
/* OperatorReserved */ .chroma .or { color: #ff7b72; font-weight: bold }
/* Comment */ .chroma .c { color: #8b949e; font-style: italic }
/* CommentHashbang */ .chroma .ch { color: #8b949e; font-style: italic }
/* CommentMultiline */ .chroma .cm { color: #8b949e; font-style: italic }
/* CommentSingle */ .chroma .c1 { color: #8b949e; font-style: italic }
/* CommentSpecial */ .chroma .cs { color: #8b949e; font-weight: bold; font-style: italic }
/* CommentPreproc */ .chroma .cp { color: #8b949e; font-weight: bold; font-style: italic }
/* CommentPreprocFile */ .chroma .cpf { color: #8b949e; font-weight: bold; font-style: italic }
/* GenericDeleted */ .chroma .gd { color: #ffa198; background-color: #490202 }
/* GenericEmph */ .chroma .ge { font-style: italic }
/* GenericError */ .chroma .gr { color: #ffa198 }
/* GenericHeading */ .chroma .gh { color: #79c0ff; font-weight: bold }
/* GenericInserted */ .chroma .gi { color: #56d364; background-color: #0f5323 }
/* GenericOutput */ .chroma .go { color: #8b949e }
/* GenericPrompt */ .chroma .gp { color: #8b949e }
/* GenericStrong */ .chroma .gs { font-weight: bold }
/* GenericSubheading */ .chroma .gu { color: #79c0ff }
/* GenericTraceback */ .chroma .gt { color: #ff7b72 }
/* GenericUnderline */ .chroma .gl { text-decoration: underline }
/* TextWhitespace */ .chroma .w { color: #6e7681 }

/* Mobile: the links fold behind a hamburger, and the topbar stays one row. */
@media (max-width: 760px) {
  /* nowrap: the hamburger exists so the bar stays one row. */
  .topbar { gap: 12px; padding: 10px 14px; flex-wrap: nowrap; }
  /* Hamburger left, mark centred, account right. */
  /* auto on the right: a fixed track wrapped the sign-in button onto four
     lines and stretched the bar. */
  .topbar { display: grid; grid-template-columns: 36px 1fr auto; align-items: center; }
  .topbar .burger-btn {
    display: grid; place-items: center; width: 34px; height: 34px;
    grid-column: 1; grid-row: 1; justify-self: start; cursor: pointer;
    border: 1px solid var(--border); border-radius: 8px; background: var(--panel-2);
  }
  /* Three bars from one element, so the button needs no icon file. */
  .burger, .burger::before, .burger::after {
    display: block; width: 15px; height: 2px; border-radius: 2px;
    background: var(--text); content: "";
  }
  .burger { position: relative; }
  .burger::before { position: absolute; top: -5px; }
  .burger::after  { position: absolute; top: 5px; }
  .topbar .brand { grid-column: 2; grid-row: 1; justify-self: center; }
  .topbar .user { grid-column: 3; grid-row: 1; justify-self: end; }
  .topbar .nav-group { display: none; }
  .nav-toggle:checked ~ .nav-group {
    display: grid; gap: 2px; position: absolute; left: 14px; top: 56px;
    min-width: 180px; z-index: 30; padding: 6px;
    background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  }
  .nav-group nav { display: grid; gap: 2px; }
  /* Stacked in one sheet, the two groups need a line between them instead of
     the distance they get side by side. */
  .topbar .nav-meta { margin-left: 0; }
  .nav-app + .nav-meta { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 4px; }
  .topbar nav a { padding: 8px 10px; border-radius: 6px; }
  .topbar nav a:hover { background: var(--panel-2); text-decoration: none; }
  /* The avatar is identity enough at this width. */
  .user-name { display: none; }
  .wrap { padding: 18px 14px; }
  /* The capture is wider than any phone, so let it pan instead of shrinking
     into an unreadable strip. */
  /* No parallax on a phone: transforming a full-bleed image every frame is
     what makes the page feel heavy to scroll. */
  .glacier .ice { transform: none; will-change: auto; }
  .shot { overflow-x: auto; }
  .shot .shot-img { min-width: 620px; width: 620px; }
}

/* Docs version picker: sits above the walkthrough, so a reader sets their kaniko
   version before following steps that depend on it. */
.version-picker { display: flex; align-items: center; gap: 10px; margin: 0 0 22px; font-size: 13px; }
.version-picker label { color: var(--dim); }
.version-picker select {
  padding: 5px 8px; border-radius: 6px; font: inherit; font-size: 13px;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
}

/* Profile page. The token input is wide because an API key is long and a field
   that shows six characters of it invites a truncated paste. */
.profile h2 { margin: 0 0 .5rem; font-size: 1rem; }
.profile .card { margin-bottom: 1rem; }
.profile .card > .dim { margin: 0 0 .75rem; max-width: 62ch; }
.user-link { display: block; padding: .4rem .1rem; color: var(--link); text-decoration: none; }
.user-link:hover { text-decoration: underline; }
.profile-token { display: flex; gap: .5rem; margin-top: .75rem; }
.token-input {
  flex: 1; min-width: 0; padding: .45rem .6rem; font-family: var(--mono, monospace);
  color: inherit; background: var(--input-bg, rgba(0,0,0,.25));
  border: 1px solid var(--border, rgba(255,255,255,.15)); border-radius: 6px;
}
.profile-token-remove { margin-top: .5rem; }
.btn-quiet { background: none; border: 1px solid var(--border, rgba(255,255,255,.15)); opacity: .8; }
.btn-quiet:hover { opacity: 1; }

/* A report page. The body is goldmark output — h2/p/table/pre and nothing else,
   because raw HTML is disabled — so the whole Firn report style is these rules
   over generated markup. Nothing to keep in sync with a hand-written document.

   Prose in the product's sans, every measurement in mono: a report is mostly
   numbers, and the two faces are what separate the argument from the evidence. */
/* Centred in the wrap, not flush left: a report is a document, and a measure
   this narrow hard against the left edge of a 1180px page reads as a column
   that failed to lay out rather than one that was chosen. */
.report { max-width: 78ch; margin: 0 auto; }
.report h1 { font-size: 30px; line-height: 1.12; letter-spacing: -.02em; margin: 4px 0 6px; }
.report .report-meta { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--dim);
  margin: 0 0 28px; }
.report h2 { font-size: 19px; font-weight: 600; letter-spacing: -.015em; color: var(--text);
  margin: 36px 0 12px; padding-top: 12px;
  /* Stratum rule: firn is layered snow under load, and the wordmark is a core
     sample. Every section opens on three compacted lines rather than one. */
  background:
    linear-gradient(var(--text), var(--text)) 0 0/100% 1px no-repeat,
    linear-gradient(var(--border), var(--border)) 0 3px/100% 1px no-repeat,
    linear-gradient(var(--panel-2), var(--panel-2)) 0 5px/100% 1px no-repeat; }
.report h3 { font-size: 15px; font-weight: 600; color: var(--text); margin: 24px 0 8px; }
.report p, .report li { color: var(--dim); font-size: 15.5px; line-height: 1.65; }
.report p { margin: 0 0 14px; }
.report strong { color: var(--text); font-weight: 600; }
.report ul, .report ol { margin: 0 0 14px; padding-left: 1.3em; }
.report li { margin-bottom: 6px; }
.report a { color: var(--accent); }

/* Tables carry the measurements, so they get the mono treatment and room to
   scroll rather than squeezing a column to nothing. */
/* Not display:block. That shrinks the internal table layout to its content
   while the block box still fills the column, which reads as a table hugging
   the left edge of its own background. */
.report table { width: 100%; margin: 0 0 20px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px; }
.report thead th { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--dim);
  font-weight: 400; white-space: nowrap; }
.report tbody td { font-size: 13.5px; }
/* The label column carries instruction text, which is inline code, and the
   global td code rule pins that open. Left alone it drives the table past the
   column instead of wrapping inside it. */
.report td code { white-space: normal; overflow-wrap: anywhere; }
/* GFM writes its alignment as an inline style rather than an align attribute,
   so the substring match is what catches it. A right-aligned column is a number
   column, which is why it earns mono and tabular figures with no extra markup
   in the body. */
.report td[style*="right"], .report th[style*="right"] {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.report tbody tr:last-child td { border-bottom: none; }

.report pre { background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; overflow-x: auto; margin: 0 0 20px; }
.report pre code { font-size: 12.5px; line-height: 1.62; color: var(--text); }
.report :not(pre) > code { background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 4px; padding: .08em .34em; }
.report blockquote { margin: 0 0 18px; padding: 2px 0 2px 16px;
  border-left: 2px solid var(--accent); color: var(--dim); }
.report hr { border: 0; border-top: 1px solid var(--border); margin: 32px 0; }
