aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmed <git@gumx.cc>2026-06-18 00:10:20 +0300
committerAhmed <git@gumx.cc>2026-06-18 00:10:20 +0300
commitd6c3e7e8989bf2eb8c6038cfa3fd5aeddf893ad7 (patch)
tree2d0788107c2f9e81ebd1037fa484dd47fee2e2b3
parent361cecee3636036625a26e29811a37ce5b808580 (diff)
fix: favicon and style, again
-rw-r--r--ccc.html293
-rw-r--r--favicon.svg1
-rw-r--r--hooks/post-receive49
-rw-r--r--styles/ccc.css155
-rw-r--r--styles/main.css102
5 files changed, 288 insertions, 312 deletions
diff --git a/ccc.html b/ccc.html
index def1860..1497a70 100644
--- a/ccc.html
+++ b/ccc.html
@@ -5,294 +5,9 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>gumx / coffee</title>
- <link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNDAiIGhlaWdodD0iMTQwIiBzdHJva2U9IiMwMDAiPjxwYXRoIHN0cm9rZS13aWR0aD0iMTIyIiBzdHJva2UtZGFzaGFycmF5PSIyLDM4IiBkPSJtOSw3MGgxMjJNNzAsOXYxMjIiLz48cGF0aCBzdHJva2Utd2lkdGg9IjMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Im03MCwzMGgwbTQwLDQwaDBtLTgwLDQwdjBtNDAsMGgwbTQwLDBoMCIvPjwvc3ZnPg==">
- <style>
- @font-face { font-family: "Kawkab Mono"; src: url(/fonts/KawkabMono-Regular.woff2); font-weight: normal; }
- @font-face { font-family: "Kawkab Mono"; src: url(/fonts/KawkabMono-Bold.woff2); font-weight: bold; }
-
- /* ── CONFIG ─────────────────────────────────────────────── */
- /* Edit these two values to configure the app. */
- /* DATA_URL: "" = local mode, "<url>" = static site mode */
- /* MAX_CUPS: maximum cups per day */
- /* WEEK_START: first day of week (0=Sun, 1=Mon … 6=Sat) */
-
- :root {
- --bg: #fff;
- --fg: #111;
- --muted: #888;
- --border: #ccc;
- --cell-0: #eee;
- --cell-1: #bbb;
- --cell-2: #888;
- --cell-3: #555;
- --cell-4: #222;
- --today-outline: #111;
- --tooltip-bg: #000;
- --tooltip-fg: #fff;
- --hover-bg: #111;
- --hover-fg: #fff;
- --popover-bg: #fff;
- --popover-border: #ccc;
- }
-
- @media (prefers-color-scheme: dark) {
- :root {
- --bg: #111;
- --fg: #eee;
- --muted: #777;
- --border: #444;
- --cell-0: #222;
- --cell-1: #444;
- --cell-2: #666;
- --cell-3: #999;
- --cell-4: #ccc;
- --today-outline: #eee;
- --tooltip-bg: #fff;
- --tooltip-fg: #000;
- --hover-bg: #eee;
- --hover-fg: #111;
- --popover-bg: #1a1a1a;
- --popover-border: #444;
- }
- }
-
- *,
- *::before,
- *::after {
- unicode-bidi: plaintext;
- box-sizing: border-box;
- margin: 0;
- padding: 0;
- }
-
- body {
- font-family: "Kawkab Mono", monospace;
- background: var(--bg);
- color: var(--fg);
- margin: 0;
- padding: 4rem 0;
- line-height: 1.4;
- font-size: 16px;
- min-height: 100%;
- overflow-wrap: break-word;
- }
-
- header, main, footer { max-width: 800px; margin-inline: auto; padding: 0 2rem; }
- h1, header, footer { text-align: center; }
- main { text-align: left; }
- header { margin-bottom: 1em; }
- footer { margin-top: 3em; }
-
- h1 {
- font-size: 1.2rem;
- margin-bottom: 0.25rem;
- }
-
- h2 {
- font-size: 0.95rem;
- margin: 1.5rem 0 0.5rem;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- color: var(--muted);
- }
-
- hr {
- border: none;
- border-top: 1px solid var(--border);
- margin: 1.25rem 0;
- }
-
- ul {
- list-style: none;
- padding: 0;
- }
-
- ul li {
- padding: 0.1rem 0;
- }
-
- .subtitle {
- color: var(--muted);
- font-size: 0.85rem;
- margin-bottom: 1rem;
- }
-
- .static-notice {
- font-size: 0.8rem;
- color: var(--muted);
- border: 1px solid var(--border);
- padding: 0.4rem 0.7rem;
- margin-bottom: 1rem;
- display: inline-block;
- }
-
- /* ── HEATMAP ─────────────────────────────────────────────── */
- .heatmap-wrap {
- overflow-x: auto;
- margin: 0.5rem 0 0.25rem;
- }
-
- #heatmap-svg {
- display: block;
- font-family: inherit;
- }
-
- .cell {
- cursor: pointer;
- }
-
- .cell:hover rect {
- opacity: 0.75;
- }
-
- /* ── LEGEND ─────────────────────────────────────────────── */
- .legend {
- display: flex;
- align-items: center;
- gap: 0.35rem;
- font-size: 0.75rem;
- color: var(--muted);
- margin-top: 0.35rem;
- flex-wrap: wrap;
- }
-
- .legend-swatch {
- width: 10px;
- height: 10px;
- border-radius: 2px;
- display: inline-block;
- flex-shrink: 0;
- }
-
- /* ── CONTROLS ────────────────────────────────────────────── */
- .controls {
- margin-top: 0.25rem;
- }
-
- .row {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- flex-wrap: wrap;
- margin-bottom: 0.5rem;
- }
-
- button {
- font-family: inherit;
- font-size: 0.85rem;
- background: var(--bg);
- color: var(--fg);
- border: 1px solid var(--border);
- padding: 0.2rem 0.65rem;
- cursor: pointer;
- line-height: 1.5;
- transition: background 0.1s, color 0.1s;
- }
-
- button:hover:not(:disabled) {
- background: var(--hover-bg);
- color: var(--hover-fg);
- }
-
- button:disabled {
- opacity: 0.35;
- cursor: not-allowed;
- }
-
- .count-display {
- min-width: 1.8rem;
- text-align: center;
- font-size: 0.85rem;
- }
-
- .hint {
- font-size: 0.75rem;
- color: var(--muted);
- margin-top: 0.3rem;
- }
-
- /* ── STATS ───────────────────────────────────────────────── */
- .stats-list li {
- display: flex;
- gap: 0.75rem;
- }
-
- .stats-list .label {
- color: var(--muted);
- min-width: 130px;
- }
-
- .stats-list .value {
- font-weight: bold;
- }
-
- /* ── TOOLTIP ─────────────────────────────────────────────── */
- #tooltip {
- position: fixed;
- background: var(--tooltip-bg);
- color: var(--tooltip-fg);
- font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;
- font-size: 0.75rem;
- padding: 0.3rem 0.6rem;
- pointer-events: none;
- z-index: 1000;
- white-space: nowrap;
- display: none;
- border-radius: 2px;
- }
-
- /* ── POPOVER ─────────────────────────────────────────────── */
- #popover {
- position: absolute;
- background: var(--popover-bg);
- border: 1px solid var(--popover-border);
- padding: 0.75rem 1rem;
- z-index: 500;
- display: none;
- min-width: 200px;
- font-size: 0.85rem;
- }
-
- #popover .pop-title {
- font-size: 0.75rem;
- color: var(--muted);
- margin-bottom: 0.5rem;
- }
-
- #popover .pop-row {
- display: flex;
- align-items: center;
- gap: 0.4rem;
- margin-bottom: 0.5rem;
- }
-
- #popover input[type="number"] {
- font-family: inherit;
- font-size: 0.85rem;
- width: 3.5rem;
- background: var(--bg);
- color: var(--fg);
- border: 1px solid var(--border);
- padding: 0.2rem 0.4rem;
- text-align: center;
- -moz-appearance: textfield;
- }
-
- #popover input[type="number"]::-webkit-inner-spin-button,
- #popover input[type="number"]::-webkit-outer-spin-button {
- -webkit-appearance: none;
- }
-
- #popover .pop-actions {
- display: flex;
- gap: 0.4rem;
- }
-
- /* ── IMPORT HIDDEN ───────────────────────────────────────── */
- #import-input {
- display: none;
- }
- </style>
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg">
+ <link rel="stylesheet" href="/styles/main.css">
+ <link rel="stylesheet" href="/styles/ccc.css">
</head>
<body>
@@ -377,7 +92,7 @@
// CONFIG — edit these values to configure the app
// ─────────────────────────────────────────────────────────────
const CONFIG = {
- DATA_URL: "", // "" = local mode | "<url>" = static site mode
+ DATA_URL: "data.json", // "" = local mode | "<url>" = static site mode
MAX_CUPS: 5, // maximum cups allowed per day
WEEK_START: 6, // first day of the week: 0=Sun, 1=Mon, 2=Tue, 3=Wed, 4=Thu, 5=Fri, 6=Sat
};
diff --git a/favicon.svg b/favicon.svg
new file mode 100644
index 0000000..4f9ab68
--- /dev/null
+++ b/favicon.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="140" height="140" stroke="#000"><path stroke-width="122" stroke-dasharray="2,38" d="m9,70h122M70,9v122"/><path stroke-width="33" stroke-linecap="round" d="m70,30h0m40,40h0m-80,40v0m40,0h0m40,0h0"/></svg>
diff --git a/hooks/post-receive b/hooks/post-receive
index 1240593..d492010 100644
--- a/hooks/post-receive
+++ b/hooks/post-receive
@@ -1,27 +1,30 @@
#!/bin/sh
set -e
WORK=/home/git/build/ccc
-WEBROOT=/var/www/coffee.gumx.cc
-mkdir -p "$WEBROOT/fonts"
-cp "$WORK/ccc.html" "$WEBROOT/index.html"
-rsync -rlptD "$WORK/fonts/" "$WEBROOT/fonts/" 2>/dev/null || true
-python3 - "$WEBROOT/index.html" <<'EOF'
-import sys
-p = sys.argv[1]
-html = open(p).read()
-footer = (
- '<footer>\n<hr>\n'
- '<a href="https://twt.gumx.cc">twt</a> /\n'
- '<a href="https://git.gumx.cc">git</a> /\n'
- '<a href="https://mail.gumx.cc">mail</a> /\n'
- '<a href="https://irc.gumx.cc">irc</a> /\n'
- '<a href="https://files.gumx.cc">files</a> /\n'
- '<a href="https://vpn.gumx.cc">vpn</a> /\n'
- '<a href="https://pgp.gumx.cc">pgp</a> /\n'
- '<a href="https://demo.gumx.cc">demo</a> /\n'
- '<a href="https://wk.fo">wk.fo</a>\n'
- '</footer>'
-)
-open(p, 'w').write(html.replace('</body>', footer + '\n</body>'))
+COFFEE=/var/www/coffee.gumx.cc
+DEMO=/var/www/demo.gumx.cc
+
+# ── coffee.gumx.cc (personal log: DATA_URL=data.json, with footer) ──────────
+mkdir -p "$COFFEE/styles" "$COFFEE/fonts"
+cp "$WORK/ccc.html" "$COFFEE/index.html"
+cp "$WORK/favicon.svg" "$COFFEE/favicon.svg"
+cp "$WORK/styles/main.css" "$COFFEE/styles/main.css"
+cp "$WORK/styles/ccc.css" "$COFFEE/styles/ccc.css"
+rsync -rlptD "$WORK/fonts/" "$COFFEE/fonts/" 2>/dev/null || true
+
+# ── demo.gumx.cc/ccc (public demo: local mode, no footer) ───────────────────
+mkdir -p "$DEMO/ccc" "$DEMO/styles" "$DEMO/fonts"
+python3 - "$WORK/ccc.html" "$DEMO/ccc/index.html" <<'EOF'
+import sys, re
+src, dst = sys.argv[1], sys.argv[2]
+html = open(src).read()
+html = html.replace('DATA_URL: "data.json"', 'DATA_URL: ""')
+html = re.sub(r'\n <footer>.*?</footer>', '', html, flags=re.DOTALL)
+open(dst, 'w').write(html)
EOF
-echo "ccc deployed to coffee.gumx.cc"
+cp "$WORK/favicon.svg" "$DEMO/favicon.svg"
+cp "$WORK/styles/main.css" "$DEMO/styles/main.css"
+cp "$WORK/styles/ccc.css" "$DEMO/styles/ccc.css"
+rsync -rlptD "$WORK/fonts/" "$DEMO/fonts/" 2>/dev/null || true
+
+echo "ccc deployed to coffee.gumx.cc and demo.gumx.cc/ccc"
diff --git a/styles/ccc.css b/styles/ccc.css
new file mode 100644
index 0000000..cbf4853
--- /dev/null
+++ b/styles/ccc.css
@@ -0,0 +1,155 @@
+/* ccc app-specific styles — base typography/layout from /styles/main.css */
+
+/* Extra reset the app needs beyond main.css */
+*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+
+/* App CSS variables (light mode; dark mode via filter:invert in main.css) */
+:root {
+ --muted: #888;
+ --border: #ccc;
+ --bg: #fff;
+ --fg: #111;
+ --cell-0: #eee;
+ --cell-1: #bbb;
+ --cell-2: #888;
+ --cell-3: #555;
+ --cell-4: #222;
+ --today-outline: #111;
+ --tooltip-bg: #000;
+ --tooltip-fg: #fff;
+ --hover-bg: #111;
+ --hover-fg: #fff;
+ --popover-bg: #fff;
+ --popover-border: #ccc;
+}
+
+h1 { font-size: 1.2rem; margin-bottom: 0.25rem; }
+
+h2 {
+ font-size: 0.95rem;
+ margin: 1.5rem 0 0.5rem;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+ color: var(--muted);
+}
+
+hr {
+ border: none;
+ border-top: 1px solid var(--border);
+ margin: 1.25rem 0;
+}
+
+ul { list-style: none; padding: 0; }
+ul li { padding: 0.1rem 0; }
+
+.subtitle { color: var(--muted); font-size: 0.85rem; margin-bottom: 1rem; }
+
+.static-notice {
+ font-size: 0.8rem;
+ color: var(--muted);
+ border: 1px solid var(--border);
+ padding: 0.4rem 0.7rem;
+ margin-bottom: 1rem;
+ display: inline-block;
+}
+
+/* ── Heatmap ─────────────────────────────────────────────── */
+.heatmap-wrap { overflow-x: auto; margin: 0.5rem 0 0.25rem; }
+#heatmap-svg { display: block; font-family: inherit; }
+.cell { cursor: pointer; }
+.cell:hover rect { opacity: 0.75; }
+
+/* ── Legend ──────────────────────────────────────────────── */
+.legend {
+ display: flex;
+ align-items: center;
+ gap: 0.35rem;
+ font-size: 0.75rem;
+ color: var(--muted);
+ margin-top: 0.35rem;
+ flex-wrap: wrap;
+}
+.legend-swatch {
+ width: 10px;
+ height: 10px;
+ border-radius: 2px;
+ display: inline-block;
+ flex-shrink: 0;
+}
+
+/* ── Controls ────────────────────────────────────────────── */
+.controls { margin-top: 0.25rem; }
+.row {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ flex-wrap: wrap;
+ margin-bottom: 0.5rem;
+}
+
+button {
+ font-family: inherit;
+ font-size: 0.85rem;
+ background: var(--bg);
+ color: var(--fg);
+ border: 1px solid var(--border);
+ padding: 0.2rem 0.65rem;
+ cursor: pointer;
+ line-height: 1.5;
+ transition: background 0.1s, color 0.1s;
+}
+button:hover:not(:disabled) { background: var(--hover-bg); color: var(--hover-fg); }
+button:disabled { opacity: 0.35; cursor: not-allowed; }
+
+.count-display { min-width: 1.8rem; text-align: center; font-size: 0.85rem; }
+.hint { font-size: 0.75rem; color: var(--muted); margin-top: 0.3rem; }
+
+/* ── Stats ───────────────────────────────────────────────── */
+.stats-list li { display: flex; gap: 0.75rem; }
+.stats-list .label { color: var(--muted); min-width: 130px; }
+.stats-list .value { font-weight: bold; }
+
+/* ── Tooltip ─────────────────────────────────────────────── */
+#tooltip {
+ position: fixed;
+ background: var(--tooltip-bg);
+ color: var(--tooltip-fg);
+ font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, "DejaVu Sans Mono", monospace;
+ font-size: 0.75rem;
+ padding: 0.3rem 0.6rem;
+ pointer-events: none;
+ z-index: 1000;
+ white-space: nowrap;
+ display: none;
+ border-radius: 2px;
+}
+
+/* ── Popover ─────────────────────────────────────────────── */
+#popover {
+ position: absolute;
+ background: var(--popover-bg);
+ border: 1px solid var(--popover-border);
+ padding: 0.75rem 1rem;
+ z-index: 500;
+ display: none;
+ min-width: 200px;
+ font-size: 0.85rem;
+}
+#popover .pop-title { font-size: 0.75rem; color: var(--muted); margin-bottom: 0.5rem; }
+#popover .pop-row { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.5rem; }
+#popover input[type="number"] {
+ font-family: inherit;
+ font-size: 0.85rem;
+ width: 3.5rem;
+ background: var(--bg);
+ color: var(--fg);
+ border: 1px solid var(--border);
+ padding: 0.2rem 0.4rem;
+ text-align: center;
+ -moz-appearance: textfield;
+}
+#popover input[type="number"]::-webkit-inner-spin-button,
+#popover input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; }
+#popover .pop-actions { display: flex; gap: 0.4rem; }
+
+#import-input { display: none; }
diff --git a/styles/main.css b/styles/main.css
new file mode 100644
index 0000000..c4bd01c
--- /dev/null
+++ b/styles/main.css
@@ -0,0 +1,102 @@
+@font-face {
+ font-family: "Kawkab Mono";
+ src: url(/fonts/KawkabMono-Regular.woff2);
+ font-weight: normal;
+}
+
+@font-face {
+ font-family: "Kawkab Mono";
+ src: url(/fonts/KawkabMono-Bold.woff2);
+ font-weight: bold;
+}
+
+* {
+ unicode-bidi: plaintext;
+}
+
+html {
+ color: black;
+ background-color: white;
+}
+
+body {
+ font-family: "Kawkab Mono";
+ font-size: 16px;
+ line-height: 1.4;
+ margin: 0;
+ padding: 4rem 0;
+ min-height: 100%;
+ overflow-wrap: break-word;
+}
+
+h1,
+header,
+footer {
+ text-align: center;
+}
+
+main {
+ text-align: left;
+}
+
+main,
+header,
+footer {
+ max-width: 800px;
+ margin-inline: auto;
+ padding: 0 2rem;
+}
+
+@media (max-width: 600px) {
+ body {
+ font-size: 0.9em;
+ }
+
+ h1 {
+ font-size: 1.8em;
+ }
+}
+
+@media (max-width: 400px) {
+ body {
+ font-size: 0.8em;
+ }
+
+ h1 {
+ font-size: 1.6em;
+ }
+}
+
+p,
+h2,
+h3,
+h4 {
+ margin: 1em 0 0 0;
+}
+
+ul,
+ol {
+ margin: 0;
+}
+
+img {
+ max-width: 100%;
+}
+
+header {
+ margin-bottom: 1em;
+}
+
+footer {
+ margin-top: 3em;
+}
+
+@media (prefers-color-scheme: dark) {
+ html {
+ filter: invert(1);
+ }
+
+ img {
+ filter: invert(1);
+ }
+}