<!DOCTYPE html>
<html lang="en" dir="auto" data-theme="{{ theme }}" data-theme-default="{{ theme }}" data-editor-theme="{{ editor_theme | default(value='follow') }}">
<head>
{% include "theme-boot.html" %}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="workspace-id" content="{{ workspace_id }}">
<meta name="can-manage" content="{{ can_manage | default(value=false) }}">
<meta name="shared-annotation" content="{{ shared_annotation }}">
<meta name="is-worktree-diff" content="{{ is_worktree_diff }}">
<meta name="diff-editable" content="{{ diff_editable }}">
<meta name="enable-viewed" content="false">
<meta name="enable-search" content="false">
<meta name="enable-edit" content="false">
<meta name="enable-live" content="{{ enable_live }}">
<meta name="enable-chat" content="{{ enable_chat }}">
<meta name="default-chat-mode" content="{{ default_chat_mode }}">
<title>{{ title }}</title>
<link id="markon-github-markdown-light" rel="stylesheet" href="/_/css/github-markdown-light.css" media="not all">
<link id="markon-github-markdown-dark" rel="stylesheet" href="/_/css/github-markdown-dark.css" media="not all">
<script>window.MarkonTheme && window.MarkonTheme.applyStylesheetMedia();</script>
<link rel="stylesheet" href="/_/css/tokens.css">
<link rel="stylesheet" href="/_/css/shortcuts.css">
<link rel="stylesheet" href="/_/css/editor.css">
<link rel="stylesheet" href="/_/css/collaboration.css">
<link rel="stylesheet" href="/_/css/chat.css">
<style>
* {
box-sizing: border-box;
}
:root {
--markon-note-width: 280px;
--markon-rail-edge-gap: 40px;
}
/* Root carries the page background too, so the overscroll/rubber-band area
(trackpad drag past the edge) shows the same dark surface instead of the
browser's default white; `overscroll-behavior: none` also stops the
bounce so the column divider always reaches the viewport edge. */
html {
background: var(--markon-bg-default);
overscroll-behavior: none;
}
body {
margin: 0;
min-height: 100vh;
background: var(--markon-bg-default);
overscroll-behavior: none;
color: var(--markon-fg-default);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.5;
}
a,
a:visited {
color: var(--markon-accent);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
button,
input {
font: inherit;
}
.git-diff-page {
min-height: 100vh;
height: 100vh;
overflow: hidden;
}
.git-file-meta,
.workspace-diff-empty {
color: var(--markon-fg-muted);
font-size: 12px;
}
.git-diff-title {
margin: 0;
font-size: 18px;
line-height: 1.25;
}
.git-diff-titlebox {
min-width: 0;
display: flex;
align-items: flex-start;
gap: 8px;
}
.git-diff-titletext {
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
/* Collapse-the-sidebar button (sits at the title row's right edge). Flat
ghost icon button — no border/box, hover background only. */
.git-sidebar-toggle {
flex: 0 0 auto;
margin-left: auto;
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
padding: 0;
border: 0;
border-radius: var(--markon-radius-sm);
background: transparent;
color: var(--markon-fg-muted);
cursor: pointer;
}
.git-sidebar-toggle:hover {
color: var(--markon-fg-default);
background: color-mix(in srgb, var(--markon-fg-default) 10%, transparent);
}
.git-sidebar-toggle svg { display: block; }
/* Workspace path under the title (repo icon + path); links to home. Extra
top spacing both separates it from the title and drops the whole options
block (ws path → toggles → files) down a touch for breathing room. */
.git-diff-ws-path {
display: flex;
align-items: center;
gap: 7px;
min-width: 0;
max-width: 100%;
margin-top: 8px;
font-size: 12px;
}
/* repo-name as a neutral pill (matches the compare preset chips). */
.git-diff-ws-name {
flex: none;
padding: 2px 10px;
border-radius: 999px;
background: var(--markon-bg-muted);
color: var(--markon-fg-default);
font-size: 11px;
line-height: 1.55;
white-space: nowrap;
}
/* repo-path as a plain (square) text link in muted colour. */
.git-diff-ws-full {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--markon-fg-muted);
}
.git-diff-ws-full:visited { color: var(--markon-fg-muted); }
.git-diff-ws-full:hover,
.git-diff-ws-full:focus-visible {
text-decoration: underline;
text-underline-offset: 2px;
}
.git-diff-summary {
min-width: 0;
margin-bottom: 14px;
display: flex;
flex-direction: column;
align-items: stretch;
gap: 12px;
}
/* View controls row (under Base→Compare): viewed ratio on the left, the
Raw|Rendered + Unified|Split icon toggles on the right. */
.git-diff-viewbar {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
min-height: 28px;
margin: 12px 0 4px;
}
.git-diff-viewbar-toggles {
display: inline-flex;
align-items: center;
gap: 8px;
}
.git-diff-layout-seg[hidden] { display: none; }
.git-diff-viewed-count {
display: inline-flex;
align-items: center;
gap: 5px;
color: var(--markon-fg-muted);
font-size: 12px;
font-weight: 500;
white-space: nowrap;
}
.git-diff-viewed-count[hidden] { display: none; }
.git-diff-viewed-count.is-complete {
color: var(--markon-diff-add-fg, #2da44e);
}
.git-diff-viewed-count svg { display: block; }
/* ── Base↔Compare picker control ───────────────────────────────────── */
.git-compare-control { min-width: 0; }
/* Field caption above the trigger (the picker's label). */
.git-compare-caption {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 5px;
padding-left: 2px;
}
.git-compare-caption-text {
display: inline-flex;
align-items: center;
gap: 5px;
color: var(--markon-fg-muted);
font-size: 12px;
font-weight: 500;
}
.git-compare-caption-text svg { display: block; }
.git-compare-caption .git-diff-viewed-count { flex: none; }
/* Trigger + view toggles on one row; the toggles sit at the right edge and
stretch to the same height as the (content-width) trigger button. Own class
(NOT .git-compare-row, which the picker popover uses) so it carries no panel
background — just vertical breathing room, flush left/right. */
.git-compare-head {
display: flex;
align-items: stretch;
gap: 8px;
padding: 5px 0;
}
.git-compare-head .git-compare-trigger { flex: 0 0 auto; }
.git-compare-head .git-diff-viewbar-toggles {
margin-left: auto;
align-items: stretch;
}
.git-compare-head .git-diff-view-seg { align-self: stretch; }
.git-compare-trigger {
width: fit-content;
min-width: 0;
display: grid;
/* base | arrow | compare | chevron — every column is content-sized; the
only horizontal whitespace is the fixed column-gap, so the button width
is purely (content + fixed gaps + padding). */
grid-template-columns: auto auto auto auto;
align-items: center;
column-gap: 12px;
min-height: 34px;
padding: 2px 12px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-muted);
color: var(--markon-fg-default);
cursor: pointer;
text-align: left;
}
.git-compare-trigger:hover {
border-color: color-mix(in srgb, var(--markon-fg-default) 30%, var(--markon-border-default));
}
/* Single-line revisions: large bold values with an arrow linking them, the
per-column captions dropped for a clean "<base> → <compare>" reading. */
.git-compare-leg {
min-width: 0;
display: flex;
align-items: center;
justify-content: center;
justify-self: stretch;
}
.git-compare-leg-label { display: none; }
.git-compare-leg-value {
max-width: 160px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
font-weight: 400;
line-height: 1.2;
}
.git-compare-sep {
justify-self: center;
align-self: center;
color: var(--markon-fg-muted);
font-size: 13px;
}
.git-compare-chevron { justify-self: end; align-self: center; color: var(--markon-fg-muted); }
/* ── Picker modal ──────────────────────────────────────────────────── */
.git-compare-panel {
position: fixed;
width: min(720px, calc(100vw - 16px));
display: flex;
flex-direction: column;
}
/* Quick presets under the Base→Compare trigger — they SET the comparator, so
they read as subordinate chips of the button above, not standalone links.
Neutral (no accent blue) keeps the toggle the page's single blue focus. */
.git-compare-quick {
display: flex;
flex-wrap: wrap;
gap: 7px;
margin-top: 10px;
}
.git-compare-quick:empty { display: none; }
/* Small tag-style chips — deliberately smaller (type + box) than the real
segmented/seg buttons, so they read as secondary shortcuts. */
.git-compare-preset {
padding: 1px 9px;
border: 1px solid var(--markon-border-default);
border-radius: 999px;
background: transparent;
color: var(--markon-fg-muted);
font-size: 11px;
line-height: 1.55;
cursor: pointer;
transition: color 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}
.git-compare-preset:hover {
color: var(--markon-fg-default);
border-color: color-mix(in srgb, var(--markon-fg-default) 30%, var(--markon-border-default));
background: var(--markon-bg-muted);
}
/* The standard modal frame owns the outer surface; this element only
clips and sizes the two-column body. */
.git-compare-surface {
display: flex;
flex-direction: column;
min-height: 0;
max-height: min(52vh, 400px);
border-radius: var(--markon-radius-lg);
overflow: hidden;
}
.git-compare-cols {
display: grid;
grid-template-columns: 1fr 1fr;
min-height: 0;
flex: 1;
}
.git-compare-col {
display: flex;
flex-direction: column;
min-height: 0;
min-width: 0;
padding: 10px;
}
.git-compare-col + .git-compare-col {
border-left: 1px solid var(--markon-border-default);
}
.git-compare-col-title {
font-size: 12px;
font-weight: 700;
color: var(--markon-fg-muted);
margin-bottom: 6px;
}
.git-compare-search {
min-height: 30px;
margin-bottom: 6px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
padding: 4px 8px;
background: var(--markon-bg-default);
color: var(--markon-fg-default);
font-size: 12px;
}
.git-compare-search:focus { outline: none; border-color: var(--markon-accent); }
.git-compare-list {
min-height: 0;
overflow: auto;
flex: 1;
}
.git-compare-group {
position: sticky;
top: 0;
padding: 5px 4px 3px;
background: var(--markon-bg-overlay);
color: var(--markon-fg-muted);
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.git-compare-row {
width: 100%;
display: flex;
align-items: center;
gap: 8px;
padding: 5px 6px;
border: 0;
border-radius: var(--markon-radius-sm);
background: transparent;
color: var(--markon-fg-default);
text-align: left;
cursor: pointer;
}
.git-compare-row:hover { background: color-mix(in srgb, var(--markon-fg-default) 8%, transparent); }
.git-compare-row.is-selected {
background: color-mix(in srgb, var(--markon-accent) 16%, var(--markon-bg-default));
}
.git-compare-row.is-disabled {
opacity: 0.4;
cursor: not-allowed;
}
.git-compare-badge {
flex: none;
min-width: 30px;
text-align: center;
padding: 1px 4px;
border-radius: 4px;
background: color-mix(in srgb, var(--markon-fg-default) 12%, transparent);
color: var(--markon-fg-muted);
font-size: 9px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.git-compare-badge-branch { background: color-mix(in srgb, var(--markon-accent) 22%, transparent); color: var(--markon-accent); }
.git-compare-badge-worktree { background: color-mix(in srgb, var(--markon-success, #3fb950) 22%, transparent); color: var(--markon-success, #3fb950); }
.git-compare-row-main {
min-width: 0;
flex: 1;
display: grid;
gap: 1px;
}
.git-compare-row-name {
display: flex;
align-items: center;
gap: 6px;
overflow: hidden;
font-size: 13px;
font-weight: 600;
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
}
.git-compare-row-name-text {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.git-compare-row-alias {
flex: none;
padding: 1px 5px;
border-radius: 999px;
background: color-mix(in srgb, var(--markon-accent) 12%, transparent);
color: var(--markon-accent);
font: 700 9px/1.35 var(--markon-ui-font);
letter-spacing: 0.02em;
}
.git-compare-row-sub {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 11px;
color: var(--markon-fg-muted);
}
.git-compare-row-detail,
.git-compare-row-date {
flex: none;
color: var(--markon-fg-muted);
font-size: 11px;
white-space: nowrap;
}
.git-compare-empty {
padding: 12px 6px;
color: var(--markon-fg-muted);
font-size: 12px;
}
/* Compact segmented Raw/Rendered toggle (sits in the summary function row). */
.git-diff-view-seg {
display: inline-flex;
flex: none;
padding: 2px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-muted);
}
.git-diff-seg-btn {
display: inline-flex;
align-items: center;
justify-content: center;
border: 0;
border-radius: calc(var(--markon-radius-sm) - 2px);
padding: 4px 9px;
background: transparent;
color: var(--markon-fg-muted);
font-size: 12px;
font-weight: 500;
line-height: 1.6;
cursor: pointer;
transition: background 140ms ease, color 140ms ease;
}
.git-diff-seg-btn svg { display: block; }
.git-diff-seg-btn[aria-pressed="true"] {
background: color-mix(in srgb, var(--markon-accent) 18%, var(--markon-bg-default));
color: var(--markon-accent);
}
.git-diff-seg-btn:focus-visible {
outline: 2px solid color-mix(in srgb, var(--markon-accent) 65%, transparent);
outline-offset: 1px;
}
/* Raw is a split button: clicking it switches to the Raw view; clicking it
again while Raw is already active drops down the Split/Unified menu. A
small caret tucked in the lower-right corner hints at that second action
without the bulk of a separate divided segment. */
.git-diff-seg-split { position: relative; display: inline-flex; }
.git-diff-seg-btn-main { position: relative; padding-right: 7px; }
.git-diff-seg-caret-mark {
position: absolute;
right: 0;
bottom: 1px;
display: block;
opacity: 0.7;
pointer-events: none;
}
.git-diff-seg-btn-main[aria-pressed="true"] .git-diff-seg-caret-mark,
.git-diff-seg-btn-main[aria-expanded="true"] .git-diff-seg-caret-mark { opacity: 1; }
.git-diff-more-menu {
position: absolute;
top: calc(100% + 6px);
right: 0;
z-index: 30;
min-width: 178px;
padding: 5px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-default);
box-shadow: 0 8px 24px color-mix(in srgb, #000 35%, transparent);
}
.git-diff-more-menu[hidden] { display: none; }
.git-diff-menu-group[hidden] { display: none; }
.git-diff-menu-heading {
padding: 3px 8px 3px;
color: var(--markon-fg-muted);
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
}
.git-diff-menu-item {
display: flex;
align-items: center;
gap: 7px;
width: 100%;
padding: 6px 8px;
border: 0;
border-radius: calc(var(--markon-radius-sm) - 2px);
background: none;
color: var(--markon-fg-default);
font-size: 12.5px;
text-align: left;
cursor: pointer;
}
.git-diff-menu-item:hover { background: color-mix(in srgb, var(--markon-fg-default) 8%, transparent); }
.git-diff-menu-check { flex: none; opacity: 0; color: var(--markon-accent); }
.git-diff-menu-item[aria-checked="true"] > .git-diff-menu-check,
.git-diff-menu-input:checked ~ .git-diff-menu-check { opacity: 1; }
.git-diff-menu-label { flex: 1 1 auto; min-width: 0; }
.git-diff-menu-icon { flex: none; display: block; color: var(--markon-fg-muted); }
.git-diff-menu-item[aria-checked="true"] .git-diff-menu-icon { color: var(--markon-fg-default); }
.git-diff-menu-input { position: absolute; width: 0; height: 0; opacity: 0; pointer-events: none; }
.git-diff-menu-sep { height: 1px; margin: 5px 4px; background: var(--markon-border-default); }
/* Viewed-count chip now lives at the right of the filter row (where the filter
button used to be); the search field flexes to fill the rest. */
.git-filter .git-diff-viewed-count { flex: none; }
.git-diff-body {
position: relative;
height: 100vh;
min-height: 100vh;
display: grid;
grid-template-columns: minmax(260px, 330px) minmax(0, 1fr) minmax(0, 1fr);
grid-template-areas: "sidebar old new";
overflow: hidden;
}
/* The left/right column divider is the sidebar's own border-right (below).
It's full-height (sidebar fills the grid row) and the root's
`overscroll-behavior: none` stops the rubber-band bounce that used to
flash a gap past it — so no separate overlay element is needed. */
.git-diff-sidebar {
grid-area: sidebar;
min-width: 0;
min-height: 0;
overflow: auto;
/* Top padding matches the floating re-open button's offset (11px) so
the collapse toggle and the re-open icon land on the same line —
toggling the sidebar only shifts the button horizontally. */
padding: 11px 18px 18px;
border-right: 1px solid var(--markon-border-default);
background: var(--markon-bg-default);
}
/* Collapsed sidebar: drop its grid track and reveal a floating re-open
button pinned to the top-left of the content. */
[data-diff-shell][data-sidebar-collapsed] .git-diff-body {
grid-template-columns: 0 minmax(0, 1fr) minmax(0, 1fr);
}
[data-diff-shell][data-sidebar-collapsed] .git-diff-sidebar {
display: none;
}
/* Floating re-open button (collapsed state). Flat ghost icon aligned with
the file-header icon row (which sits at y≈11, height 24). */
.git-sidebar-reopen {
position: absolute;
top: 11px;
left: 14px;
z-index: 30;
display: none;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
padding: 0;
border: 0;
border-radius: var(--markon-radius-sm);
background: transparent;
color: var(--markon-fg-muted);
cursor: pointer;
}
.git-sidebar-reopen:hover {
color: var(--markon-fg-default);
background: color-mix(in srgb, var(--markon-fg-default) 10%, transparent);
}
.git-sidebar-reopen svg { display: block; }
[data-diff-shell][data-sidebar-collapsed] .git-sidebar-reopen {
display: inline-flex;
}
.git-sidebar-block {
padding-bottom: 16px;
margin-bottom: 16px;
border-bottom: 1px solid var(--markon-border-default);
}
.git-sidebar-block:last-child {
border-bottom: 0;
}
.git-filter {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
}
.git-filter-field {
position: relative;
flex: 1;
min-width: 0;
display: flex;
align-items: center;
}
.git-filter-search-icon {
position: absolute;
left: 9px;
top: 50%;
transform: translateY(-50%);
color: var(--markon-fg-muted);
pointer-events: none;
}
.git-filter-input {
flex: 1;
min-width: 0;
min-height: 34px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
padding: 6px 9px 6px 30px;
background: var(--markon-bg-default);
color: var(--markon-fg-default);
font-size: 13px;
}
.git-filter-input::placeholder {
color: var(--markon-fg-muted);
}
/* File-list filter button + simple "Markdown only" menu. */
.git-filter-menu-wrap {
position: relative;
flex: none;
}
.git-filter-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-default);
color: var(--markon-fg-muted);
cursor: pointer;
}
.git-filter-btn:hover {
color: var(--markon-fg-default);
border-color: color-mix(in srgb, var(--markon-fg-default) 30%, var(--markon-border-default));
}
.git-filter-btn.is-active {
color: var(--markon-accent);
border-color: color-mix(in srgb, var(--markon-accent) 60%, var(--markon-border-default));
background: color-mix(in srgb, var(--markon-accent) 12%, var(--markon-bg-default));
}
.git-filter-menu {
position: absolute;
right: 0;
top: calc(100% + 4px);
z-index: 20;
min-width: 180px;
padding: 6px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-default);
box-shadow: 0 2px 6px color-mix(in srgb, var(--markon-fg-default) 12%, transparent);
}
.git-filter-opt {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 10px;
border-radius: var(--markon-radius-sm);
cursor: pointer;
user-select: none;
font-size: 13px;
color: var(--markon-fg-default);
}
.git-filter-opt:hover {
background: color-mix(in srgb, var(--markon-fg-default) 10%, transparent);
}
.git-filter-opt input {
margin: 0;
cursor: pointer;
}
.git-files {
list-style: none;
margin: 0;
padding: 0;
}
.git-files li {
margin: 0;
padding: 0;
}
.git-nav-entry {
--guide: color-mix(in srgb, var(--markon-fg-default) 11%, transparent);
width: 100%;
display: grid;
grid-template-columns: 16px minmax(0, 1fr);
align-items: center;
gap: 2px;
min-height: 30px;
border: 0;
border-radius: var(--markon-radius-sm);
/* A little left/vertical padding so the hover background wraps the icon
with breathing room instead of hugging it. */
padding: 5px 6px 5px calc(5px + var(--depth) * 14px);
background: transparent;
color: var(--markon-fg-default);
text-align: left;
cursor: default;
/* GitHub-style tree guide lines: one vertical rule per ancestor level,
drawn across the indent zone (width = depth * 14px). Shifted right by
the same 5px base padding so they stay under the indent. */
background-image: repeating-linear-gradient(
to right, var(--guide) 0, var(--guide) 1px, transparent 1px, transparent 14px);
background-size: calc(var(--depth) * 14px) 100%;
background-repeat: no-repeat;
/* Each guide rule must fall through its ancestor folder's chevron centre,
which sits at (5px base padding + 8px twist centre) = 13px, then +14px
per level. Aligning the gradient origin to 13px keeps the vertical line
passing straight through the chevron above it. */
background-position: 13px 0;
}
.git-nav-entry.is-file {
cursor: pointer;
}
.git-nav-entry.is-file:hover,
.git-nav-entry.is-dir:hover {
background-color: color-mix(in srgb, var(--markon-fg-default) 6%, transparent);
}
.git-nav-entry.is-active {
background-color: color-mix(in srgb, var(--markon-accent) 12%, transparent);
}
.git-nav-entry.is-active .git-nav-name {
color: var(--markon-accent);
}
/* Twist gutter: chevron for folders, blank (aligning) for files. */
.git-nav-twist {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
color: var(--markon-fg-muted);
}
.git-nav-chevron {
transition: transform 0.12s ease;
transform: rotate(90deg);
}
.git-nav-entry.is-dir[aria-expanded="false"] .git-nav-chevron {
transform: rotate(0deg);
}
.git-nav-main {
min-width: 0;
display: inline-flex;
align-items: center;
gap: 6px;
}
.git-nav-icon {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
}
.git-nav-icon svg { display: block; }
.git-nav-folder { color: var(--markon-fg-muted); }
.git-nav-status.is-added { color: var(--markon-diff-add-fg, #2da44e); }
.git-nav-status.is-deleted { color: var(--markon-diff-del-fg, #cf222e); }
.git-nav-status.is-modified { color: var(--markon-attention-fg, #bf8700); }
.git-nav-status.is-renamed,
.git-nav-status.is-copied { color: var(--markon-accent, #1f6feb); }
.git-nav-name {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
font-weight: 550;
}
.git-nav-entry.is-dir {
cursor: pointer;
}
.git-nav-entry.is-dir .git-nav-name {
color: var(--markon-fg-default);
font-weight: 600;
}
/* Root row: no chevron gutter, flush-left (the workspace scope header). */
.git-nav-entry.is-root {
grid-template-columns: minmax(0, 1fr);
}
.git-nav-entry.is-root .git-nav-twist { display: none; }
.git-nav-entry.is-root .git-nav-name { color: var(--markon-fg-default); font-weight: 650; }
/* Inline "new file/folder" affordances (only when diff-editable). */
.git-nav-entry.is-dir {
position: relative;
}
.git-nav-add {
position: absolute;
right: 4px;
top: 50%;
transform: translateY(-50%);
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
padding: 0;
border: 0;
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-default);
color: var(--markon-fg-muted);
cursor: pointer;
opacity: 0;
transition: opacity 0.12s ease;
}
.git-nav-entry.is-dir:hover > .git-nav-add,
.git-nav-add:focus-visible {
opacity: 1;
}
.git-nav-add:hover {
color: var(--markon-accent);
background: color-mix(in srgb, var(--markon-accent) 14%, var(--markon-bg-default));
}
.git-nav-root-add-row {
margin: 0 0 8px;
padding: 0;
}
.git-nav-add-root {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 3px 10px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-default);
color: var(--markon-fg-muted);
font-size: 12px;
cursor: pointer;
}
.git-nav-add-root:hover {
color: var(--markon-accent);
border-color: color-mix(in srgb, var(--markon-accent) 50%, var(--markon-border-default));
}
.git-nav-add-root svg { display: block; }
.git-nav-add-menu {
position: fixed;
z-index: 50;
min-width: 132px;
padding: 5px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-default);
box-shadow: 0 2px 6px color-mix(in srgb, var(--markon-fg-default) 12%, transparent);
}
.git-nav-add-item {
display: block;
width: 100%;
text-align: left;
padding: 6px 10px;
border: 0;
border-radius: var(--markon-radius-sm);
background: transparent;
color: var(--markon-fg-default);
font-size: 13px;
cursor: pointer;
}
.git-nav-add-item:hover {
background: color-mix(in srgb, var(--markon-fg-default) 10%, transparent);
}
.git-nav-input-row {
margin: 2px 0;
}
.git-nav-input {
width: calc(100% - 16px);
min-width: 0;
min-height: 26px;
border: 1px solid color-mix(in srgb, var(--markon-accent) 50%, var(--markon-border-default));
border-radius: var(--markon-radius-sm);
padding: 3px 8px;
background: var(--markon-bg-default);
color: var(--markon-fg-default);
font-size: 13px;
}
.git-nav-input:focus {
outline: none;
border-color: var(--markon-accent);
}
.git-source-diff-pane {
grid-column: 2 / 4;
min-width: 0;
min-height: 0;
overflow: hidden;
background: var(--markon-bg-default);
}
.git-preview-scroll {
grid-column: 2 / 4;
min-width: 0;
min-height: 0;
overflow: auto;
background: var(--markon-bg-default);
}
.git-preview-pane {
width: min(100%, 1120px);
min-width: 0;
min-height: 100%;
margin: 0 auto;
overflow: visible;
background: var(--markon-bg-default);
}
.workspace-diff-content {
width: 100%;
height: 100%;
min-height: 0;
overflow: auto;
position: relative;
padding: 14px;
}
.workspace-diff-content.is-virtualized-diff {
padding: 0;
}
.workspace-diff-row-line {
display: grid;
margin: 0;
overflow: visible;
background: var(--markon-bg-default);
color: var(--markon-fg-default);
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
font-size: 12px;
line-height: 1.5;
}
.workspace-diff-split-line {
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}
/* Unified (single-column) layout: old# | new# | +/- marker | code. */
.workspace-diff-unified-line {
grid-template-columns: 46px 46px 20px minmax(0, 1fr);
}
.workspace-diff-sign {
padding: 2px 0;
text-align: center;
color: var(--markon-fg-muted);
user-select: none;
white-space: pre;
}
.workspace-diff-unified-line.git-diff-add .workspace-diff-sign { color: var(--markon-success); }
.workspace-diff-unified-line.git-diff-del .workspace-diff-sign { color: var(--markon-danger); }
.workspace-diff-split-cell {
min-width: 0;
display: grid;
grid-template-columns: 54px minmax(0, 1fr);
}
.workspace-diff-split-cell + .workspace-diff-split-cell {
border-left: 1px solid var(--markon-border-default);
}
.workspace-diff-line-no {
padding: 2px 8px;
border-right: 1px solid var(--markon-border-default);
color: var(--markon-fg-muted);
text-align: right;
user-select: none;
}
.workspace-diff-code {
min-width: 0;
padding: 2px 10px;
color: inherit;
font: inherit;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
.git-diff-empty-side {
background: color-mix(in srgb, var(--markon-bg-muted) 74%, transparent);
}
.git-diff-add {
background: color-mix(in srgb, var(--markon-success) 12%, transparent);
}
.git-diff-del {
background: color-mix(in srgb, var(--markon-danger) 11%, transparent);
}
/* GitHub's two-tone diff gutter: the line-number column carries a stronger
add/del tint than the code, layered over the row tint for a combined
shade so the changed side reads at a glance. */
.git-diff-add .workspace-diff-line-no {
background: color-mix(in srgb, var(--markon-success) 16%, transparent);
}
.git-diff-del .workspace-diff-line-no {
background: color-mix(in srgb, var(--markon-danger) 15%, transparent);
}
/* Word-level highlight sits clearly above the line tint: stronger fill
plus a faint same-hue ring so the exact changed tokens read at a glance. */
.git-diff-word-add,
.git-diff-word-del {
border-radius: var(--markon-radius-sm);
padding: 0 1px;
}
.git-diff-word-add {
background: color-mix(in srgb, var(--markon-success) 52%, transparent);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--markon-success) 45%, transparent);
}
.git-diff-word-del {
background: color-mix(in srgb, var(--markon-danger) 50%, transparent);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--markon-danger) 42%, transparent);
}
/* Rendered view, structural (item-level) modified diff: changed list/table
items shown old-then-new with a tint; unchanged items are plain context.
The diff shading is ONE unified style — a band overlay drawn in JS and
measured against the block (content-width tint + gutter rail + +/- marker,
identical to the change cards), so it never depends on the list's own
indentation. The <li>.md-diff-item-old/new classes are just markers the
JS finds; their visuals come entirely from the band overlay. */
.md-diff-rendered-structural {
position: relative;
isolation: isolate;
/* It is a grid item; without this it expands to its min-content (a wide
table's natural width) and overflows the column, blowing the whole
diff out horizontally. min-width:0 lets the inner table's own
max-width:100% + overflow:auto contain it. */
min-width: 0;
}
.md-diff-item-band {
position: absolute;
left: 0;
right: 0;
z-index: -1;
pointer-events: none;
}
.md-diff-item-band-old {
--md-diff-guide-color: color-mix(in srgb, var(--markon-danger) 82%, var(--markon-fg-default));
background: color-mix(in srgb, var(--markon-danger) 13%, transparent);
}
.md-diff-item-band-new {
--md-diff-guide-color: color-mix(in srgb, var(--markon-success) 86%, var(--markon-fg-default));
background: color-mix(in srgb, var(--markon-success) 13%, transparent);
}
.md-diff-item-band::before {
content: attr(data-diff-marker);
position: absolute;
top: 0;
bottom: 0;
right: calc(100% + 8px);
width: 26px;
box-sizing: border-box;
border-right: 3px solid var(--md-diff-guide-color);
padding-right: 8px;
color: var(--md-diff-guide-color);
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
font-size: 16px;
font-weight: 800;
line-height: 1.2;
text-align: left;
}
/* Raw view: one wrapper per diff block, holding its source line rows. */
.workspace-diff-block { display: block; }
/* Unchanged context lines (no add/del tint). */
.git-diff-ctx { background: var(--markon-bg-default); }
.workspace-diff-empty {
margin: 12px;
padding: 16px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-muted);
}
/* No empty placeholder box during load/transition — only show when it
actually carries a message. */
.workspace-diff-empty:empty {
display: none;
}
.workspace-diff-empty.is-error {
border-color: color-mix(in srgb, var(--markon-danger) 36%, var(--markon-border-default));
color: var(--markon-danger);
}
[data-diff-view-panel][hidden] {
display: none !important;
}
.git-markdown-diff-content {
max-width: 1120px;
margin: 0 auto;
padding: 34px 46px 88px;
background: var(--markon-bg-default);
}
.git-markdown-diff-content.is-virtualized-md-diff {
padding: 0;
position: relative;
/* Full panel width so file headers span edge-to-edge like the raw
view (the 1120px reading cap applies to single-file articles). */
width: 100%;
max-width: none;
}
.md-diff-file-section {
width: 100%;
}
.md-diff-file-title {
overflow-wrap: anywhere;
font-size: 13px;
font-weight: 650;
}
.md-diff-file-meta,
.md-diff-block-meta {
color: var(--markon-fg-muted);
font-size: 12px;
}
.md-diff-file-section {
margin: 0;
}
/* Clear visual break between files: a gap of panel background plus each
file closed top (header border) and bottom (body border). */
.md-diff-file-section + .md-diff-file-section {
margin-top: 108px;
}
/* A pure-rename file is just a one-line fold. The inter-file margin lives on
the NEXT section's top, so it bleeds into the perceived space BELOW the
fold line — and because it varies with the neighbour's state (108 / 28 /
0), the fold looks unbalanced and the imbalance shifts as nearby files are
collapsed. Zero it out at every boundary touching a pure-rename so the
ONLY space around the fold is the section's own symmetric padding (the
sticky header borders still separate the files). */
.md-diff-file-section.is-pure-rename + .md-diff-file-section,
.md-diff-file-section + .md-diff-file-section.is-pure-rename {
margin-top: 0;
}
/* The big inter-file gap separates EXPANDED content. A collapsed (Viewed)
file is just a header row, so any boundary touching one collapses to a
compact gap (the sticky header borders provide the separation). */
.md-diff-file-section.is-collapsed + .md-diff-file-section,
.md-diff-file-section + .md-diff-file-section.is-collapsed {
margin-top: 0;
}
/* Native stacked-sticky header: each header sticks to the top while its
own section scrolls, and the next section's header pushes it out — the
GitHub PR-review pattern, no JS, no scroll jitter. Styled to match the
raw view's file row: full-width, no radius, top/bottom border only. */
.md-diff-file-header {
position: sticky;
top: 0;
z-index: 3;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
min-height: 40px;
padding: 8px 46px;
border-top: 1px solid var(--markon-border-default);
border-bottom: 1px solid var(--markon-border-default);
background: var(--markon-bg-muted);
/* The whole bar is a control surface (chevron / copy / Viewed / menu)
with a double-click-to-fold affordance — never a text target, so
the double-click can't accidentally select the file path. */
-webkit-user-select: none;
user-select: none;
}
.md-diff-file-left {
display: flex;
align-items: center;
gap: 6px;
min-width: 0;
}
.md-diff-file-right {
display: flex;
align-items: center;
gap: 8px;
flex: none;
}
.md-diff-file-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 650;
}
/* icon buttons (chevron / copy / kebab) */
.md-diff-chevron,
.md-diff-file-copy,
.md-diff-file-open,
.md-diff-menu-btn {
display: inline-flex;
align-items: center;
justify-content: center;
flex: none;
width: 24px;
height: 24px;
padding: 0;
border: 0;
border-radius: var(--markon-radius-sm);
background: transparent;
color: var(--markon-fg-muted);
cursor: pointer;
}
.md-diff-chevron:hover,
.md-diff-file-copy:hover,
.md-diff-file-open:hover,
.md-diff-menu-btn:hover {
background: color-mix(in srgb, var(--markon-fg-default) 10%, transparent);
color: var(--markon-fg-default);
}
.md-diff-chevron {
transition: transform 120ms ease;
}
.md-diff-file-header.is-collapsed .md-diff-chevron {
transform: rotate(-90deg);
}
.md-diff-file-copy.is-copied {
color: var(--markon-success, #3fb950);
}
/* diffstat: +N -M and a 5-square bar */
.md-diff-stat {
display: inline-flex;
align-items: center;
gap: 6px;
flex: none;
font-size: 12px;
font-variant-numeric: tabular-nums;
}
.md-diff-stat-add { color: var(--markon-success, #3fb950); font-weight: 650; }
.md-diff-stat-del { color: var(--markon-danger); font-weight: 650; }
.md-diff-stat-bars {
display: inline-flex;
gap: 2px;
}
.md-diff-bar {
width: 9px;
height: 9px;
border-radius: 2px;
background: color-mix(in srgb, var(--markon-fg-default) 18%, transparent);
}
.md-diff-bar.is-add { background: var(--markon-success, #3fb950); }
.md-diff-bar.is-del { background: var(--markon-danger); }
/* bordered "Viewed" checkbox */
.md-diff-file-check {
display: inline-flex;
align-items: center;
gap: 6px;
flex: none;
cursor: pointer;
user-select: none;
font-size: 12px;
color: var(--markon-fg-default);
white-space: nowrap;
padding: 3px 9px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-default);
}
.md-diff-file-check:hover {
border-color: color-mix(in srgb, var(--markon-fg-default) 30%, var(--markon-border-default));
}
.md-diff-file-check input {
cursor: pointer;
margin: 0;
}
/* kebab menu popover */
.md-diff-menu {
position: relative;
flex: none;
}
.md-diff-menu-pop {
position: absolute;
top: calc(100% + 4px);
right: 0;
z-index: 20;
min-width: 168px;
padding: 6px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-default);
box-shadow: 0 2px 6px color-mix(in srgb, var(--markon-fg-default) 12%, transparent);
}
.md-diff-menu-item {
display: block;
width: 100%;
text-align: left;
padding: 6px 10px;
border: 0;
border-radius: var(--markon-radius-sm);
background: transparent;
color: var(--markon-fg-default);
font-size: 13px;
cursor: pointer;
}
.md-diff-menu-item:hover {
background: color-mix(in srgb, var(--markon-fg-default) 10%, transparent);
}
.md-diff-menu-item.is-danger {
color: var(--markon-danger);
}
.md-diff-file-header.is-collapsed {
background: var(--markon-bg-default);
}
.md-diff-file-header.is-collapsed .md-diff-file-title {
opacity: 0.62;
}
.md-diff-file-body {
padding: 12px 46px 16px;
}
/* A pure-rename body is a single centered fold with no inter-section margin,
so its own padding is the only space around the line — keep top and bottom
equal (with the 22px gap padding) so the fold reads as vertically centred. */
.md-diff-file-section.is-pure-rename .md-diff-file-body {
padding-top: 12px;
padding-bottom: 12px;
}
/* Raw diff lines carry their own gutter; let them span the full width. */
.md-diff-file-body.workspace-diff-body {
padding: 0;
}
/* Collapsed run of unchanged blocks: a centered label (with an unfold
icon) sitting on a faint dashed "fold seam" line, with generous
vertical whitespace — reads as "content folded here, click to expand". */
/* One shared gap (createGap) is used by both views. The rendered body
insets its content 46px; the raw body has no padding (so its code spans
full width). Inset the raw gap 46px too so the dashed "fold seam" is the
SAME document width in both views. */
.workspace-diff-body .md-diff-gap {
box-sizing: border-box;
padding-left: 46px;
padding-right: 46px;
}
/* Standalone fold (whole body is one fold, e.g. a pure rename): compact and
vertically centered. Uses PADDING (not margin) so the whitespace can't
collapse through a zero-padding body (the raw view), keeping the space
above and below the line equal in both views. */
.md-diff-gap.md-diff-gap-standalone {
margin: 0;
padding-top: 22px;
padding-bottom: 22px;
}
.md-diff-gap {
display: flex;
align-items: center;
gap: 14px;
width: 100%;
margin: 38px 0;
padding: 0;
border: none;
background: none;
font: inherit;
font-size: 12px;
cursor: pointer;
/* A click-to-expand affordance, not a text target. */
-webkit-user-select: none;
user-select: none;
}
.md-diff-gap::before,
.md-diff-gap::after {
content: "";
flex: 1;
min-width: 0;
height: 0;
border-top: 1px dashed var(--markon-border-default);
opacity: 0.85;
}
.md-diff-gap-label {
flex: none;
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
color: var(--markon-fg-muted);
transition: color 0.12s ease;
}
.md-diff-gap-icon {
opacity: 0.85;
}
.md-diff-gap:hover .md-diff-gap-label {
color: var(--markon-accent-fg, #2f81f7);
}
.md-diff-file-section.is-collapsed .md-diff-file-body {
display: none;
}
/* Expanding a collapsed run: the space is opened and the 下文 re-pinned in
one synchronous step (no per-frame scrolling → no jank), then the
revealed blocks fade + settle in. Only opacity/transform animate, which
are compositor-driven and smooth. The wrapper is a plain, margin-neutral
box so unwrapping it at the end changes nothing. */
.md-diff-reveal > * {
opacity: 0;
transform: translateY(-6px);
transition: opacity 280ms ease, transform 280ms cubic-bezier(0.33, 1, 0.68, 1);
}
.md-diff-reveal.is-open > * {
opacity: 1;
transform: none;
}
@media (prefers-reduced-motion: reduce) {
.md-diff-reveal > * {
transition: none;
}
}
.md-diff-diagnostics {
padding: 9px 12px;
border: 1px solid color-mix(in srgb, var(--markon-danger) 30%, var(--markon-border-default));
border-radius: var(--markon-radius-sm);
background: color-mix(in srgb, var(--markon-danger) 7%, transparent);
color: var(--markon-danger);
font-size: 12px;
}
.md-diff-block {
margin: 0;
border: 0;
border-radius: 0;
overflow: visible;
}
.md-diff-block.is-modified,
.md-diff-block.is-added,
.md-diff-block.is-deleted {
display: grid;
gap: 0;
margin: 16px 0;
overflow: visible;
}
.md-diff-block.is-modified:first-of-type,
.md-diff-block.is-added:first-of-type,
.md-diff-block.is-deleted:first-of-type {
margin-top: 0;
}
/* j/k keyboard focus: an accent rail at the file body's left edge spanning
the focused change block. scroll-margin keeps it clear of the sticky
header when scrolled into view. */
/* j/k focus rail — shared by both views (the `.is-focused` block carries
the shared `diff-change-block` marker). Only the horizontal offset
differs, because the rendered block sits 46px right of the divider
while the raw block starts at the divider itself. */
.diff-change-block.is-focused {
position: relative;
scroll-margin-top: 60px;
}
.diff-change-block.is-focused::before {
content: "";
position: absolute;
top: -3px;
bottom: -3px;
width: 3px;
background: var(--markon-accent);
}
/* Rendered: block content is inset 46px from the divider → -48 centres the
4px rail on it. Raw: block starts at the divider → -2 centres it. */
.md-diff-block.is-focused::before { left: -48px; }
.workspace-diff-block.is-focused::before { left: -2px; }
.md-diff-change-card {
min-width: 0;
position: relative;
display: flow-root;
margin: 0;
padding: 0;
border: 0;
border-radius: 0;
background: transparent;
isolation: isolate;
}
.md-diff-change-card::before {
content: "";
position: absolute;
z-index: 0;
inset: 0;
border-radius: 0;
pointer-events: none;
}
.md-diff-change-card::after {
content: attr(data-diff-marker);
position: absolute;
z-index: 2;
top: 0;
bottom: 0;
right: calc(100% + 8px);
width: 26px;
box-sizing: border-box;
border-right: 3px solid var(--md-diff-guide-color);
padding-right: 8px;
color: var(--md-diff-guide-color);
font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;
font-size: 16px;
font-weight: 800;
line-height: 1.2;
text-align: left;
pointer-events: none;
user-select: none;
}
.md-diff-change-card-old {
--md-diff-guide-color: color-mix(in srgb, var(--markon-danger) 82%, var(--markon-fg-default));
}
.md-diff-change-card-old::before {
background: color-mix(in srgb, var(--markon-danger) 10%, transparent);
}
.md-diff-change-card-new {
--md-diff-guide-color: color-mix(in srgb, var(--markon-success) 86%, var(--markon-fg-default));
}
.md-diff-change-card-new::before {
background: color-mix(in srgb, var(--markon-success) 10%, transparent);
}
.md-diff-rendered {
position: relative;
z-index: 1;
max-width: none;
padding: 0;
background: transparent;
}
/* Wide tables in the rendered diff fit the column and wrap their cells
(long commands/code break at spaces) instead of forcing a horizontal
scrollbar — a reviewer should see every column at once. */
.git-markdown-diff-content table {
display: table;
width: 100%;
table-layout: auto;
}
.git-markdown-diff-content th,
.git-markdown-diff-content td {
overflow-wrap: anywhere;
}
.git-markdown-diff-content th code,
.git-markdown-diff-content td code {
white-space: pre-wrap;
overflow-wrap: anywhere;
}
/* No heading-depth indentation: the diff matches the document, which does
not indent content under headings (markdown's own list/blockquote
indentation still comes from the rendered HTML). */
.md-diff-rendered-sectioned {
padding-left: 0;
padding-right: 0;
}
/* Inside a change card the rendered block hugs the band (no leading/
trailing margin). Equal/context blocks instead keep their natural
markdown margins so the diff flows exactly like the document. */
.md-diff-change-card .md-diff-rendered > :first-child,
.md-diff-change-card .md-diff-rendered .heading-section:first-child {
margin-top: 0;
}
.md-diff-change-card .md-diff-rendered > :last-child,
.md-diff-change-card .md-diff-rendered .heading-section:last-child {
margin-bottom: 0;
}
.md-diff-placeholder {
min-height: 1px;
}
.md-diff-empty {
padding: 16px;
border: 1px solid var(--markon-border-default);
border-radius: var(--markon-radius-sm);
background: var(--markon-bg-muted);
color: var(--markon-fg-muted);
font-size: 12px;
}
.md-diff-empty:empty {
display: none;
}
/* Centered "all done" states: empty when Hide Viewed filters every file,
and tail when viewed files remain visible. */
.md-diff-viewed-empty,
.md-diff-viewed-done {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 10px;
min-height: 60vh;
padding: 24px;
text-align: center;
}
.md-diff-viewed-done {
min-height: 42vh;
margin-top: 24px;
}
.md-diff-viewed-empty-emoji {
font-size: 40px;
line-height: 1;
}
.md-diff-viewed-empty-title {
color: var(--markon-fg-default);
font-size: 15px;
font-weight: 600;
}
.md-diff-viewed-empty-actions {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.md-diff-viewed-empty-link {
border: 0;
background: none;
padding: 0;
color: var(--markon-accent);
font-size: 13px;
cursor: pointer;
}
.md-diff-viewed-empty-link:hover { text-decoration: underline; }
.md-diff-viewed-empty-link:disabled,
.md-diff-viewed-empty-link.is-disabled,
.md-diff-viewed-empty-link:disabled:hover,
.md-diff-viewed-empty-link.is-disabled:hover {
color: var(--markon-fg-muted);
cursor: default;
text-decoration: none;
}
@media (max-width: 920px) {
.git-diff-page {
height: auto;
overflow: visible;
}
.git-diff-body {
display: block;
overflow: visible;
height: auto;
min-height: 100vh;
}
.git-diff-sidebar {
max-height: 42vh;
border-right: 0;
border-bottom: 1px solid var(--markon-border-default);
}
.git-source-diff-pane,
.git-preview-scroll,
.git-preview-pane {
height: 72vh;
}
.git-preview-scroll {
display: grid;
}
.md-diff-file-header {
align-items: flex-start;
flex-direction: column;
}
}
</style>
{% if styles_css %}<style>{{ styles_css | safe }}</style>{% endif %}
{% include "i18n-boot.html" %}
{% if shortcuts_json %}<script>window.__MARKON_SHORTCUTS__ = {{ shortcuts_json | safe }};</script>{% endif %}
</head>
<body>
<main class="git-diff-page"
data-diff-shell
data-current-diff-view="{{ initial_diff_view }}"
data-source-url="{{ source_diff_url }}"
data-markdown-url="{{ markdown_diff_url }}"
data-markdown-diff
data-diff-data-url="{{ markdown_diff_data_url }}"
data-default-diff-path="{{ default_diff_path }}"
data-diff-autoload="{% if initial_diff_view == "rendered" %}true{% else %}false{% endif %}">
<section class="git-diff-body">
<aside class="git-diff-sidebar">
<section class="git-diff-summary">
<div class="git-diff-titlebox">
<div class="git-diff-titletext">
<h1 class="git-diff-title">Markdiff</h1>
<div class="git-diff-ws-path"><span class="git-diff-ws-name">{% if workspace_alias %}{{ workspace_alias }}{% else %}{{ workspace_display_path | split(pat="/") | last }}{% endif %}</span><a class="git-diff-ws-full" href="{{ files_url }}" title="{{ workspace_display_path }}">{{ workspace_display_path }}</a></div>
</div>
<button type="button" class="git-sidebar-toggle" data-sidebar-toggle
aria-label="Collapse sidebar" title="Collapse sidebar">
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path fill="currentColor" d="M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z"/><path fill="currentColor" d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25Zm13 12.5V1.75a.25.25 0 0 0-.25-.25H11v13h3.25a.25.25 0 0 0 .25-.25Z"/></svg>
</button>
</div>
</section>
<section class="git-sidebar-block" aria-label="Diff options">
<div class="git-compare-control"
data-compare-control
data-compare-path-base="{{ compare_path_base }}"
data-compare-status-url="{{ compare_options_status_url }}">
<div class="git-compare-caption">
<span class="git-compare-caption-text" aria-label="Compare" title="Compare"><svg viewBox="0 0 24 24" width="15" height="15" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 1a1 1 0 0 1 1 1v1a1 1 0 1 1 0 2v14a1 1 0 1 1 0 2v1a1 1 0 1 1-2 0v-1H6a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h5V2a1 1 0 0 1 1-1zm-1 4H6a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h5zm5-1a1 1 0 0 1 1-1h1a3 3 0 0 1 3 3v1a1 1 0 1 1-2 0V6a1 1 0 0 0-1-1h-1a1 1 0 0 1-1-1zm4 6a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0v-2a1 1 0 0 1 1-1zm0 6a1 1 0 0 1 1 1v1a3 3 0 0 1-3 3h-1a1 1 0 1 1 0-2h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1z"/></svg><span class="git-compare-caption-label">compare</span></span>
<span class="git-diff-viewed-count" data-diff-viewed-count aria-live="polite" hidden>
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><path fill="currentColor" d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg>
<span data-diff-viewed-count-text></span>
</span>
</div>
<div class="git-compare-head">
<button type="button" class="git-compare-trigger" data-compare-trigger
aria-haspopup="dialog" aria-expanded="false" aria-label="Choose compared revisions">
<span class="git-compare-leg">
<span class="git-compare-leg-label">Base</span>
<span class="git-compare-leg-value" data-compare-base-label>…</span>
</span>
<span class="git-compare-sep" aria-hidden="true">→</span>
<span class="git-compare-leg">
<span class="git-compare-leg-label">Compare</span>
<span class="git-compare-leg-value" data-compare-compare-label>…</span>
</span>
<svg class="git-compare-chevron" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4.5 6.25 8 2.75l3.5 3.5"/><path d="M4.5 9.75 8 13.25l3.5-3.5"/></svg>
</button>
<div class="git-diff-viewbar-toggles">
<div class="git-diff-view-seg" role="group" aria-label="Diff view" data-diff-view-seg>
<button type="button" class="git-diff-seg-btn" data-view="rendered" title="Rendered" aria-label="Rendered"
aria-pressed="{% if initial_diff_view == "raw" %}false{% else %}true{% endif %}"><svg viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 13.5h12"/><path d="M4 13V8"/><path d="M8 13V3.5"/><path d="M12 13V6"/></svg></button>
<span class="git-diff-seg-split">
<button type="button" class="git-diff-seg-btn git-diff-seg-btn-main" data-view="raw" data-diff-more-toggle
aria-haspopup="menu" aria-expanded="false" title="Raw (source)" aria-label="Raw (source)"
aria-pressed="{% if initial_diff_view == "raw" %}true{% else %}false{% endif %}"><svg viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M6.4 2.5 5 13.5M11 2.5 9.6 13.5M3 6h10.5M2.5 10H13"/></svg><svg class="git-diff-seg-caret-mark" viewBox="0 0 16 16" width="7" height="7" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6l5 5 5-5"/></svg></button>
<div class="git-diff-more-menu" role="menu" hidden data-diff-more-menu>
<div class="git-diff-menu-group git-diff-layout-seg" role="group" aria-label="Raw layout" data-diff-layout-seg>
<div class="git-diff-menu-heading">Raw layout</div>
<button type="button" class="git-diff-menu-item" role="menuitemradio" data-layout="split" aria-checked="true"><svg class="git-diff-menu-check" viewBox="0 0 16 16" width="13" height="13" fill="currentColor" aria-hidden="true"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg><svg class="git-diff-menu-icon" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linejoin="round" aria-hidden="true"><rect x="1.75" y="3" width="5.4" height="10" rx="1.1"/><rect x="8.85" y="3" width="5.4" height="10" rx="1.1"/></svg><span class="git-diff-menu-label">Split</span></button>
<button type="button" class="git-diff-menu-item" role="menuitemradio" data-layout="unified" aria-checked="false"><svg class="git-diff-menu-check" viewBox="0 0 16 16" width="13" height="13" fill="currentColor" aria-hidden="true"><path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"/></svg><svg class="git-diff-menu-icon" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.4" y="1.4" width="9.2" height="13.2" rx="1.4"/><path d="M5.6 4.4h5.8M5.6 6.8h5.8M5.6 9.2h5.8M5.6 11.6h5.8"/></svg><span class="git-diff-menu-label">Unified</span></button>
</div>
</div>
</span>
</div>
</div>
</div>
<!-- Quick-preset links sit inline under the trigger (populated by
diff-ref-picker.ts), not inside the popover. -->
<div class="git-compare-quick" data-compare-quick></div>
</div>
<script type="application/json" data-compare-picker>{{ compare_picker_json | safe }}</script>
</section>
<section class="git-sidebar-block">
<div class="git-filter">
<div class="git-filter-field">
<svg class="git-filter-search-icon" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"><path fill="currentColor" d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"/></svg>
<input class="git-filter-input" type="search" placeholder="Filter files..." data-diff-filter>
</div>
<div class="git-filter-menu-wrap">
<button class="git-filter-btn" type="button" data-diff-filter-toggle
aria-haspopup="menu" aria-expanded="false" aria-label="Filter files" title="Filter files">
<svg viewBox="0 0 16 16" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" aria-hidden="true"><path d="M2.5 4.5h11"/><path d="M4.5 8h7"/><path d="M6.5 11.5h3"/></svg>
</button>
<div class="git-filter-menu" role="menu" hidden data-diff-filter-menu>
<label class="git-filter-opt">
<input type="checkbox" class="git-filter-opt-input" data-diff-show-viewed>
<span>Hide Viewed files</span>
</label>
</div>
</div>
</div>
{% if diff.nav_entries | length > 0 %}
<ul class="git-files" data-diff-file-list
data-create-file-url="{{ create_file_url }}"
data-create-folder-url="{{ create_folder_url }}">
{% for entry in diff.nav_entries %}
<li data-diff-nav-entry
data-diff-kind="{{ entry.kind }}"
data-diff-path="{{ entry.path }}">
{% if entry.kind == "file" %}
<button class="git-nav-entry is-file git-file-link"
type="button"
aria-pressed="false"
style="--depth: {{ entry.depth }}"
data-diff-status="{{ entry.status }}"
data-diff-scroll-path="{{ entry.path }}">
<span class="git-nav-twist" aria-hidden="true"></span>
<span class="git-nav-main">
<span class="git-nav-icon git-nav-status is-{{ entry.status }}" aria-hidden="true">
{% if entry.status == "added" %}<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2.5"/><path d="M12 9v6M9 12h6"/></svg>
{% elif entry.status == "deleted" %}<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2.5"/><path d="M9 12h6"/></svg>
{% elif entry.status == "renamed" or entry.status == "copied" %}<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2.5"/><path d="M8.5 12h5.5M12.5 9.5l3 2.5-3 2.5"/></svg>
{% else %}<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2.5"/><circle cx="12" cy="12" r="2.2" fill="currentColor" stroke="none"/></svg>{% endif %}
</span>
<span class="git-nav-name">{{ entry.name }}</span>
</span>
</button>
{% else %}
<div class="git-nav-entry is-dir"
style="--depth: {{ entry.depth }}"
role="button" tabindex="0" aria-expanded="true"
data-diff-dir-toggle>
<span class="git-nav-twist" aria-hidden="true"><svg class="git-nav-chevron" viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"/></svg></span>
<span class="git-nav-main">
<span class="git-nav-icon git-nav-folder" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"/></svg></span>
<span class="git-nav-name">{{ entry.name }}</span>
</span>
</div>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<div class="workspace-diff-empty">No changed files.</div>
{% endif %}
</section>
</aside>
<button type="button" class="git-sidebar-reopen" data-sidebar-reopen
aria-label="Show sidebar" title="Show sidebar">
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path fill="currentColor" d="M4.177 7.823a.25.25 0 0 0 0 .354l2.396 2.396A.25.25 0 0 0 7 10.396V5.604a.25.25 0 0 0-.427-.177Z"/><path fill="currentColor" d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25Zm13 12.5V1.75a.25.25 0 0 0-.25-.25H11v13h3.25a.25.25 0 0 0 .25-.25Z"/></svg>
</button>
<section class="git-source-diff-pane"
data-diff-view-panel="raw"
data-standalone-diff
{% if initial_diff_view == "rendered" %}hidden{% endif %}>
<div class="workspace-diff-content"
data-virtual-diff
data-diff-scroller
data-diff-autoload="{% if initial_diff_view == "raw" %}true{% else %}false{% endif %}"
data-diff-data-url="{{ markdown_diff_data_url }}"
data-diff-open-url="">
<div class="workspace-diff-empty"></div>
</div>
</section>
<section class="git-preview-scroll"
data-diff-view-panel="rendered"
data-diff-scroller
{% if initial_diff_view != "rendered" %}hidden{% endif %}>
<article class="git-preview-pane git-markdown-diff-content markdown-body"
data-md-diff-content>
<div class="md-diff-empty"></div>
</article>
</section>
</section>
</main>
<!-- File-list filter + Raw/Rendered view switcher (classic IIFE, runs
during parse before the deferred diff-view modules). -->
<script src="/_/js/diff-controls.js"></script>
<script type="module" src="/_/js/workspace-diff.js"></script>
<script type="module" src="/_/js/markdown-diff.js"></script>
<script type="module" src="/_/js/diff-annotations.js"></script>
<script type="module" src="/_/js/diff-shortcuts.js"></script>
<script type="module" src="/_/js/diff-file-create.js"></script>
<script type="module" src="/_/js/diff-ref-picker.js"></script>
</body>
</html>