From ab3e508b9bdfe313d6fe2bc78a6c30efb1726e5c Mon Sep 17 00:00:00 2001 From: martian56 Date: Sat, 25 Jul 2026 13:07:07 +0400 Subject: [PATCH 1/3] Adopt the keyword chip, button caps and drawn divider Takes the transferable parts of the reference system: one accent keyword highlighted inside the headline, uppercase button labels with a tracking lift, and a drawn divider above the footer instead of a rule. The accent is the cyan already in the palette rather than a new colour, and one chip per viewport keeps it doing work. --- web/index.html | 5 ++++- web/style.css | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/web/index.html b/web/index.html index 17da9cc..58a235c 100644 --- a/web/index.html +++ b/web/index.html @@ -39,7 +39,7 @@

A durable OLTP engine, written in Rust

-

A database that shows its work.

+

A database that shows its work.

Every page is checksummed. Every commit waits for the log. Every benchmark names the machine it ran on, and a result is thrown out if a @@ -272,6 +272,9 @@

Do not store data you love in this. Yet.

- + -
- -
-
-

A durable OLTP engine, written in Rust

-

A database that shows its work.

-

- Every page is checksummed. Every commit waits for the log. Every - benchmark names the machine it ran on, and a result is thrown out if a - single correctness test fails. QuantaDB is being built the slow way: - storage first, proofs before promises. +

+
+
+

An OLTP database, measured in the open.

+

+ QuantaDB is a storage engine written in Rust and spoken to over the + PostgreSQL wire protocol. Every benchmark names the machine it ran on, + runs beside PostgreSQL, MySQL and MariaDB, and gets published whether it + wins or loses.

-
-
- data page 42, byte for byte -
-
-
- 0000 - 51 4E 50 47 - magic "QNPG": this is a page -
-
- 0004 - 01 00  00 00 - format v1, reserved -
-
- 0008 - 2A 00 00 00 00 00 00 00 - page ID 42, little endian -
-
- 0010 - C4 01 00 00 00 00 00 00 - last applied log sequence number -
-
- 0018 - 9A 00 00 00 - payload length, 154 bytes -
-
- 001C - 7B 3D 91 C8 - CRC32 over the whole page -
-
- 0020 - 00 00 00 00 … - 32 reserved bytes -
-
- 0040 - 51 4E 4D 56 01 00 00 00 - payload: an MVCC version record, "QNMV" +
+
+
22,528Reads per second, ahead of PostgreSQL
+
<1 msRead latency at the 99th percentile
+
5Machine profiles benched per change
+
Apache-2.0Open source, no paid tier
+
+
+
+ +
+
+
+

Why it exists

+

Most database benchmarks are marketing. These are not.

+

+ Performance claims usually arrive without the hardware, the + competitors, or the runs that went badly. QuantaDB publishes all + three, because a number you cannot reproduce is not a number. +

+
+
+
+

Durable by default

+

+ A commit returns once its record is on disk. Pages carry checksums, + the log is replayed on restart, and corruption is detected rather + than assumed away. There is no faster mode that quietly drops this. +

-
- 0048 - 1D 00 00 00 00 00 00 00 - committed at timestamp 29 +
+

Readers never wait for writers

+

+ Snapshot isolation with multi-version reads. A query sees a + consistent moment in time and takes no locks, so a long read cannot + be blocked by a slow commit. +

-
- 0050 - - key, value, zero padding to 8192 +
+

Speaks PostgreSQL

+

+ Connect with psql, psycopg, or any Postgres driver you already use. + There is a native protocol and a browser client too, but nothing + forces you onto them. +

-

- A page is never written before its log record and batch commit are on - disk. Recovery replays complete batches only, so a crash exposes all of - a commit or none of it. -

- +
-
-
-

On disk

-

Five magics, one rule: versioned, checksummed, documented.

-

- Everything QuantaDB persists starts with four bytes that say what it is - and a version that says how to read it. Readers verify before trusting. - The formats are documented in the repository down to the byte, because a - storage engine you cannot audit is a storage engine you cannot trust. +

+
+
+

Benchmarks

+

Four engines, identical containers, one driver.

+

+ Each database runs alone at 2 CPUs and 2 GiB with default durability, + driven by the same client over the same protocol. Operations per + second, higher is better. +

+
+ +
+ + + + + + + + + + +
EngineReadsMixed 80/20Writes
QuantaDB22,52816,7748,374
PostgreSQL 1817,06017,00611,404
MariaDB 11.43,7354,0066,741
MySQL 8.43,8043,8454,847
+
+

+ QuantaDB leads on reads and ties on mixed. PostgreSQL still leads on + writes, and the gap is tracked in the open. Read throughput for MySQL and + MariaDB is limited by the shared Python driver; their write numbers are + server bound.

-
-
    -
  • QNPGdata page8192 bytes, CRC32, identity checked on every read
  • -
  • QNWLlog recordphysical page image, batch commit, or checkpoint
  • -
  • QNMVversion recordkey, optional value, commit timestamp
  • -
  • QNIXindex nodeimmutable B+ tree leaf or internal node
  • -
  • QNIRindex root48 byte manifest publishing one generation
  • -
+
-
-
-

Architecture

-

Six crates, one direction.

-

- The dependency graph is acyclic and enforced: parsing knows nothing of - storage, the server delegates everything to the engine, and the network - threads never touch a disk. Each layer is testable, and tested, alone. -

-
-
    -
  • - -

    syntax

    -

    A dependency-light SQL lexer and parser. Every token carries a byte - span, so an error can point at the exact character that caused it.

    -
  • -
  • - -

    storage

    -

    Checksummed pages, a physical write-ahead log, restart recovery, and - a group commit coordinator that lets concurrent writers share syncs.

    -
  • -
  • - -

    index

    -

    Immutable B+ tree generations. Readers traverse without locks while - the next generation is built beside them, never on top of them.

    -
  • -
  • - -

    mvcc

    -

    Snapshot isolation with first-committer-wins conflicts. Versions - become visible only after the log says they are durable. Old versions - are reclaimed the moment no snapshot can see them.

    -
  • -
  • - -

    engine

    -

    The relational layer: schemas, constraints, typed expressions, and - transactional CRUD mapped onto ordered binary keys.

    -
  • -
  • - -

    server

    -

    A TCP server bounded on every axis: connections, in-flight requests, - frame size, idle time. Overload gets a clean error, not a hung socket.

    -
  • -
+
+
+
+

Get started

+

Running in about a minute.

+

Start the server, then connect with the Postgres client you already have.

+
+
# start a server
+docker run -p 55432:55432 ghcr.io/martian56/quantadb
+
+# connect with psql
+psql "host=127.0.0.1 port=55432 user=quanta dbname=quanta"
+
+CREATE TABLE notes (id BIGINT PRIMARY KEY, body TEXT NOT NULL);
+INSERT INTO notes VALUES (1, 'durable on return');
+SELECT * FROM notes;
+
-
-
-

Measured, not promised

-

The benchmark log is part of the changelog.

-

- These are medians from the development machine: a Core i5-1035G1 laptop - with a consumer NVMe drive, full sync on every commit. Not a marketing - rig. When a change regresses a number, the number gets published anyway - and the regression gets fixed next. -

-
-
- - - - - - - - - -
criterion medians, 2026-07-23
hot indexed point lookup705 ns
in-memory snapshot read583 ns
parse a point select2.8 µs
B+ tree range scan, 100 keys13.3 µs
durable single-key commit16.1 ms, the disk's fsync
-
-

one workload, one week

-

736 to 2607 ops/s

+
+
+
+

Status

+

Honest about where this is.

- The same mixed workload, before and after a node cache, online index - publication, version reclamation, and a record cache. The read tail - fell from 139 ms worst case to 18.5 ms. One intermediate change made - reads worse; the benchmark caught it before main did. + QuantaDB is experimental. It has no authentication and no replication, + and it is not where your production data should live yet.

+
    +
  • Done
    Storage kernel

    Checksummed pages, write-ahead log, group commit, crash recovery.

  • +
  • Done
    Transactions and indexes

    MVCC snapshots, B+ tree indexes published online, version reclamation.

  • +
  • Done
    PostgreSQL wire protocol

    Simple and extended queries, so existing drivers connect unmodified.

  • +
  • Now
    Write throughput

    Closing the remaining gap to PostgreSQL on durable commits.

  • +
  • Next
    Authentication, TLS, replication

    The work that has to land before anyone stores something they care about.

  • +
-
-
-

Protocol v1

-

One JSON frame per line. Deliberately boring.

-

- The current wire protocol is built for debugging a young database: you - can drive it with a terminal and read every byte. PostgreSQL wire - compatibility is on the roadmap; this is the scaffolding that gets us - there honestly. +

+
+

Read the code, run the benchmarks.

+

+ Everything is Apache-2.0, including the harness that produced the numbers + on this page. Disagree with them and you can rerun them.

-
-
-
-
-

Status

-

Do not store data you love in this. Yet.

-

- QuantaDB is a working engine and an honest work in progress. The v0.1 - prototype was retired; the current codebase is a clean foundation with - real durability guarantees and a long road ahead. Milestones are - numbered because they are a sequence: each one is load-bearing for the - next. -

-
-
    -
  1. M1

    Syntax and server foundation

    Span-aware parser, versioned protocol, bounded connections.

  2. -
  3. M2

    Durable storage kernel

    Pages, WAL, group commit, crash recovery, corruption detection.

  4. -
  5. M3

    Transactions and indexes

    MVCC, online index generations, reclamation, and a concurrent - history checker that has already caught two real bugs. Range conflict - tracking remains.

  6. -
  7. M4

    Execution engine

    Planner, joins, ordering, secondary indexes, cost-based decisions.

  8. -
  9. M5

    Production operations

    PostgreSQL wire protocol, auth, TLS, backup, format stability.

  10. -
  11. M6

    Replication

    Replicated log, failover, and adversarial failure testing before any - talk of distribution.

  12. -
-
- -
- -
- - diff --git a/web/logo-mark.png b/web/logo-mark.png index 79749fbf87fe7a2c05ae8d258c28d26da0eebc12..450b5af77a0dc909c306bf2462495cb11c81faa8 100644 GIT binary patch literal 8429 zcmeI1_ghoxw#PSJ1jLAgj5LL@M5;&&EvS?sbixQI5EKznA_yWq0U0%lfF%?m5D*hU zkS<6~919AP(2*KML+CY>K+4^obACL}bN_&Q^GovVz4p7`vetKf*2)7HCtI1_2X_Mi zAY=EZl^XyEgFl6VUE<&uJF0IR01nmKS)F!|A}owaJ@y^+QCJo?3We*Ab- z>T8auFupd3@L4|f!CBH7Q>_3!e-lZSN@(savemG#vZ7J<-jlkyPQu8nGXb-I_oWl; zO!mAp7Cnl8YV2&3H4qJ}^1o2sOpi4Qj40=5j`Wyh+@{1*7$H{z*B8nI%jqpFf`CJ8 zO93bJ|DXS|1L8-}Y%yI<7%fjOuM+QeE?Ch6o(>OuagkMZ@Y$95p{q#5>r0al+F_A& zS5Eu7*S`H_NS-^N@Bm0yu^~M=cuuAC&oG*)+9jKtRpKOMqu^#EG~8AzZmS#@bXZJE z6%QzBwPwZdP={{r`gRG|OHPQo-{j53FR+kgoW0s)3S>oAee$_te2TQ&3|C;RcHLj*Nkws4Ltmc3-lm2^9Us141mA*ENwE(&4Xw`f~4WTaQFVnsy ztZrPIcJcR_L2RZgcE!@F*;K9E5gJd@_U`Dd^9;?MEm~zk^w~(iX4g)bz|)F*-m3W} zKZbMCCNPwy+A&-bAvM^l0HNUBVj?%cI&};u$h;!9s|rzTU+xd5oqBVzA*Sr&%(=_& zUy2G-4nW`+ZbKa2aW-HvLPCGBu|b*;?>kP$ao7M zlTRyuEuYo9xE?Ho18s&pWT^!Dk%Y?{o4%gZ>sg-LHTFhsdwH*Efn+%m>B=Yk zA);&PpVHBxHkpBo`sDfXo?X3LFXNcnWY4gq%u(gBq;1&rDr;#MAl{f?T&~h;pysQ8 zF-6MkiPQ8rZtHt?>LTwSs!BiobOt=_4?tlN_FeVFZ;@vd4@9Zub}2(v9ySK(ZVyYY zS7P?O;zsLBy}L)U@AW|`W|AatcuzRkyh+k5{2AGwT0~FEXziyLq{E9sPf1(~_Fb`6 zpCn7FdQs)NwNhil5i|AM#;Rj$+e166tSU)BJfAGzF*wk8m(>uF=X&q{;px;j<|+`z z`80@Ayq&ddK4znl8yy!P4ZvDlUq51Qb+P&zOgA$Mj^_qOw|3+#V@N7;qebuR8FPV* z4r1H)qZ{7JKKq?haP)z}J2BC+XM0o5*t0kbkd+3DM`tA5;jvzPf-mufiwgFZ>xn7) zfX$~f%J+&D?`AYiV|xo-r(I?PQ60qIP?6Z+;9IU!@^Co_eRgP6%?vW8D6D!yqZf%l zW&doM5h)|KoWRn`DrD8tlzf^E)$)AQZ*AfW5C&o`T522pM90-Ni`wm>`c;;hUxr*|W z(7;;<)I!PDnFv8*miO6mV*GLJfF;m{Wwdl302KQgFoCirgNFy`7T_Tr2Bs^@ds^}_ zs%KӃ+h)6mqq^)k$@!{b?x&_#;St#2 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 diff --git a/web/logo.svg b/web/logo.svg index ebf3486..f534f9e 100644 --- a/web/logo.svg +++ b/web/logo.svg @@ -2,13 +2,13 @@ QuantaDB - - + + - - - - - + + + + + diff --git a/web/style.css b/web/style.css index b61fb75..a3831c0 100644 --- a/web/style.css +++ b/web/style.css @@ -1,646 +1,317 @@ -/* QuantaDB site styles. - Identity: engineering literature. Old-style serif prose, monospace - artifacts, and a spectral line system keyed to the on-disk magics. - No sans-serif, no icon fonts, no external resources. */ - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} +/* QuantaDB — white canvas, purple brand, quiet depth. */ :root { - --field: #10151d; - --panel: #151b25; - --panel-edge: #232c3a; - --rule: #1d2531; - --text: #c3cad4; - --text-dim: #828d9d; - --bright: #eef1f5; - - --sp-storage: #e0a458; - --sp-wal: #d1873e; - --sp-mvcc: #8f7dff; - --sp-index: #45c8d8; - --sp-engine: #74c69d; - --sp-server: #d96052; - --sp-neutral: #97a1b0; - - --serif: "Palatino Linotype", Palatino, "Book Antiqua", "URW Palladio L", Georgia, serif; - --mono: ui-monospace, "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace; - - --measure: 62ch; - --gutter: clamp(1.25rem, 4vw, 3rem); -} - -html { - scroll-behavior: smooth; -} - -body { - background: var(--field); - color: var(--text); - font-family: var(--serif); - font-size: 1.0625rem; - line-height: 1.65; - -webkit-font-smoothing: antialiased; -} + --purple: #7132f5; + --purple-dark: #5741d8; + --purple-deep: #5b1ecf; + --purple-subtle: rgba(133, 91, 251, 0.16); -::selection { - background: #2c3a52; - color: var(--bright); -} + --ink: #101114; + --gray: #686b82; + --silver: #9497a9; + --border: #dedee5; + --surface: #ffffff; + --surface-soft: #fafafc; -a { - color: var(--bright); - text-decoration: underline; - text-decoration-color: var(--text-dim); - text-underline-offset: 3px; -} + --green: #149e61; + --green-deep: #026b3f; + --green-soft: rgba(20, 158, 97, 0.16); -a:hover { - text-decoration-color: var(--bright); -} + --display: "IBM Plex Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + --ui: "Helvetica Neue", Helvetica, Arial, sans-serif; + --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace; -a:focus-visible, -.button:focus-visible { - outline: 2px solid var(--sp-index); - outline-offset: 3px; - border-radius: 1px; -} + --shadow: rgba(0, 0, 0, 0.03) 0 4px 24px; + --shadow-micro: rgba(16, 24, 40, 0.04) 0 1px 4px; -code { - font-family: var(--mono); - font-size: 0.92em; + --wide: 1120px; + --gutter: clamp(1.25rem, 5vw, 2.5rem); } -/* The spectral line device. A line means "this maps to an on-disk format - or a crate"; it never appears as decoration alone. */ -.line { - display: inline-block; - width: 3px; - height: 1.05em; - margin-right: 0.65rem; - vertical-align: -0.18em; - background: var(--sp-neutral); -} +* { box-sizing: border-box; } -.sp-storage { background: var(--sp-storage); } -.sp-wal { background: var(--sp-wal); } -.sp-mvcc { background: var(--sp-mvcc); } -.sp-index { background: var(--sp-index); } -.sp-engine { background: var(--sp-engine); } -.sp-server { background: var(--sp-server); } -.sp-neutral { background: var(--sp-neutral); } - -/* Masthead */ -.masthead { - border-bottom: 1px solid var(--rule); - position: sticky; - top: 0; - background: color-mix(in srgb, var(--field) 92%, transparent); - backdrop-filter: blur(6px); - z-index: 10; -} +html { scroll-behavior: smooth; } -.masthead-inner { - max-width: 72rem; - margin: 0 auto; - padding: 0.8rem var(--gutter); - display: flex; - align-items: baseline; - gap: 1rem; +body { + margin: 0; + background: var(--surface); + color: var(--gray); + font-family: var(--ui); + font-size: 16px; + line-height: 1.38; + -webkit-font-smoothing: antialiased; } -.wordmark { - font-family: var(--serif); +h1, h2, h3 { + font-family: var(--display); + color: var(--ink); font-weight: 700; - font-size: 1.2rem; - color: var(--bright); - text-decoration: none; - letter-spacing: 0.01em; -} - -.version { - font-family: var(--mono); - font-size: 0.72rem; - color: var(--text-dim); - letter-spacing: 0.04em; -} - -.masthead-nav { - margin-left: auto; - display: flex; - gap: 1.1rem; - font-family: var(--mono); - font-size: 0.78rem; - letter-spacing: 0.03em; + margin: 0; } -.masthead-nav a { - color: var(--text-dim); - text-decoration: none; -} +h1 { font-size: clamp(2.1rem, 5vw, 3rem); line-height: 1.17; letter-spacing: -1px; } +h2 { font-size: clamp(1.7rem, 3.6vw, 2.25rem); line-height: 1.22; letter-spacing: -0.5px; } +h3 { font-family: var(--ui); font-size: 1.375rem; font-weight: 600; line-height: 1.2; } -.masthead-nav a:hover { - color: var(--bright); -} +a { color: inherit; } -.masthead-nav .repo-link { - color: var(--bright); -} +p { margin: 0; } -/* Shared band structure */ -main { - max-width: 72rem; +.wrap { + max-width: var(--wide); margin: 0 auto; padding: 0 var(--gutter); } -.eyebrow { - font-family: var(--mono); - font-size: 0.72rem; - text-transform: uppercase; - letter-spacing: 0.22em; - color: var(--text-dim); - margin-bottom: 0.9rem; -} - -.band { - padding: clamp(3.5rem, 8vw, 5.5rem) 0; - border-top: 1px solid var(--rule); -} +/* nav */ -.band-head h2 { - font-size: clamp(1.6rem, 3.4vw, 2.3rem); - line-height: 1.15; - color: var(--bright); - font-weight: 700; - max-width: 24ch; - letter-spacing: -0.01em; +.nav { + position: sticky; + top: 0; + z-index: 20; + background: rgba(255, 255, 255, 0.9); + backdrop-filter: blur(12px); + border-bottom: 1px solid var(--border); } -.band-lede { - max-width: var(--measure); - margin-top: 1.1rem; - color: var(--text); -} +.nav-inner { display: flex; align-items: center; gap: 2rem; height: 68px; } -/* Hero */ -.hero { - display: grid; - grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); - gap: clamp(2rem, 5vw, 4.5rem); +.brand { + display: inline-flex; align-items: center; - padding: clamp(3.5rem, 9vw, 7rem) 0 clamp(3rem, 7vw, 5.5rem); -} - -.hero h1 { - font-size: clamp(2.4rem, 5.4vw, 3.9rem); - line-height: 1.06; - color: var(--bright); - font-weight: 700; - letter-spacing: -0.015em; - max-width: 14ch; -} - -.lede { - margin-top: 1.4rem; - max-width: 46ch; - font-size: 1.1rem; -} - -.hero-actions { - margin-top: 2rem; - display: flex; - gap: 0.9rem; - flex-wrap: wrap; -} - -.button { - font-family: var(--mono); - font-size: 0.82rem; + gap: 0.6rem; + font-family: var(--display); + color: var(--ink); font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.2px; - color: var(--field); - background: var(--bright); - padding: 0.65rem 1.15rem; + font-size: 1.15rem; + letter-spacing: -0.5px; text-decoration: none; - border: 1px solid var(--bright); } -.button:hover { - background: var(--text); - border-color: var(--text); -} +.brand img { display: block; border-radius: 6px; } -.button.quiet { - background: transparent; - color: var(--bright); - border-color: var(--panel-edge); -} +.nav-links { display: flex; align-items: center; gap: 1.75rem; margin-left: auto; font-size: 0.95rem; } -.button.quiet:hover { - border-color: var(--text-dim); - background: var(--panel); -} +.nav-links a { color: var(--gray); text-decoration: none; transition: color 140ms ease; } -/* The page artifact */ -.page-artifact { - background: var(--panel); - border: 1px solid var(--panel-edge); - padding: 1.4rem 1.5rem 1.2rem; - min-width: 0; -} +.nav-links a:hover { color: var(--ink); } -.mono-label { - font-family: var(--mono); - font-size: 0.72rem; - text-transform: uppercase; - letter-spacing: 0.18em; - color: var(--text-dim); -} +/* buttons */ -.page-artifact figcaption { - margin-bottom: 1rem; - padding-bottom: 0.8rem; - border-bottom: 1px solid var(--rule); -} - -.hexdump { - font-family: var(--mono); - font-size: 0.8rem; - line-height: 1.75; -} - -.hexrow { - display: flex; - gap: 1.1rem; - align-items: baseline; - padding: 0.12rem 0; +.btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 13px 16px; + border-radius: 12px; + border: 1px solid transparent; + font-family: var(--ui); + font-size: 1rem; + font-weight: 500; + text-decoration: none; + transition: background 140ms ease, border-color 140ms ease, transform 120ms ease; } -.hexrow .offset { - color: var(--text-dim); - flex: 0 0 2.6rem; - white-space: nowrap; -} +.btn:active { transform: translateY(1px); } -.hexrow .bytes { - color: var(--bright); - flex: 0 0 12.5rem; - white-space: nowrap; -} +.btn-primary { background: var(--purple); color: #fff; font-weight: 600; } +.btn-primary:hover { background: var(--purple-deep); } -.hexrow .note { - color: var(--text-dim); - min-width: 0; -} +.btn-outline { background: var(--surface); color: var(--purple-dark); border-color: var(--purple-dark); } +.btn-outline:hover { background: var(--purple-subtle); } -.hexrow.dim .bytes { - color: var(--text-dim); -} +/* hero */ -.artifact-footnote { - margin-top: 1.1rem; - padding-top: 0.9rem; - border-top: 1px solid var(--rule); - font-size: 0.88rem; - color: var(--text-dim); - max-width: 52ch; -} +.hero { padding: clamp(3.5rem, 9vw, 6.5rem) 0 clamp(2.5rem, 6vw, 4rem); } -/* Spectrum legend */ -.spectrum { - list-style: none; - margin-top: 2.4rem; - border-top: 1px solid var(--rule); -} +.hero-inner { max-width: 760px; } -.spectrum li { - display: grid; - grid-template-columns: 1.2rem 5.5rem 10rem minmax(0, 1fr); - align-items: baseline; - gap: 0.6rem; - padding: 0.85rem 0; - border-bottom: 1px solid var(--rule); -} +.hero h1 { margin-bottom: 1.25rem; } -.spectrum code { - color: var(--bright); - font-size: 0.9rem; - letter-spacing: 0.12em; -} +.hero p { font-size: 1.125rem; max-width: 58ch; margin-bottom: 2rem; } -.spectrum-what { - font-style: italic; - color: var(--text); -} +.hero-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; } -.spectrum-note { - color: var(--text-dim); - font-size: 0.95rem; -} +/* metric strip */ -/* Crate stack */ -.stack { - list-style: none; - margin-top: 2.4rem; +.metrics { display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 1.6rem 3.5rem; + grid-template-columns: repeat(4, 1fr); + gap: 1rem; + margin-top: 3.5rem; } -.stack li { - display: flex; - gap: 0.9rem; - align-items: flex-start; +.metric { + background: var(--surface); + border: 1px solid var(--border); + border-radius: 16px; + padding: 1.5rem; + box-shadow: var(--shadow-micro); } -.stack .line { - height: 100%; - min-height: 3.2rem; - margin-top: 0.35rem; - flex: 0 0 3px; +.metric b { + display: block; + font-family: var(--display); + color: var(--ink); + font-size: clamp(1.35rem, 2.2vw, 1.75rem); + font-weight: 700; + letter-spacing: -0.5px; + line-height: 1.2; + margin-bottom: 0.35rem; } -.stack h3 { - font-weight: 400; -} +.metric span { font-size: 0.875rem; color: var(--silver); } -.stack h3 code { - color: var(--bright); - font-size: 1rem; -} +/* sections */ -.stack p { - margin-top: 0.35rem; - color: var(--text-dim); - font-size: 0.98rem; - max-width: 46ch; -} +.band { padding: clamp(3.5rem, 8vw, 6rem) 0; } -/* Numbers */ -.figures { - margin-top: 2.4rem; - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); - gap: 3rem; - align-items: start; -} +.band-soft { background: var(--surface-soft); border-block: 1px solid var(--border); } -.figures-table { - width: 100%; - border-collapse: collapse; - font-size: 0.98rem; -} +.band-head { max-width: 620px; margin-bottom: 2.75rem; } -.figures-table caption { - text-align: left; - margin-bottom: 0.8rem; +.eyebrow { + font-size: 0.875rem; + font-weight: 700; + color: var(--purple); + margin-bottom: 0.75rem; } -.figures-table th { - text-align: left; - font-weight: 400; - color: var(--text); - padding: 0.6rem 0; - border-bottom: 1px solid var(--rule); -} +.band-head h2 { margin-bottom: 0.9rem; } -.figures-table td { - text-align: right; - font-family: var(--mono); - font-size: 0.85rem; - color: var(--bright); - padding: 0.6rem 0; - border-bottom: 1px solid var(--rule); - white-space: nowrap; -} +.band-head p { font-size: 1.0625rem; } -.figures-story .story-number { - font-size: clamp(1.6rem, 3vw, 2.2rem); - color: var(--bright); - margin: 0.7rem 0 0.9rem; -} +/* cards */ -.figures-story .story-number span { - font-family: var(--mono); - font-size: 0.9em; -} +.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.25rem; } -.figures-story p:last-child { - color: var(--text-dim); - max-width: 46ch; +.card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: 16px; + padding: 1.75rem; + box-shadow: var(--shadow); } -/* Protocol terminal */ -.terminal { - margin-top: 2.4rem; - background: var(--panel); - border: 1px solid var(--panel-edge); - padding: 1.3rem 1.5rem; - font-family: var(--mono); - font-size: 0.78rem; - line-height: 1.75; -} +.card h3 { margin-bottom: 0.6rem; } -.terminal p { - color: var(--text-dim); - overflow-wrap: anywhere; - padding: 0.25rem 0 0.25rem 1.4rem; - text-indent: -1.4rem; -} +.card p { font-size: 0.9375rem; } -.terminal p:nth-child(odd) { - color: var(--text); -} +/* table */ -.prompt { - color: var(--sp-server); - margin-right: 0.6rem; +.table-shell { + background: var(--surface); + border: 1px solid var(--border); + border-radius: 16px; + overflow-x: auto; + box-shadow: var(--shadow); } -.prompt.reply { - color: var(--sp-engine); -} +table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; } -/* Milestones */ -.milestones { - list-style: none; - margin-top: 2.4rem; - border-top: 1px solid var(--rule); -} +th, td { padding: 1rem 1.25rem; text-align: right; white-space: nowrap; } -.milestones li { - display: flex; - gap: 1.4rem; - padding: 1.1rem 0; - border-bottom: 1px solid var(--rule); -} +th:first-child, td:first-child { text-align: left; } -.milestones .m { - font-family: var(--mono); - font-size: 0.8rem; - color: var(--text-dim); - flex: 0 0 2.2rem; - padding-top: 0.25rem; +thead th { + color: var(--silver); + font-weight: 500; + font-size: 0.8125rem; + border-bottom: 1px solid var(--border); } -.milestones h3 { - font-weight: 400; - color: var(--text); - font-size: 1.05rem; -} +tbody tr + tr td { border-top: 1px solid var(--border); } -.milestones p { - color: var(--text-dim); - font-size: 0.95rem; - max-width: 60ch; - margin-top: 0.2rem; -} +tbody td { color: var(--ink); font-variant-numeric: tabular-nums; } -.milestones .done .m::after { - content: " \2713"; - color: var(--sp-engine); -} +tr.us td { font-weight: 600; } +tr.us td:first-child { color: var(--purple); } -.milestones .done h3 { - color: var(--text-dim); +.win { + display: inline-block; + background: var(--green-soft); + color: var(--green-deep); + font-weight: 600; + border-radius: 6px; + padding: 2px 8px; } -.milestones .active .m { - color: var(--sp-index); -} +.note { font-size: 0.875rem; color: var(--silver); margin-top: 1rem; } -.milestones .active h3 { - color: var(--bright); -} +/* code */ -/* Footer */ -.footer { - border-top: 1px solid var(--rule); - margin-top: 2rem; +.code { + background: var(--ink); + border-radius: 12px; + padding: 1.25rem 1.4rem; + overflow-x: auto; + font-family: var(--mono); + font-size: 0.875rem; + line-height: 1.8; + color: #e7e7ee; + margin: 0; } -.footer-inner { - max-width: 72rem; - margin: 0 auto; - padding: 2.2rem var(--gutter) 3rem; - display: flex; - justify-content: space-between; - gap: 1.5rem; - flex-wrap: wrap; - color: var(--text-dim); - font-size: 0.95rem; -} +.code .c { color: #7f8296; } +.code .k { color: #b69bff; } -.footer nav { - display: flex; - gap: 1.4rem; - font-family: var(--mono); - font-size: 0.78rem; -} +/* status */ -.footer a { - color: var(--text-dim); -} +.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.75rem; } -.footer a:hover { - color: var(--bright); +.step { + display: flex; + gap: 1rem; + align-items: baseline; + padding: 1.1rem 1.35rem; + border: 1px solid var(--border); + border-radius: 12px; + background: var(--surface); +} + +.step em { + font-style: normal; + font-size: 0.75rem; + font-weight: 600; + border-radius: 6px; + padding: 3px 8px; + background: rgba(104, 107, 130, 0.12); + color: #484b5e; + white-space: nowrap; } -/* Responsive */ -@media (max-width: 60rem) { - .hero { - grid-template-columns: 1fr; - } +.step.done em { background: var(--green-soft); color: var(--green-deep); } +.step.now { border-color: var(--purple); } +.step.now em { background: var(--purple-subtle); color: var(--purple); } +.step b { color: var(--ink); font-weight: 600; } +.step p { font-size: 0.9375rem; margin-top: 0.2rem; } - .figures { - grid-template-columns: 1fr; - gap: 2rem; - } +/* closing */ - .stack { - grid-template-columns: 1fr; - } -} +.closer { text-align: center; padding: clamp(3.5rem, 8vw, 6rem) 0; } +.closer p { max-width: 52ch; margin: 1rem auto 2rem; font-size: 1.0625rem; } +.closer .hero-actions { justify-content: center; } -@media (max-width: 44rem) { - .masthead-nav a:not(.repo-link) { - display: none; - } - - .hexrow { - flex-wrap: wrap; - row-gap: 0; - } - - .hexrow .note { - flex-basis: 100%; - padding-left: 3.7rem; - font-size: 0.74rem; - } - - .spectrum li { - grid-template-columns: 1.2rem 5.5rem minmax(0, 1fr); - } - - .spectrum-note { - grid-column: 2 / -1; - } -} +/* footer */ -@media (prefers-reduced-motion: reduce) { - html { - scroll-behavior: auto; - } -} +.foot { border-top: 1px solid var(--border); padding: 2.5rem 0; font-size: 0.875rem; color: var(--silver); } -.wordmark { - display: inline-flex; - align-items: center; - gap: .5ch; -} +.foot-inner { display: flex; flex-wrap: wrap; gap: 1.25rem; align-items: center; } -.wordmark-mark { - display: block; - border-radius: 5px; -} +.foot a { color: var(--gray); text-decoration: none; } +.foot a:hover { color: var(--ink); } -/* Keyword highlight: one word per viewport, marked up like a syntax hit. */ -.key { - background: var(--sp-index); - color: var(--field); - border-radius: 4px; - padding: 0 0.3em; - box-decoration-break: clone; - -webkit-box-decoration-break: clone; -} +.foot-links { display: flex; gap: 1.5rem; margin-left: auto; flex-wrap: wrap; } -.hero h1 .key { - font-weight: inherit; -} +::selection { background: var(--purple-subtle); color: var(--ink); } -/* The divider above the footer, drawn rather than ruled. */ -.squiggle { - display: block; - width: 100%; - height: 14px; - margin: 0 0 2.5rem; - color: var(--sp-index); -} +:focus-visible { outline: 2px solid var(--purple); outline-offset: 3px; border-radius: 4px; } -.squiggle path { - stroke: currentColor; - stroke-width: 3; - fill: none; - stroke-linecap: round; +@media (max-width: 900px) { + .metrics { grid-template-columns: repeat(2, 1fr); } } -@media (prefers-reduced-motion: no-preference) { - .button { - transition: background 120ms ease, border-color 120ms ease; - } +@media (max-width: 768px) { + .nav-links { display: none; } + th, td { padding: 0.85rem 0.9rem; } } From 3e5e8561ce5afb25f71f87c1dae17a2e6326a771 Mon Sep 17 00:00:00 2001 From: martian56 Date: Sat, 25 Jul 2026 13:41:31 +0400 Subject: [PATCH 3/3] Move the canvas back to dark Kraken's system is built for a consumer exchange on white. The colour roles, purple brand, twelve pixel buttons, quiet shadows and type scale carry over, but developer infrastructure is read on dark and that is where this project started. --- web/index.html | 2 +- web/style.css | 68 ++++++++++++++++++++++++++------------------------ 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/web/index.html b/web/index.html index fcff0d5..ec6ee48 100644 --- a/web/index.html +++ b/web/index.html @@ -9,7 +9,7 @@ - + diff --git a/web/style.css b/web/style.css index a3831c0..e448e7c 100644 --- a/web/style.css +++ b/web/style.css @@ -1,28 +1,31 @@ -/* QuantaDB — white canvas, purple brand, quiet depth. */ +/* QuantaDB — near-black violet canvas, purple brand, quiet depth. */ :root { - --purple: #7132f5; - --purple-dark: #5741d8; - --purple-deep: #5b1ecf; + --purple: #855bfb; + --purple-dark: #7132f5; + --purple-deep: #7132f5; --purple-subtle: rgba(133, 91, 251, 0.16); - --ink: #101114; - --gray: #686b82; - --silver: #9497a9; - --border: #dedee5; - --surface: #ffffff; - --surface-soft: #fafafc; + --ink: #f4f3f9; + --gray: #a09eb4; + --silver: #74718c; + --border: #262336; + --border-soft: #1c1a29; + --surface: #100e18; + --surface-raise: #17141f; + --surface-soft: #14121d; + --code-bg: #0a0812; - --green: #149e61; - --green-deep: #026b3f; - --green-soft: rgba(20, 158, 97, 0.16); + --green: #34d399; + --green-deep: #6ee7b7; + --green-soft: rgba(52, 211, 153, 0.14); --display: "IBM Plex Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; --ui: "Helvetica Neue", Helvetica, Arial, sans-serif; --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace; - --shadow: rgba(0, 0, 0, 0.03) 0 4px 24px; - --shadow-micro: rgba(16, 24, 40, 0.04) 0 1px 4px; + --shadow: rgba(0, 0, 0, 0.35) 0 4px 24px; + --shadow-micro: rgba(0, 0, 0, 0.25) 0 1px 4px; --wide: 1120px; --gutter: clamp(1.25rem, 5vw, 2.5rem); @@ -69,9 +72,9 @@ p { margin: 0; } position: sticky; top: 0; z-index: 20; - background: rgba(255, 255, 255, 0.9); + background: rgba(16, 14, 24, 0.82); backdrop-filter: blur(12px); - border-bottom: 1px solid var(--border); + border-bottom: 1px solid var(--border-soft); } .nav-inner { display: flex; align-items: center; gap: 2rem; height: 68px; } @@ -114,11 +117,11 @@ p { margin: 0; } .btn:active { transform: translateY(1px); } -.btn-primary { background: var(--purple); color: #fff; font-weight: 600; } -.btn-primary:hover { background: var(--purple-deep); } +.btn-primary { background: var(--purple); color: #14071f; font-weight: 600; } +.btn-primary:hover { background: #9a79fc; } -.btn-outline { background: var(--surface); color: var(--purple-dark); border-color: var(--purple-dark); } -.btn-outline:hover { background: var(--purple-subtle); } +.btn-outline { background: transparent; color: var(--ink); border-color: var(--border); } +.btn-outline:hover { background: var(--surface-raise); border-color: var(--silver); } /* hero */ @@ -142,7 +145,7 @@ p { margin: 0; } } .metric { - background: var(--surface); + background: var(--surface-raise); border: 1px solid var(--border); border-radius: 16px; padding: 1.5rem; @@ -166,7 +169,7 @@ p { margin: 0; } .band { padding: clamp(3.5rem, 8vw, 6rem) 0; } -.band-soft { background: var(--surface-soft); border-block: 1px solid var(--border); } +.band-soft { background: var(--surface-soft); border-block: 1px solid var(--border-soft); } .band-head { max-width: 620px; margin-bottom: 2.75rem; } @@ -186,7 +189,7 @@ p { margin: 0; } .cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.25rem; } .card { - background: var(--surface); + background: var(--surface-raise); border: 1px solid var(--border); border-radius: 16px; padding: 1.75rem; @@ -200,7 +203,7 @@ p { margin: 0; } /* table */ .table-shell { - background: var(--surface); + background: var(--surface-raise); border: 1px solid var(--border); border-radius: 16px; overflow-x: auto; @@ -217,7 +220,7 @@ thead th { color: var(--silver); font-weight: 500; font-size: 0.8125rem; - border-bottom: 1px solid var(--border); + border-bottom: 1px solid var(--border-soft); } tbody tr + tr td { border-top: 1px solid var(--border); } @@ -241,7 +244,8 @@ tr.us td:first-child { color: var(--purple); } /* code */ .code { - background: var(--ink); + background: var(--code-bg); + border: 1px solid var(--border); border-radius: 12px; padding: 1.25rem 1.4rem; overflow-x: auto; @@ -266,7 +270,7 @@ tr.us td:first-child { color: var(--purple); } padding: 1.1rem 1.35rem; border: 1px solid var(--border); border-radius: 12px; - background: var(--surface); + background: var(--surface-raise); } .step em { @@ -275,8 +279,8 @@ tr.us td:first-child { color: var(--purple); } font-weight: 600; border-radius: 6px; padding: 3px 8px; - background: rgba(104, 107, 130, 0.12); - color: #484b5e; + background: rgba(160, 158, 180, 0.12); + color: var(--gray); white-space: nowrap; } @@ -294,7 +298,7 @@ tr.us td:first-child { color: var(--purple); } /* footer */ -.foot { border-top: 1px solid var(--border); padding: 2.5rem 0; font-size: 0.875rem; color: var(--silver); } +.foot { border-top: 1px solid var(--border-soft); padding: 2.5rem 0; font-size: 0.875rem; color: var(--silver); } .foot-inner { display: flex; flex-wrap: wrap; gap: 1.25rem; align-items: center; } @@ -303,7 +307,7 @@ tr.us td:first-child { color: var(--purple); } .foot-links { display: flex; gap: 1.5rem; margin-left: auto; flex-wrap: wrap; } -::selection { background: var(--purple-subtle); color: var(--ink); } +::selection { background: var(--purple); color: #14071f; } :focus-visible { outline: 2px solid var(--purple); outline-offset: 3px; border-radius: 4px; }