| ⋯ 90 unchanged lines |
| 91 | 91 | | }; |
| 92 | 92 | | |
| 93 | 93 | | const STYLE: &str = r#" |
| 94 | | - | :root { --fg:#1f2328; --muted:#656d76; --bg:#fff; --border:#d0d7de; --accent:#0969da; --code-bg:#f6f8fa; --success:#1a7f37; --success-bg:#dafbe1; --error:#cf222e; --error-bg:#ffebe9; --warning:#7d4e00; --warning-bg:#fff8c5; --info:#8250df; --info-bg:#fbefff; --dir-icon:#54aeff; --diff-ins-bg:#e6ffec; --diff-del-bg:#ffebe9; } |
| 94 | + | :root { color-scheme:light; --fg:#1f2328; --muted:#656d76; --bg:#fff; --border:#d0d7de; --accent:#0969da; --code-bg:#f6f8fa; --success:#1a7f37; --success-bg:#dafbe1; --error:#cf222e; --error-bg:#ffebe9; --warning:#7d4e00; --warning-bg:#fff8c5; --info:#8250df; --info-bg:#fbefff; --dir-icon:#54aeff; --diff-ins-bg:#e6ffec; --diff-del-bg:#ffebe9; } |
| 95 | 95 | | @media (prefers-color-scheme: dark) { |
| 96 | | - | :root { --fg:#e6edf3; --muted:#8b949e; --bg:#0d1117; --border:#30363d; --accent:#58a6ff; --code-bg:#161b22; --success:#3fb950; --success-bg:#1a3a1a; --error:#f85149; --error-bg:#3d1f1a; --warning:#d29922; --warning-bg:#3a2a1a; --info:#a371f7; --info-bg:#2a1e4e; --dir-icon:#79c0ff; --diff-ins-bg:#0d2818; --diff-del-bg:#2d1519; } |
| 96 | + | :root { color-scheme:dark; --fg:#e6edf3; --muted:#8b949e; --bg:#0d1117; --border:#30363d; --accent:#58a6ff; --code-bg:#161b22; --success:#3fb950; --success-bg:#1a3a1a; --error:#f85149; --error-bg:#3d1f1a; --warning:#d29922; --warning-bg:#3a2a1a; --info:#a371f7; --info-bg:#2a1e4e; --dir-icon:#79c0ff; --diff-ins-bg:#0d2818; --diff-del-bg:#2d1519; } |
| 97 | 97 | | } |
| 98 | 98 | | * { box-sizing:border-box; } |
| 99 | 99 | | body { margin:0; font:14px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif; color:var(--fg); background:var(--bg); } |
| ⋯ 5 unchanged lines |
| 105 | 105 | | main { padding:12px 0 24px; } |
| 106 | 106 | | h1,h2 { font-weight:600; } h1 { font-size:20px; } h2 { font-size:15px; margin:20px 0 8px; } |
| 107 | 107 | | .muted { color:var(--muted); } |
| 108 | + | .error-msg { color:var(--error); } |
| 108 | 109 | | .repo-list { list-style:none; padding:0; margin:0; } |
| 109 | 110 | | .repo-list li { padding:12px 0; border-bottom:1px solid var(--border); } |
| 110 | 111 | | .repo-list .name { font-size:16px; font-weight:600; } |
| 111 | 112 | | .box { border:1px solid var(--border); border-radius:6px; overflow:hidden; } |
| 112 | | - | .box .row { display:flex; justify-content:space-between; padding:8px 16px; border-top:1px solid var(--border); } |
| 113 | + | .box .row { display:flex; gap:12px; justify-content:space-between; padding:8px 16px; border-top:1px solid var(--border); } |
| 113 | 114 | | .box .row:first-child { border-top:0; } |
| 114 | 115 | | .box .row a.entry { display:flex; gap:8px; align-items:center; white-space:nowrap; } |
| 115 | 116 | | .box .row a.fc-msg { flex:1; margin-left:24px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; text-align:left; color:var(--muted); font-size:13px; } |
| ⋯ 54 unchanged lines |
| 170 | 171 | | .pill-group > .pill { border-radius:0; margin-left:-1px; position:relative; } |
| 171 | 172 | | .pill-group > .pill:first-child { border-radius:2em 0 0 2em; margin-left:0; } |
| 172 | 173 | | .pill-group > .pill:last-child { border-radius:0 2em 2em 0; } |
| 173 | | - | form.stack p { margin:10px 0; } form.stack label { font-size:13px; color:var(--muted); } |
| 174 | | - | form.stack input[type=text], form.stack textarea { width:100%; max-width:480px; padding:6px 8px; border:1px solid var(--border); border-radius:6px; font:inherit; } |
| 175 | | - | form.stack .check { display:flex; gap:8px; align-items:flex-start; max-width:480px; } |
| 176 | | - | form.stack select { padding:6px 8px; border:1px solid var(--border); border-radius:6px; font:inherit; } |
| 177 | | - | form.stack textarea.editor { max-width:none; font:13px/1.5 ui-monospace,monospace; tab-size:4; resize:vertical; } |
| 174 | + | .stack p { margin:10px 0; } .stack label { font-size:13px; color:var(--muted); } |
| 175 | + | /* Explicit colours, not just borders: a control left to the browser's defaults |
| 176 | + | renders white-on-white in dark mode. `color-scheme` above covers the rest. */ |
| 177 | + | .stack input[type=text], .stack input[type=password], .stack textarea, .stack select { background:var(--bg); color:var(--fg); } |
| 178 | + | .stack input[type=text], .stack input[type=password], .stack textarea { width:100%; max-width:480px; padding:6px 8px; border:1px solid var(--border); border-radius:6px; font:inherit; } |
| 179 | + | .stack .check { display:flex; gap:8px; align-items:flex-start; max-width:480px; } |
| 180 | + | .stack select { padding:6px 8px; border:1px solid var(--border); border-radius:6px; font:inherit; } |
| 181 | + | .stack textarea.editor { max-width:none; font:13px/1.5 ui-monospace,monospace; tab-size:4; resize:vertical; } |
| 178 | 182 | | p.file-actions { margin:10px 0; display:flex; gap:6px; align-items:center; } |
| 179 | 183 | | .file-actions .btn { padding:3px 11px; font-size:12px; font-weight:500; border-radius:6px; display:inline-flex; align-items:center; gap:5px; } |
| 180 | 184 | | table.usage { border-collapse:collapse; width:100%; max-width:680px; margin-top:12px; } |
| ⋯ 20 unchanged lines |
| 201 | 205 | | .kanban .card-del { position:absolute; top:3px; right:4px; margin:0; } |
| 202 | 206 | | .kanban .card-del-btn { border:0; background:none; color:var(--muted); cursor:pointer; font-size:16px; line-height:1; padding:1px 5px; border-radius:4px; opacity:0; transition:opacity .1s,background .1s; } |
| 203 | 207 | | .kanban .card:hover .card-del-btn, .card-del-btn:focus { opacity:1; } |
| 204 | | - | .kanban .card-del-btn:hover { color:#cf222e; background:var(--code-bg); } |
| 208 | + | .kanban .card-del-btn:hover { color:var(--error); background:var(--code-bg); } |
| 205 | 209 | | .kanban .card .title { padding-right:14px; } |
| 206 | 210 | | .kanban .card:has(.card-grip) { padding-left:28px; } |
| 207 | 211 | | .kanban .card-grip { position:absolute; left:2px; top:5px; color:var(--muted); cursor:grab; touch-action:none; user-select:none; -webkit-user-select:none; -webkit-touch-callout:none; line-height:0; padding:4px 5px; border-radius:4px; } |
| ⋯ 636 unchanged lines |
| 844 | 848 | | |
| 845 | 849 | | h2 { "SSH keys" } |
| 846 | 850 | | p.muted { "Add a public key to clone and push over SSH." } |
| 847 | | - | @if let Some(error) = error { p style="color:#cf222e" { (error) } } |
| 851 | + | @if let Some(error) = error { p.error-msg { (error) } } |
| 848 | 852 | | @if keys.is_empty() { |
| 849 | 853 | | p.muted { "No SSH keys yet." } |
| 850 | 854 | | } @else { |
| ⋯ 174 unchanged lines |
| 1025 | 1029 | | Some(user), |
| 1026 | 1030 | | html! { |
| 1027 | 1031 | | h1 { "New repository" } |
| 1028 | | - | @if let Some(error) = error { p style="color:#cf222e" { (error) } } |
| 1032 | + | @if let Some(error) = error { p.error-msg { (error) } } |
| 1029 | 1033 | | form.stack method="post" action="/-/new" { |
| 1030 | 1034 | | (csrf_input(csrf)) |
| 1031 | 1035 | | p { label { "Name" br; input type="text" name="name" value=(name) placeholder="my-project" autofocus; } } |
| ⋯ 92 unchanged lines |
| 1124 | 1128 | | user, |
| 1125 | 1129 | | html! { |
| 1126 | 1130 | | h1 { a href=(format!("/{owner}/{repo}")) { (owner) "/" (repo) } " · settings" } |
| 1127 | | - | @if let Some(error) = error { p style="color:#cf222e" { (error) } } |
| 1131 | + | @if let Some(error) = error { p.error-msg { (error) } } |
| 1128 | 1132 | | form.stack method="post" action=(format!("/{owner}/{repo}/settings")) { |
| 1129 | 1133 | | (csrf_input(csrf)) |
| 1130 | 1134 | | p { label { "Description" br; input type="text" name="description" value=(meta.description); } } |
| ⋯ 501 unchanged lines |
| 1632 | 1636 | | h1 { a href=(format!("/{owner}/{repo}")) { (owner) "/" (repo) } } |
| 1633 | 1637 | | (breadcrumbs(owner, repo, rev, path, true)) |
| 1634 | 1638 | | p.muted { "Editing on branch " code { (rev) } " — commits as you." } |
| 1635 | | - | @if let Some(error) = error { p style="color:#cf222e" { (error) } } |
| 1639 | + | @if let Some(error) = error { p.error-msg { (error) } } |
| 1636 | 1640 | | form.stack method="post" action=(action) { |
| 1637 | 1641 | | (csrf_input(csrf)) |
| 1638 | 1642 | | input type="hidden" name="expected_tip" value=(expected_tip); |
| ⋯ 369 unchanged lines |
| 2008 | 2012 | | h1 { a href=(format!("/{owner}/{repo}")) { (owner) "/" (repo) } } |
| 2009 | 2013 | | (breadcrumbs(owner, repo, rev, path, true)) |
| 2010 | 2014 | | h2 { "Add a task" } |
| 2011 | | - | @if let Some(error) = error { p style="color:#cf222e" { (error) } } |
| 2015 | + | @if let Some(error) = error { p.error-msg { (error) } } |
| 2012 | 2016 | | form.stack method="post" action=(action) { |
| 2013 | 2017 | | (csrf_input(csrf)) |
| 2014 | 2018 | | input type="hidden" name="expected_tip" value=(expected_tip); |
| ⋯ 145 unchanged lines |
| 2160 | 2164 | | }; |
| 2161 | 2165 | | |
| 2162 | 2166 | | let mut html = String::from( |
| 2163 | | - | r#"<div class="language-bar" style="display:flex;border-radius:4px;overflow:hidden;height:20px;background:#f0f0f0;">"#, |
| 2167 | + | r#"<div class="language-bar" style="display:flex;border-radius:4px;overflow:hidden;height:20px;background:var(--code-bg);">"#, |
| 2164 | 2168 | | ); |
| 2165 | 2169 | | for lang_obj in langs { |
| 2166 | 2170 | | if let (Some(lang), Some(percent)) = ( |
| ⋯ 690 unchanged lines |