diff --git a/website/assets/css/main.css b/website/assets/css/main.css index 31e38f50ed..15c926ac5f 100644 --- a/website/assets/css/main.css +++ b/website/assets/css/main.css @@ -1,870 +1,639 @@ -/* Tau site styles — shared by landing pages and docs. */ +/* Tau site styles — shared by landing pages and docs. + Design: a typeset mathematics paper. White page, black ink, hairline + rules, numbered sections (§), theorem-style labels, equation numbers, + and a closing ∎. No color beyond grey. */ -@import url("https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,300;0,400;0,500;0,600;0,800;1,400&family=Space+Grotesk:wght@400;500;600&family=JetBrains+Mono:wght@400;500&family=Caveat:wght@500;600&display=swap"); +@import url("https://cdn.jsdelivr.net/gh/aaaakshat/cm-web-fonts@latest/fonts.css"); +@import url("https://fonts.googleapis.com/css2?family=STIX+Two+Text:ital,wght@0,400;0,500;0,600;0,700;1,400;1,600&family=JetBrains+Mono:wght@400;500&family=Caveat:wght@500;600&display=swap"); html, body{ margin:0; padding:0; } :root{ - --ground:#FFFFFF; - --grid:#DCE4F2; - --grid-strong:#C9D6EE; - --ink:#13213C; - --ink-soft:#54607A; - --accent:#1B3FA0; - --red:#D6435B; - --green:#1F8A5F; - --paper-edge:#EEF2FA; - /* solid reading surface for long-form text containers (issue #423) */ - --paper:#FFFFFF; - - --serif:"Spectral", Georgia, serif; - --grotesk:"Space Grotesk", ui-sans-serif, system-ui, sans-serif; - --mono:"JetBrains Mono", ui-monospace, monospace; - --math:"STIX Two Text","Cambria Math","Times New Roman",serif; - --hand:"Caveat", "Segoe Print", cursive; - - --cell:28px; - --maxw:1080px; -} - -body, body *{box-sizing:border-box;} + --ground:#FDFCF8; + --paper:#FDFCF8; + --paper-edge:#F4F1E8; + --pen:#C2402A; + --grid:#EBEBEB; + --grid-strong:#D4D4D4; + --ink:#111111; + --ink-soft:#5E5E5E; + --ink-faint:#9A9A9A; + --accent:#111111; + --red:#111111; + --green:#111111; + + --serif:"Computer Modern Serif","STIX Two Text","Cambria Math",Georgia,serif; + --math:"STIX Two Text","Computer Modern Serif","Cambria Math",serif; + --grotesk:var(--serif); + --hand:var(--serif); + --mono:"JetBrains Mono",ui-monospace,monospace; + + --maxw:1040px; + --rule:1px solid var(--ink); + --hair:1px solid var(--grid-strong); +} + +body, body *{ box-sizing:border-box; } body{ margin:0; background:var(--ground); color:var(--ink); font-family:var(--serif); - font-weight:400; font-size:18px; line-height:1.6; -webkit-font-smoothing:antialiased; - /* notebook grid */ - background-image: - linear-gradient(var(--grid) 1px, transparent 1px), - linear-gradient(90deg, var(--grid) 1px, transparent 1px); - background-size:var(--cell) var(--cell), var(--cell) var(--cell); - position:relative; + text-rendering:optimizeLegibility; + font-kerning:normal; min-height:100vh; } -/* faint top-fade so the grid feels like paper, not a screen */ -body::before{ - content:""; - position:fixed; inset:0; - background:radial-gradient(120% 80% at 50% -10%, rgba(255,255,255,.85), rgba(255,255,255,0) 60%); - pointer-events:none; z-index:0; -} -/* red margin line of a notebook */ -body::after{ - content:""; - position:fixed; top:0; bottom:0; - left:calc(var(--cell) * 3 + 1px); - width:1.5px; - background:var(--red); - opacity:.45; - pointer-events:none; z-index:1; -} -@media (max-width:720px){ - body::after{ left:calc(var(--cell) * 1.5); } -} - -.wrap{ - position:relative; z-index:2; - max-width:var(--maxw); - margin:0 auto; - padding:0 32px; -} -@media (max-width:720px){ .wrap{ padding:0 22px; } } - -a{color:inherit; text-decoration:none;} - -/* ---- eyebrow / labels ---- */ -.eyebrow{ - font-family:var(--grotesk); - font-weight:500; - font-size:12.5px; - letter-spacing:.22em; - text-transform:uppercase; +::selection{ background:#111; color:#fff; } + +.wrap{ max-width:var(--maxw); margin:0 auto; padding:0 40px; } +@media (max-width:720px){ .wrap{ padding:0 16px; } } + +a{ color:inherit; text-decoration:none; } +p a, .lede a, h2 a{ text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:3px; } + +.tau{ font-family:var(--math); font-style:italic; } + +/* ---- small-caps labels ---- */ +.eyebrow, .sidebar-group-label, .figure .figlabel, .strip .cap, +.meta-cap, .eq-title, .eq-col .lbl, .family small, .flow-node small, +.turn-head > span, .release-section h4, .docs-prevnext .dir, .docs-content th{ + font-family:var(--serif) !important; + font-variant:small-caps; + text-transform:lowercase; + letter-spacing:.06em; + font-weight:400; color:var(--ink-soft); } -.tau{ font-family:var(--math); font-style:italic; } -/* ---- nav ---- */ +/* "Definition." style run-in label above headings */ +.eyebrow-hand{ + display:block; margin:0 0 6px; + font-family:var(--serif); font-weight:700; font-size:17px; + color:var(--ink); letter-spacing:0; +} +.eyebrow-hand::first-letter{ text-transform:uppercase; } +.eyebrow-hand::after{ content:"."; } +.hero .eyebrow-hand{ font-weight:400; font-style:italic; color:var(--ink-soft); } +.hero .eyebrow-hand::after{ content:""; } + +/* ---- nav: a running head ---- */ .site-nav{ position:relative; z-index:3; - display:flex; align-items:baseline; justify-content:space-between; - padding:26px 32px 0; - max-width:var(--maxw); - margin:0 auto; -} -@media (max-width:720px){ .site-nav{ padding:22px 22px 0; } } -.brand-group{ display:flex; align-items:baseline; gap:10px; } -.brand{ display:flex; align-items:baseline; gap:12px; } -.brand .glyph{ - font-family:var(--math); font-style:italic; - font-size:30px; line-height:1; color:var(--accent); -} -.brand .name{ - font-family:var(--grotesk); font-weight:500; - letter-spacing:.04em; font-size:18px; -} -.brand .ver{ - font-family:var(--mono); font-size:12px; color:var(--ink-soft); - border:1px solid var(--grid-strong); border-radius:2px; - padding:1px 6px; transform:translateY(-2px); -} -.brand-by{ - display:inline-flex; align-items:baseline; gap:5px; - padding-left:10px; margin-left:2px; - border-left:1px solid var(--grid-strong); - color:var(--ink-soft); opacity:.85; -} -.brand-by .by-text{ - font-family:var(--grotesk); font-size:12px; font-style:italic; - color:var(--ink-soft); transform:translateY(1px); -} -.brand-by .hf-logo{ display:inline-block; transform:translateY(3px); } -@media (max-width:480px){ - .brand-by .by-text{ display:none; } - .brand-by{ padding-left:8px; } -} -.navlinks{ display:flex; gap:24px; font-family:var(--grotesk); font-size:14.5px; align-items:center; } -.navlinks a{ color:var(--ink-soft); transition:color .2s; } -.navlinks a:hover{ color:var(--accent); } - + display:flex; align-items:baseline; justify-content:space-between; gap:24px; + max-width:var(--maxw); margin:0 auto; + padding:28px 40px 14px; + border-bottom:var(--hair); +} +@media (max-width:720px){ .site-nav{ padding:20px 16px 12px; } } +.brand-group{ display:flex; align-items:baseline; gap:12px; } +.brand{ display:flex; align-items:baseline; gap:10px; } +.brand .glyph{ font-family:var(--math); font-style:italic; font-size:28px; line-height:1; } +.brand .name{ font-variant:small-caps; letter-spacing:.08em; font-size:19px; } +.brand .ver{ font-family:var(--mono); font-size:11.5px; color:var(--ink-soft); } +.brand-by{ display:inline-flex; align-items:baseline; gap:6px; color:var(--ink-soft); } +.brand-by .by-text{ font-style:italic; font-size:14px; } +.brand-by .hf-logo{ display:inline-block; transform:translateY(3px); filter:grayscale(1); } +@media (max-width:480px){ .brand-by .by-text{ display:none; } } + +.navlinks{ display:flex; gap:22px; align-items:center; font-size:16px; } +.navlinks a{ color:var(--ink-soft); transition:color .15s; } +.navlinks a:hover{ color:var(--ink); } .hf-logo{ display:block; } -.gh-with-stars{ display:inline-flex; align-items:center; gap:7px; color:var(--ink-soft); transition:color .2s; } -.gh-with-stars:hover{ color:var(--accent); } +.gh-with-stars{ display:inline-flex; align-items:center; gap:7px; color:var(--ink-soft); } +.gh-with-stars:hover{ color:var(--ink); } .gh-with-stars .gh-icon{ display:block; } -.gh-stars{ - display:inline-flex; align-items:center; gap:4px; - font-family:var(--mono); font-size:12.5px; color:var(--ink-soft); - border:1px solid var(--grid-strong); border-radius:12px; - padding:2px 8px 2px 6px; transition:color .2s, border-color .2s; -} -.gh-with-stars:hover .gh-stars{ color:var(--accent); border-color:var(--accent); } -.gh-stars .star-icon{ color:var(--red); } -@media (max-width:560px){ - .gh-with-stars{ padding:14px 22px; border-top:1px solid var(--grid); } -} +.gh-stars{ display:inline-flex; align-items:center; gap:4px; font-family:var(--mono); font-size:12px; color:var(--ink-soft); } +.gh-stars .star-icon{ color:var(--ink); } .search-trigger{ display:inline-flex; align-items:center; justify-content:center; - color:var(--ink-soft); - background:none; border:1px solid var(--grid-strong); border-radius:50%; - width:30px; height:30px; padding:0; cursor:pointer; - transition:color .2s, border-color .2s; + color:var(--ink-soft); background:none; border:none; + width:28px; height:28px; padding:0; cursor:pointer; } -.search-trigger:hover{ color:var(--accent); border-color:var(--accent); } +.search-trigger:hover{ color:var(--ink); } .search-trigger .search-icon{ display:block; } body.search-open{ overflow:hidden; } - .search-modal{ position:fixed; inset:0; z-index:50; - background:rgba(19,33,60,.4); + background:rgba(253,252,248,.9); display:flex; align-items:flex-start; justify-content:center; - padding:80px 20px; + padding:80px 16px; } .search-modal[hidden]{ display:none; } .search-modal-inner{ - position:relative; background:var(--ground); border-radius:10px; + position:relative; background:var(--ground); max-width:640px; width:100%; padding:28px 24px; - box-shadow:0 40px 80px -30px rgba(19,33,60,.5); - max-height:70vh; overflow-y:auto; + border:var(--rule); max-height:70vh; overflow-y:auto; } .search-close{ - position:absolute; top:14px; right:16px; background:none; border:none; - font-size:22px; line-height:1; color:var(--ink-soft); cursor:pointer; + position:absolute; top:10px; right:14px; background:none; border:none; + font-size:24px; line-height:1; color:var(--ink-soft); cursor:pointer; } -.search-close:hover{ color:var(--accent); } +.search-close:hover{ color:var(--ink); } +.search-unavailable{ margin:0; font-size:15px; color:var(--ink-soft); } +.search-unavailable code{ font-family:var(--mono); font-size:.88em; } -.nav-toggle{ - display:none; - background:none; border:none; cursor:pointer; - flex-direction:column; gap:5px; - padding:6px 2px; +.pagefind-ui{ + --pagefind-ui-primary:#111; + --pagefind-ui-text:#111; + --pagefind-ui-background:#fff; + --pagefind-ui-border:#D4D4D4; + --pagefind-ui-tag:#EBEBEB; + --pagefind-ui-border-radius:0; + --pagefind-ui-font:var(--serif); } -.nav-toggle .bar{ - width:22px; height:2px; background:var(--ink); - display:block; border-radius:1px; + +.nav-toggle{ + display:none; background:none; border:none; cursor:pointer; + flex-direction:column; gap:5px; padding:6px 2px; } -@media (max-width:560px){ +.nav-toggle .bar{ width:20px; height:1.5px; background:var(--ink); display:block; } +@media (max-width:640px){ .nav-toggle{ display:inline-flex; } .navlinks{ - display:none; - position:absolute; inset-inline:0; top:100%; - flex-direction:column; gap:0; - background:var(--ground); - border-bottom:1px solid var(--grid-strong); - box-shadow:0 16px 30px -20px rgba(19,33,60,.3); - z-index:20; - } - .navlinks a{ - padding:14px 22px; - border-top:1px solid var(--grid); - } - .navlinks .search-trigger{ - margin:14px 22px; border-radius:50%; + display:none; position:absolute; inset-inline:0; top:100%; + flex-direction:column; align-items:stretch; gap:0; + background:var(--ground); border-bottom:var(--rule); z-index:20; } + .navlinks a, .navlinks .search-trigger{ padding:12px 16px; border-top:1px solid var(--grid); width:auto; height:auto; justify-content:flex-start; } .navlinks.is-open{ display:flex; } } -.search-unavailable{ - margin:0; font-family:var(--grotesk); font-size:14px; color:var(--ink-soft); line-height:1.6; -} -.search-unavailable code{ - font-family:var(--mono); font-size:.9em; background:var(--paper-edge); - border:1px solid var(--grid-strong); border-radius:3px; padding:1px 5px; -} +/* ---- hero: title page ---- */ +header.hero{ padding:88px 0 48px; } +header.hero.hero-compact{ padding-top:64px; } +@media (max-width:720px){ header.hero, header.hero.hero-compact{ padding:48px 0 24px; } } +.hero-grid{ display:grid; grid-template-columns:1.05fr .95fr; gap:56px; align-items:center; } +@media (max-width:860px){ .hero-grid{ grid-template-columns:1fr; gap:36px; } } -/* ---- pagefind theme ---- */ -.pagefind-ui{ - --pagefind-ui-primary: var(--accent); - --pagefind-ui-text: var(--ink); - --pagefind-ui-background: var(--ground); - --pagefind-ui-border: var(--grid-strong); - --pagefind-ui-tag: var(--grid-strong); - --pagefind-ui-font: var(--grotesk); +h1, .hero-title-original, .h1-compact{ + font-family:var(--serif); font-weight:400; + font-size:clamp(40px,6.4vw,68px); line-height:1.06; + letter-spacing:-0.012em; margin:10px 0 0; } +h1 em, .hero-title-original em{ font-style:italic; color:var(--ink); } +h1 .big-tau{ font-family:var(--math); font-style:italic; } -/* ---- hero ---- */ -header.hero{ padding:74px 0 40px; } -header.hero.hero-compact{ padding-top:64px; } -@media (max-width:720px){ header.hero.hero-compact{ padding-top:40px; } } -.hero-grid{ - display:grid; - grid-template-columns:1.02fr .98fr; - gap:48px; align-items:center; -} -@media (max-width:860px){ - .hero-grid{ grid-template-columns:1fr; gap:30px; } - header.hero{ padding:48px 0 24px; } -} - -h1{ - font-family:var(--hand); - font-weight:500; - font-size:clamp(48px, 8.5vw, 92px); - line-height:1.02; - letter-spacing:-0.005em; - margin:14px 0 0; -} -h1 em{ font-style:normal; font-weight:500; color:var(--accent); } -.h1-compact{ font-size:clamp(48px,7.5vw,72px); margin-top:8px; } - -/* The homepage hero title keeps its original serif treatment, while every - other heading across the site uses the handwritten font. */ -.hero-title-original{ - font-family:var(--serif); - font-weight:300; - font-size:clamp(40px, 7vw, 76px); - line-height:1.04; - letter-spacing:-0.015em; - margin:18px 0 0; -} -.hero-title-original em{ font-style:italic; font-weight:400; color:var(--accent); } -h1 .big-tau{ - font-family:var(--math); font-style:italic; font-weight:400; - color:var(--accent); -} -.lede{ - margin:24px 0 0; max-width:30em; - color:var(--ink); font-weight:400; font-size:19px; -} -.lede strong{ font-weight:600; } -.small-lede{ margin-top:14px; color:var(--ink-soft); font-size:17px; } +.lede{ margin:26px 0 0; max-width:31em; font-size:19.5px; color:var(--ink); } +.lede strong{ font-weight:700; } +.small-lede{ margin-top:12px; font-style:italic; color:var(--ink-soft); font-size:17.5px; } -.cta-row{ display:flex; flex-wrap:wrap; gap:14px; align-items:center; margin-top:34px; } +.cta-row{ display:flex; flex-wrap:wrap; gap:14px 26px; align-items:center; margin-top:36px; } .install{ - display:inline-flex; align-items:center; gap:12px; - font-family:var(--mono); font-size:14.5px; - background:var(--ink); color:#fff; - padding:13px 18px; border-radius:4px; + display:inline-flex; align-items:center; gap:14px; max-width:100%; + font-family:var(--mono); font-size:13.5px; + border:var(--rule); padding:12px 16px; background:var(--ground); + overflow-x:auto; white-space:nowrap; } -.install .dollar{ color:var(--red); } +.install .dollar{ color:var(--ink-faint); } .install .copy{ - margin-left:6px; font-family:var(--grotesk); font-size:11px; - letter-spacing:.1em; text-transform:uppercase; - color:rgba(255,255,255,.55); cursor:pointer; transition:color .2s; - background:none; border:none; padding:0; -} -.install .copy:hover{ color:#fff; } -.ghost{ - font-family:var(--grotesk); font-size:15px; font-weight:500; - color:var(--accent); - border-bottom:1.5px solid var(--accent); - padding-bottom:2px; transition:opacity .2s; -} -.ghost:hover{ opacity:.65; } -.ghost .arr{ font-family:var(--serif); } - -.star-cta{ margin-top:18px; } -.star-cta-link{ - display:inline-flex; align-items:center; gap:8px; - font-family:var(--grotesk); font-size:14px; font-weight:500; - color:var(--ink-soft); - border:1px solid var(--grid-strong); border-radius:20px; - padding:7px 16px; transition:color .2s, border-color .2s, background .2s; -} -.star-cta-link:hover{ - color:var(--accent); border-color:var(--accent); background:rgba(201,214,238,.25); -} -.star-cta-link .gh-icon{ display:block; flex-shrink:0; } -.star-cta-link .star-icon{ color:var(--red); flex-shrink:0; } - -/* ---- canvas figure ---- */ -.figure{ - position:relative; - border:1px solid var(--grid-strong); - border-radius:6px; - background:rgba(255,255,255,.6); - backdrop-filter:blur(1px); - padding:14px; - box-shadow:0 1px 0 rgba(19,33,60,.04), 0 24px 48px -28px rgba(19,33,60,.28); -} + font-family:var(--serif); font-variant:small-caps; font-size:15px; letter-spacing:.04em; + color:var(--ink-soft); cursor:pointer; background:none; border:none; border-left:var(--hair); + padding:0 0 0 14px; +} +.install .copy:hover{ color:var(--ink); } +.ghost{ font-size:17px; font-style:italic; color:var(--ink); border-bottom:1px solid var(--ink); padding-bottom:1px; } +.ghost:hover{ border-bottom-color:transparent; } +.ghost .arr{ font-style:normal; font-family:var(--math); } + +.star-cta{ margin-top:20px; } +.star-cta-link{ display:inline-flex; align-items:center; gap:8px; font-size:15.5px; color:var(--ink-soft); } +.star-cta-link:hover{ color:var(--ink); } +.star-cta-link .gh-icon, .star-cta-link .star-icon{ display:block; flex-shrink:0; } + +/* ---- figure: captioned plot ---- */ +.figure{ position:relative; margin:0; padding:0 0 34px; border:none; } .figure canvas{ display:block; width:100%; height:auto; } -.figure.wide{ align-self:center; } -.figure .figlabel{ - position:absolute; top:14px; left:18px; - font-family:var(--grotesk); font-size:11px; letter-spacing:.18em; - text-transform:uppercase; color:var(--ink-soft); -} -.figure .figval{ - position:absolute; bottom:16px; right:18px; - font-family:var(--mono); font-size:13px; color:var(--accent); -} +.figure .figlabel{ position:absolute; bottom:4px; left:0; font-size:15px; } +.figure .figlabel::before{ content:"Fig. 1 \2014\00a0"; font-variant:normal; text-transform:none; letter-spacing:0; color:var(--ink); } +.figure .figval{ position:absolute; bottom:4px; right:0; font-family:var(--mono); font-size:12.5px; color:var(--ink-soft); } /* ---- definition strip ---- */ .strip{ - border-top:1px solid var(--grid-strong); - border-bottom:1px solid var(--grid-strong); - margin-top:30px; - display:grid; grid-template-columns:repeat(3,1fr); -} -.strip .cellitem{ - padding:24px 6px; text-align:center; - border-right:1px solid var(--grid-strong); + margin-top:48px; display:grid; grid-template-columns:repeat(3,1fr); + border-top:var(--rule); border-bottom:var(--rule); } +.strip .cellitem{ padding:20px 8px; text-align:center; border-right:var(--hair); } .strip .cellitem:last-child{ border-right:none; } -.strip .num{ - font-family:var(--math); font-style:italic; - font-size:30px; color:var(--accent); line-height:1; -} -.arch-strip .num{ - font-family:var(--mono); font-style:normal; - font-size:19px; -} -.strip .cap{ - display:block; margin-top:8px; - font-family:var(--grotesk); font-size:12px; letter-spacing:.14em; - text-transform:uppercase; color:var(--ink-soft); -} +.strip .num{ font-family:var(--math); font-style:italic; font-size:28px; line-height:1; } +.arch-strip .num{ font-family:var(--serif); } +.strip .cap{ display:block; margin-top:8px; font-size:16px; } @media (max-width:560px){ .strip{ grid-template-columns:1fr; } - .strip .cellitem{ border-right:none; border-bottom:1px solid var(--grid-strong); } + .strip .cellitem{ border-right:none; border-bottom:var(--hair); } .strip .cellitem:last-child{ border-bottom:none; } } -/* ---- section scaffolding ---- */ -section{ padding:88px 0; } -.sec-head{ display:flex; align-items:baseline; gap:18px; margin-bottom:44px; } -.sec-head .mark{ - font-family:var(--mono); font-size:13px; color:var(--red); - transform:translateY(-2px); -} -.sec-head h2{ - font-family:var(--hand); font-weight:600; font-style:normal; - font-size:clamp(32px,5vw,46px); line-height:1.0; margin:0; letter-spacing:-0.01em; +/* ---- sections ---- */ +section{ padding:80px 0; border-top:var(--hair); } +.wrap > section:first-child{ border-top:none; } +.sec-head{ display:flex; align-items:baseline; gap:20px; margin-bottom:40px; } +.sec-head .mark{ font-family:var(--serif); font-size:26px; font-weight:700; line-height:1; } +.sec-head .mark::before{ content:"\00a7"; margin-right:4px; font-weight:400; } +.sec-head h2, .two h2{ + font-family:var(--serif); font-weight:700; font-style:normal; + font-size:clamp(26px,3.6vw,34px); line-height:1.15; margin:0; letter-spacing:-0.005em; } +.two h2{ margin-bottom:16px; } +.sec-head .eyebrow-hand{ display:none; } -/* ---- handwritten eyebrow labels ---- - The small label above each section heading is set in a handwritten - font, so section intros read like a sketched marginal note rather - than a printed kicker. */ -.eyebrow-hand{ - font-family:var(--hand); - font-size:22px; - font-weight:600; - letter-spacing:.01em; - text-transform:none; - color:var(--red); - display:inline-block; - margin:0 0 2px; -} -.hero .eyebrow-hand{ color:var(--ink-soft); margin-bottom:0; } - -/* ---- layers ---- */ -.layers{ display:grid; grid-template-columns:repeat(3,1fr); gap:1px; - background:var(--grid-strong); border:1px solid var(--grid-strong); border-radius:6px; overflow:hidden; } +/* ---- layers: three lemmas ---- */ +.layers{ display:grid; grid-template-columns:repeat(3,1fr); border-top:var(--rule); border-bottom:var(--rule); } @media (max-width:760px){ .layers{ grid-template-columns:1fr; } } -.layer{ background:var(--ground); padding:30px 26px 34px; position:relative; } -.layer .pkg{ font-family:var(--mono); font-size:13.5px; color:var(--accent); } -.layer h3{ font-family:var(--hand); font-weight:600; font-size:27px; line-height:1.02; margin:12px 0 6px; } -.layer p{ margin:0; font-size:16px; color:var(--ink-soft); line-height:1.55; } -.layer .idx{ - position:absolute; top:24px; right:24px; - font-family:var(--math); font-style:italic; font-size:22px; color:var(--grid-strong); -} - -/* ---- principles ---- */ -.principles{ display:grid; grid-template-columns:repeat(2,1fr); gap:36px 56px; } +.layer{ padding:26px 24px 30px; position:relative; border-right:var(--hair); } +.layer:last-child{ border-right:none; } +@media (max-width:760px){ .layer{ border-right:none; border-bottom:var(--hair); } .layer:last-child{ border-bottom:none; } } +.layer .pkg{ font-family:var(--mono); font-size:13px; color:var(--ink-soft); } +.layer h3{ font-family:var(--serif); font-weight:700; font-size:21px; line-height:1.2; margin:12px 0 8px; } +.layer p{ margin:0; font-size:16.5px; font-style:italic; color:var(--ink); line-height:1.55; } +.layer .idx{ position:absolute; top:22px; right:22px; font-family:var(--math); font-size:20px; color:var(--ink-faint); } + +/* ---- principles: axioms ---- */ +.principles{ display:grid; grid-template-columns:repeat(2,1fr); gap:34px 56px; counter-reset:axiom; } @media (max-width:680px){ .principles{ grid-template-columns:1fr; } } -.pr{ border-top:1.5px solid var(--ink); padding-top:18px; } -.pr h3{ font-family:var(--hand); font-weight:600; font-size:26px; line-height:1.02; margin:0 0 6px; } -.pr p{ margin:0; font-size:16.5px; color:var(--ink-soft); } - -/* ---- code block (terminal figure) ---- */ -.terminal{ - border:1px solid var(--grid-strong); border-radius:8px; overflow:hidden; - background:#0E1A30; - box-shadow:0 28px 60px -34px rgba(19,33,60,.5); -} -.terminal .bar{ - display:flex; align-items:center; gap:8px; - padding:12px 16px; border-bottom:1px solid rgba(255,255,255,.07); -} -.terminal .bar span{ width:11px; height:11px; border-radius:50%; background:rgba(255,255,255,.18); } -.terminal .bar span:first-child{ background:var(--red); opacity:.8; } -.terminal .bar .t{ width:auto; height:auto; border-radius:0; background:none; - margin-left:8px; font-family:var(--mono); font-size:12px; color:rgba(255,255,255,.4); } -.terminal pre{ - margin:0; padding:24px 22px; overflow-x:auto; - font-family:var(--mono); font-size:14px; line-height:1.85; color:#D7E0F4; -} -.terminal .pmt{ color:var(--red); } -.terminal .cmd{ color:#fff; } -.terminal .out{ color:#7F8CAA; } -.terminal .key{ color:#8FB4FF; } - -.two{ display:grid; grid-template-columns:.85fr 1.15fr; gap:48px; align-items:center; } -.boundary-two{ grid-template-columns:.78fr 1.22fr; } +.pr{ counter-increment:axiom; } +.pr h3{ font-family:var(--serif); font-weight:700; font-size:18px; line-height:1.35; margin:0 0 6px; } +.pr h3::before{ content:"Axiom " counter(axiom) " "; font-variant:small-caps; } +.pr h3::after{ content:"."; } +.pr p{ margin:0; font-size:17px; font-style:italic; } + +/* ---- code figures ---- */ +.terminal{ border-top:var(--rule); border-bottom:var(--rule); background:var(--ground); } +.terminal .bar{ display:flex; align-items:center; padding:8px 0; border-bottom:var(--hair); } +.terminal .bar span{ display:none; } +.terminal .bar .t{ display:block; font-family:var(--serif); font-variant:small-caps; font-size:15px; color:var(--ink-soft); letter-spacing:.04em; } +.terminal pre{ margin:0; padding:20px 0; overflow-x:auto; font-family:var(--mono); font-size:13.5px; line-height:1.85; color:var(--ink); } +.terminal .pmt{ color:var(--ink); } +.terminal .cmd{ color:var(--ink); font-weight:500; } +.terminal .out{ color:var(--ink-faint); } +.terminal .key{ color:var(--ink); font-style:italic; } + +.two{ display:grid; grid-template-columns:.9fr 1.1fr; gap:56px; align-items:center; } +.boundary-two{ grid-template-columns:.8fr 1.2fr; } @media (max-width:820px){ .two, .boundary-two{ grid-template-columns:1fr; gap:28px; } } -.two p{ color:var(--ink-soft); } -.two h2{ font-family:var(--hand); font-weight:600; font-style:normal; - font-size:clamp(32px,5vw,44px); line-height:1.0; margin:0 0 14px; } - -/* ---- event flow and capabilities ---- */ -.event-flow{ - border:1px solid var(--grid-strong); border-radius:8px; - background:rgba(255,255,255,.72); padding:22px; - box-shadow:0 20px 50px -34px rgba(19,33,60,.4); -} -.flow-node{ - border:1px solid var(--grid-strong); border-radius:6px; - background:var(--ground); padding:15px 18px; -} -.flow-node span{ display:block; font-family:var(--mono); font-size:14px; color:var(--accent); } -.flow-node small{ display:block; margin-top:5px; font-family:var(--grotesk); font-size:12px; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-soft); } -.flow-arrow{ text-align:center; color:var(--red); font-family:var(--math); font-size:24px; line-height:1.35; } +.two p{ color:var(--ink); } + +/* ---- event flow: commutative-diagram feel ---- */ +.event-flow{ padding:4px 0; } +.flow-node{ border:var(--rule); padding:12px 16px; text-align:center; background:var(--ground); } +.flow-node span{ display:block; font-family:var(--math); font-style:italic; font-size:18px; } +.flow-node small{ display:block; margin-top:2px; font-size:14.5px; } +.flow-arrow{ text-align:center; font-family:var(--math); font-size:22px; line-height:1.5; color:var(--ink); } .flow-split{ display:grid; grid-template-columns:1fr 1fr; gap:14px; } @media (max-width:560px){ .flow-split{ grid-template-columns:1fr; } } -.capabilities{ display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--grid-strong); border:1px solid var(--grid-strong); border-radius:6px; overflow:hidden; } -.capabilities div{ background:rgba(255,255,255,.82); padding:20px 18px; font-family:var(--grotesk); font-size:15px; line-height:1.45; color:var(--ink); } -.capabilities code, .pr code{ font-family:var(--mono); font-size:.9em; color:var(--accent); background:rgba(201,214,238,.35); padding:1px 4px; border-radius:3px; } +/* ---- capabilities: enumerated list ---- */ +.capabilities{ + display:grid; grid-template-columns:repeat(3,1fr); gap:0 40px; + counter-reset:cap; border-top:var(--rule); border-bottom:var(--rule); padding:10px 0; +} +.capabilities div{ counter-increment:cap; padding:12px 0 12px 2.2em; position:relative; font-size:16.5px; line-height:1.45; } +.capabilities div::before{ content:"(" counter(cap, lower-roman) ")"; position:absolute; left:0; color:var(--ink-soft); font-style:italic; } +.capabilities code, .pr code{ font-family:var(--mono); font-size:.86em; } @media (max-width:820px){ .capabilities{ grid-template-columns:1fr; } } -/* ---- closing ---- */ -.closing{ text-align:center; padding:110px 0 90px; } -.closing .turn{ - font-family:var(--math); font-style:italic; - font-size:clamp(64px,16vw,150px); color:var(--accent); line-height:.9; - display:block; -} -.closing p{ max-width:24em; margin:22px auto 0; color:var(--ink-soft); } +/* ---- closing: Q.E.D. ---- */ +.closing{ text-align:center; padding:110px 0 100px; } +.closing .turn{ font-family:var(--math); font-style:italic; font-size:clamp(72px,14vw,132px); line-height:.9; display:block; } +.closing p{ max-width:26em; margin:26px auto 0; font-style:italic; } +.closing p::after{ content:"\00a0\220E"; font-style:normal; } .closing .cta-row{ justify-content:center; } +/* ---- footer ---- */ .site-footer{ - border-top:1px solid var(--grid-strong); - padding:34px 0 60px; - display:flex; justify-content:space-between; align-items:center; - font-family:var(--grotesk); font-size:13.5px; color:var(--ink-soft); - flex-wrap:wrap; gap:14px; - max-width:var(--maxw); margin:0 auto; position:relative; z-index:2; -} -@media (max-width:720px){ .site-footer{ padding:34px 22px 60px; } } -.site-footer a:hover{ color:var(--accent); } -.site-footer .l{ display:flex; gap:24px; flex-wrap:wrap; align-items:center; } + max-width:var(--maxw); margin:0 auto; padding:28px 40px 56px; + border-top:var(--rule); + display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:14px; + font-size:15px; color:var(--ink-soft); +} +@media (max-width:720px){ .site-footer{ padding:28px 16px 48px; } } +.site-footer a:hover{ color:var(--ink); } +.site-footer .l{ display:flex; gap:20px; flex-wrap:wrap; align-items:center; } .footer-hf{ display:inline-flex; align-items:center; gap:6px; } -.footer-hf .hf-logo{ display:block; opacity:.85; } -.footer-hf:hover .hf-logo{ opacity:1; } - -:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:2px; } - -/* ---- "Why Tau?" : angle turns table ---- */ -.turns{ - border:1px solid var(--grid-strong); border-radius:6px; overflow:hidden; - background:var(--grid-strong); - display:grid; gap:1px; -} -.turn-row{ - display:grid; grid-template-columns:1.4fr 1fr 1fr; align-items:center; - background:var(--ground); -} -.turn-row > span{ padding:14px 20px; } -.turn-row > span:first-child{ - font-family:var(--grotesk); font-size:14px; color:var(--ink); - letter-spacing:.04em; -} -.turn-row .pi{ color:var(--ink-soft); border-left:1px solid var(--grid); font-family:var(--math); font-size:19px; } -.turn-row .ta{ color:var(--accent); border-left:1px solid var(--grid); font-family:var(--math); font-size:19px; background:rgba(27,63,160,.05); } -.turn-head{ background:#F4F7FD; } -.turn-head > span{ - font-family:var(--grotesk) !important; font-size:11px !important; - letter-spacing:.16em; text-transform:uppercase; color:var(--ink-soft) !important; - padding-top:12px; padding-bottom:12px; -} -.turn-head .ta{ color:var(--accent) !important; background:rgba(27,63,160,.05); } -.turns-note{ margin:20px 0 0; color:var(--ink-soft); font-size:16.5px; max-width:46em; } - -/* ---- "Why Tau?" : equation comparison cards ---- */ -.eq-list{ - display:grid; gap:1px; background:var(--grid-strong); - border:1px solid var(--grid-strong); border-radius:6px; overflow:hidden; -} -.eq{ background:var(--ground); padding:30px 30px 32px; } -.eq-title{ - display:block; font-family:var(--grotesk); font-size:12px; - letter-spacing:.14em; text-transform:uppercase; color:var(--ink-soft); -} -.eq-cols{ - display:grid; grid-template-columns:1fr 1fr; gap:1px; - margin-top:18px; background:var(--grid-strong); - border:1px solid var(--grid-strong); border-radius:6px; overflow:hidden; -} +.footer-hf .hf-logo{ filter:grayscale(1); } + +:focus-visible{ outline:1.5px solid var(--ink); outline-offset:3px; } + +/* ---- "Why Tau?" : turns table ---- */ +.turns{ border-top:var(--rule); border-bottom:var(--rule); display:grid; } +.turn-row{ display:grid; grid-template-columns:1.4fr 1fr 1fr; align-items:center; border-top:var(--hair); } +.turn-row:first-child{ border-top:none; } +.turn-row > span{ padding:12px 16px; } +.turn-row > span:first-child{ padding-left:0; font-size:16.5px; } +.turn-row .pi{ color:var(--ink-soft); font-family:var(--math); font-size:19px; } +.turn-row .ta{ font-family:var(--math); font-size:19px; font-weight:600; } +.turn-head{ border-bottom:var(--rule); } +.turn-head > span{ font-size:15px !important; padding-top:10px; padding-bottom:10px; } +.turns-note{ margin:18px 0 0; color:var(--ink-soft); font-size:16.5px; max-width:46em; font-style:italic; } + +/* ---- "Why Tau?" : numbered equations ---- */ +.eq-list{ display:grid; counter-reset:eqn; } +.eq{ counter-increment:eqn; padding:30px 0; border-top:var(--hair); position:relative; } +.eq:first-child{ border-top:none; } +.eq::after{ content:"(" counter(eqn) ")"; position:absolute; top:30px; right:0; font-family:var(--serif); color:var(--ink-soft); } +.eq-title{ display:block; font-size:17px; } +.eq-cols{ display:grid; grid-template-columns:1fr 1fr; margin-top:16px; border-top:var(--rule); border-bottom:var(--rule); } @media (max-width:620px){ .eq-cols{ grid-template-columns:1fr; } } -.eq-col{ - background:var(--ground); padding:22px 24px; - display:flex; flex-direction:column; gap:12px; align-items:flex-start; -} -.eq-col.tau-col{ background:rgba(27,63,160,.05); } -.eq-col .lbl{ - font-family:var(--grotesk); font-size:11px; letter-spacing:.14em; - text-transform:uppercase; color:var(--ink-soft); -} -.eq-col.tau-col .lbl{ color:var(--accent); } -.eq-col .form{ font-size:19px; color:var(--ink); } -.eq-col.tau-col .form{ color:var(--accent); } -.eq-note{ margin:18px 0 0; color:var(--ink-soft); font-size:16px; } - -.family{ - display:grid; grid-template-columns:repeat(4,1fr); gap:1px; - margin-top:18px; background:var(--grid-strong); - border:1px solid var(--grid-strong); border-radius:6px; overflow:hidden; -} +.eq-col{ padding:20px 22px; display:flex; flex-direction:column; gap:10px; align-items:flex-start; } +.eq-col + .eq-col{ border-left:var(--hair); } +@media (max-width:620px){ .eq-col + .eq-col{ border-left:none; border-top:var(--hair); } } +.eq-col .form{ font-size:19px; } +.eq-col.tau-col .lbl{ color:var(--ink); } +.eq-note{ margin:16px 0 0; color:var(--ink-soft); font-size:16px; font-style:italic; } + +.family{ display:grid; grid-template-columns:repeat(4,1fr); margin-top:16px; border-top:var(--rule); border-bottom:var(--rule); } @media (max-width:620px){ .family{ grid-template-columns:repeat(2,1fr); } } -.family > div{ - background:var(--ground); padding:18px 14px; text-align:center; -} -.family .fam-tau{ background:rgba(27,63,160,.05); } -.family .form{ display:block; font-size:18px; color:var(--ink); } -.family .fam-tau .form{ color:var(--accent); } -.family small{ - display:block; margin-top:8px; font-family:var(--grotesk); - font-size:11px; letter-spacing:.08em; text-transform:uppercase; color:var(--ink-soft); -} +.family > div{ padding:16px 12px; text-align:center; } +.family .form{ display:block; font-size:18px; } +.family .fam-tau .form{ font-weight:600; } +.family small{ display:block; margin-top:6px; font-size:14px; } @media (prefers-reduced-motion:reduce){ *{ scroll-behavior:auto; } } /* ============================================================ - Docs: sidebar + content typography + admonitions + Docs: a numbered paper ============================================================ */ -.docs-layout{ - display:grid; - grid-template-columns:240px minmax(0,1fr); - gap:56px; - padding:48px 0 100px; -} -@media (max-width:860px){ - .docs-layout{ grid-template-columns:1fr; gap:28px; padding:32px 0 70px; } -} +.docs-layout{ display:grid; grid-template-columns:220px minmax(0,1fr); gap:64px; padding:56px 40px 100px; } +@media (max-width:860px){ .docs-layout{ grid-template-columns:1fr; gap:28px; padding:32px 16px 70px; } } -.docs-sidebar{ - position:sticky; top:28px; - font-family:var(--grotesk); - font-size:14px; - max-height:calc(100vh - 56px); - overflow-y:auto; -} -@media (max-width:860px){ - .docs-sidebar{ position:static; max-height:none; } -} +.docs-sidebar{ position:sticky; top:28px; font-size:15.5px; max-height:calc(100vh - 56px); overflow-y:auto; } +@media (max-width:860px){ .docs-sidebar{ position:static; max-height:none; } } .sidebar-group{ margin-bottom:22px; } -.sidebar-group-label{ - margin:0 0 8px; - font-size:11.5px; letter-spacing:.14em; text-transform:uppercase; - color:var(--ink-soft); -} +.sidebar-group-label{ margin:0 0 6px; font-size:15px; color:var(--ink) !important; } .docs-sidebar ul{ list-style:none; margin:0; padding:0; } -.docs-sidebar li{ margin:0; } -.docs-sidebar a{ - display:block; padding:6px 0; color:var(--ink-soft); - border-left:2px solid transparent; padding-left:12px; - margin-left:-13px; - transition:color .15s, border-color .15s; -} -.docs-sidebar a:hover{ color:var(--ink); } -.docs-sidebar a.active{ color:var(--accent); border-left-color:var(--accent); font-weight:500; } -.sidebar-toplink{ - display:block; padding:6px 0 6px 12px; margin:0 0 14px -13px; - border-left:2px solid transparent; - font-weight:500; color:var(--ink-soft); -} -.sidebar-toplink:hover{ color:var(--ink); } -.sidebar-toplink.active{ color:var(--accent); border-left-color:var(--accent); } - -/* Long-form doc pages read on a solid "sheet of paper" card, so body text - never sits directly on the notebook grid. */ -.docs-content{ - min-width:0; font-family:var(--serif); font-size:17px; line-height:1.7; - background:var(--paper); - border:1px solid var(--grid-strong); border-radius:6px; - padding:40px 48px 48px; - box-shadow:0 24px 48px -32px rgba(19,33,60,.28); -} -@media (max-width:860px){ - .docs-content{ padding:28px 24px 32px; } -} -.docs-content h1{ - font-size:clamp(30px,5vw,42px); font-weight:400; margin:0 0 8px; letter-spacing:-0.01em; -} -.docs-description{ color:var(--ink-soft); font-size:17px; margin:0 0 40px; } +.docs-sidebar a, .sidebar-toplink{ display:block; padding:3px 0; color:var(--ink-soft); } +.sidebar-toplink{ margin:0 0 14px; } +.docs-sidebar a:hover, .sidebar-toplink:hover{ color:var(--ink); } +.docs-sidebar a.active, .sidebar-toplink.active{ color:var(--ink); font-style:italic; } +.docs-sidebar a.active::before, .sidebar-toplink.active::before{ content:"\2192\00a0"; font-style:normal; } + +.docs-content{ min-width:0; max-width:44em; font-size:18px; line-height:1.7; counter-reset:h2; } +.docs-content h1{ font-size:clamp(32px,5vw,44px); font-weight:400; margin:0 0 10px; } +.docs-description{ color:var(--ink-soft); font-style:italic; font-size:18px; margin:0 0 40px; padding-bottom:28px; border-bottom:var(--hair); } .docs-content h2{ - font-family:var(--serif); font-weight:400; font-style:italic; - font-size:28px; margin:48px 0 16px; letter-spacing:-0.01em; - border-top:1px solid var(--grid-strong); padding-top:32px; -} -.docs-content h2:first-child{ border-top:none; padding-top:0; margin-top:0; } -.docs-content h3{ font-family:var(--grotesk); font-weight:600; font-size:19px; margin:32px 0 12px; } -.docs-content p{ margin:0 0 18px; color:var(--ink); } -.docs-content ul, .docs-content ol{ margin:0 0 18px; padding-left:1.4em; color:var(--ink); } -.docs-content li{ margin:0 0 8px; } -.docs-content a{ color:var(--accent); border-bottom:1px solid var(--grid-strong); } -.docs-content a:hover{ border-color:var(--accent); } -.docs-content strong{ font-weight:600; } -.docs-content code{ - font-family:var(--mono); font-size:.85em; background:var(--paper-edge); - border:1px solid var(--grid-strong); border-radius:3px; padding:1px 5px; -} + counter-increment:h2; counter-reset:h3; + font-family:var(--serif); font-weight:700; font-size:25px; margin:48px 0 14px; +} +.docs-content h3{ counter-increment:h3; font-family:var(--serif); font-weight:700; font-size:19.5px; margin:32px 0 10px; } +.docs-content p{ margin:0 0 18px; } +.docs-content ul, .docs-content ol{ margin:0 0 18px; padding-left:1.5em; } +.docs-content li{ margin:0 0 6px; } +.docs-content a{ text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:3px; text-decoration-color:var(--ink-faint); } +.docs-content a:hover{ text-decoration-color:var(--ink); } +.docs-content strong{ font-weight:700; } +.docs-content code{ font-family:var(--mono); font-size:.82em; } .docs-content pre{ - background:#0E1A30; color:#D7E0F4; border-radius:8px; - padding:20px 22px; overflow-x:auto; margin:0 0 22px; - box-shadow:0 20px 44px -30px rgba(19,33,60,.5); -} -.docs-content pre code{ - background:none; border:none; padding:0; font-size:14px; line-height:1.7; color:inherit; -} -.docs-content blockquote{ - margin:0 0 18px; padding:2px 20px; border-left:2px solid var(--grid-strong); color:var(--ink-soft); -} -.docs-content table{ width:100%; border-collapse:collapse; margin:0 0 22px; font-size:15.5px; } -.docs-content th, .docs-content td{ - text-align:left; padding:10px 14px; border-bottom:1px solid var(--grid-strong); -} -.docs-content th{ font-family:var(--grotesk); font-size:12.5px; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-soft); } -.docs-content hr{ border:none; border-top:1px solid var(--grid-strong); margin:36px 0; } - -.docs-footer{ - display:flex; justify-content:space-between; align-items:center; gap:16px; flex-wrap:wrap; - margin-top:56px; padding-top:24px; border-top:1px solid var(--grid-strong); - font-family:var(--grotesk); font-size:13.5px; -} + background:var(--paper-edge); color:var(--ink); + border-left:2px solid var(--ink); + padding:18px 20px; overflow-x:auto; margin:0 0 22px; +} +.docs-content pre.astro-code{ background:var(--paper-edge) !important; } +.docs-content pre code{ font-size:13.5px; line-height:1.7; color:inherit; } +.docs-content blockquote{ margin:0 0 18px; padding:0 0 0 24px; font-style:italic; color:var(--ink-soft); } +.docs-content table{ width:100%; border-collapse:collapse; margin:0 0 22px; font-size:16px; border-top:var(--rule); border-bottom:var(--rule); } +.docs-content th, .docs-content td{ text-align:left; padding:8px 12px 8px 0; border-bottom:var(--hair); } +.docs-content th{ font-size:16px; color:var(--ink) !important; border-bottom:var(--rule); } +.docs-content hr{ border:none; text-align:center; margin:36px 0; } +.docs-content hr::after{ content:"\2217\2003\2217\2003\2217"; color:var(--ink-soft); } + +.docs-footer{ margin-top:56px; padding-top:20px; border-top:var(--hair); font-size:15px; } .docs-footer .edit-link{ color:var(--ink-soft); } -.docs-footer .edit-link:hover{ color:var(--accent); } +.docs-footer .edit-link:hover{ color:var(--ink); } .docs-prevnext{ display:flex; justify-content:space-between; gap:16px; margin-top:16px; } -.docs-prevnext a{ - display:block; max-width:48%; - border:1px solid var(--grid-strong); border-radius:6px; padding:12px 16px; - font-family:var(--grotesk); font-size:14px; color:var(--ink); -} -.docs-prevnext a:hover{ border-color:var(--accent); } -.docs-prevnext .dir{ display:block; font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-soft); margin-bottom:4px; } +.docs-prevnext a{ display:block; max-width:48%; font-size:17px; font-style:italic; text-decoration:none; } +.docs-prevnext a:hover{ text-decoration:underline; } +.docs-prevnext .dir{ display:block; font-style:normal; font-size:14.5px; margin-bottom:2px; } .docs-prevnext .next{ margin-left:auto; text-align:right; } -/* ---- admonitions ---- */ -.admonition{ - border-left:3px solid var(--accent); - background:rgba(27,63,160,.05); - border-radius:0 6px 6px 0; - padding:14px 20px; - margin:0 0 22px; -} -.admonition-title{ - margin:0 0 8px; font-family:var(--grotesk); font-weight:600; font-size:13px; - letter-spacing:.06em; text-transform:uppercase; color:var(--accent); -} +/* ---- admonitions: Remark. / Hint. / Warning. ---- */ +.admonition{ border-left:var(--rule); padding:2px 0 2px 20px; margin:0 0 22px; } +.admonition-title{ margin:0 0 6px; font-weight:700; font-size:17px; } .admonition > *:last-child{ margin-bottom:0; } -.admonition-tip{ border-left-color:var(--green); background:rgba(31,138,95,.07); } -.admonition-tip .admonition-title{ color:var(--green); } -.admonition-caution{ border-left-color:var(--red); background:rgba(214,67,91,.06); } -.admonition-caution .admonition-title{ color:var(--red); } +.admonition p{ font-style:italic; } +.admonition-caution{ border-left-width:3px; } -/* ---- releases page ---- */ +/* ---- releases ---- */ .release-header{ padding-top:64px; } @media (max-width:720px){ .release-header{ padding-top:40px; } } .release-hero{ max-width:640px; } -.release-hero h1{ - margin:8px 0 0; font-family:var(--hand); font-size:clamp(48px,7.5vw,72px); - font-weight:500; line-height:1.02; letter-spacing:-0.005em; -} +.release-hero h1{ margin:8px 0 0; } .release-hero .lede{ margin-top:16px; } -.release-meta-row{ - display:flex; gap:0; margin-top:40px; - border-top:1px solid var(--grid-strong); border-bottom:1px solid var(--grid-strong); -} -.meta-cell{ - flex:1; display:flex; flex-direction:column; gap:6px; - padding:20px 24px; border-right:1px solid var(--grid-strong); -} +.release-meta-row{ display:flex; margin-top:40px; border-top:var(--rule); border-bottom:var(--rule); } +.meta-cell{ flex:1; display:flex; flex-direction:column; gap:4px; padding:18px 20px; border-right:var(--hair); } +.meta-cell:first-child{ padding-left:0; } .meta-cell:last-child{ border-right:none; } -.meta-num{ font-family:var(--mono); font-size:22px; color:var(--accent); } -.meta-cap{ font-family:var(--grotesk); font-size:12px; letter-spacing:.14em; text-transform:uppercase; color:var(--ink-soft); } +.meta-num{ font-family:var(--math); font-size:24px; } +.meta-cap{ font-size:15px; } @media (max-width:640px){ .release-meta-row{ flex-direction:column; } - .meta-cell{ border-right:none; border-bottom:1px solid var(--grid-strong); } + .meta-cell{ border-right:none; border-bottom:var(--hair); padding-left:0; } .meta-cell:last-child{ border-bottom:none; } } -.release-list{ - display:grid; gap:1px; border:1px solid var(--grid-strong); border-radius:6px; - overflow:hidden; background:var(--grid-strong); -} -.release-card{ background:var(--paper); } +.release-list{ display:grid; border-top:var(--rule); border-bottom:var(--rule); } +.release-card + .release-card{ border-top:var(--hair); } .release-card-head{ display:flex; align-items:center; justify-content:space-between; gap:24px; - padding:22px 32px; cursor:pointer; list-style:none; user-select:none; - transition:background-color .15s; + padding:18px 0; cursor:pointer; list-style:none; user-select:none; } .release-card-head::-webkit-details-marker{ display:none; } -.release-card-head:hover{ background:rgba(27,63,160,.045); } -.release-version{ - display:flex; align-items:center; gap:10px; - font-family:var(--serif); font-size:clamp(22px,3vw,28px); font-weight:400; - color:var(--accent); letter-spacing:-0.01em; -} -.chevron{ - display:inline-block; font-family:var(--serif); font-size:22px; - color:var(--ink-soft); transition:transform .2s ease; -} +.release-card-head:hover .release-version{ text-decoration:underline; text-underline-offset:4px; text-decoration-thickness:1px; } +.release-version{ display:flex; align-items:center; gap:10px; font-family:var(--math); font-size:clamp(21px,3vw,26px); } +.chevron{ display:inline-block; font-family:var(--math); font-size:18px; color:var(--ink-soft); transition:transform .2s ease; } .release-card[open] .chevron{ transform:rotate(90deg); } .release-head-right{ display:flex; align-items:center; gap:14px; } .badge{ - font-family:var(--grotesk); font-size:11px; font-weight:500; letter-spacing:.1em; - text-transform:uppercase; color:#fff; background:var(--red); padding:3px 9px; border-radius:999px; -} -.release-card time{ font-family:var(--mono); color:var(--ink-soft); font-size:13px; } -.release-sections{ - display:grid; grid-template-columns:repeat(3,1fr); gap:28px; - padding:4px 32px 32px; border-top:1px solid var(--grid-strong); padding-top:24px; -} -.release-section{ padding:0; } -.release-section h4{ - margin:0 0 10px; font-family:var(--grotesk); font-size:13px; font-weight:500; - letter-spacing:.18em; text-transform:uppercase; color:var(--red); -} -.release-section ul{ margin:0; padding-left:20px; color:var(--ink-soft); font-size:16.5px; line-height:1.6; } -.release-section li + li{ margin-top:8px; } -@media (max-width:860px){ .release-sections{ grid-template-columns:1fr; gap:22px; } } -@media (max-width:560px){ - .release-card-head{ padding:18px 20px; } - .release-sections{ padding:4px 20px 24px; } -} - -/* ---- roadmap page ---- */ -.release-hero .eyebrow-hand{ margin-bottom:0; } - -/* A hand-drawn dashed line runs down through the marker column, connecting - every phase in a group like a sketched timeline. Each marker (check/dot) - sits on top with a solid background so it reads as a bead on the line. */ -.roadmap-list{ - position:relative; - display:flex; flex-direction:column; - border:1px solid var(--grid-strong); border-radius:6px; - background:var(--paper); margin-bottom:12px; - overflow:hidden; -} -.roadmap-list::before{ - content:""; - position:absolute; - left:36px; top:0; bottom:0; width:0; - border-left:1.5px dashed var(--grid-strong); -} -.roadmap-item{ - position:relative; - display:flex; gap:18px; align-items:flex-start; - padding:20px 26px; - border-bottom:1px solid var(--grid-strong); -} -.roadmap-item:last-child{ border-bottom:none; } + font-family:var(--serif); font-variant:small-caps; text-transform:lowercase; font-size:14px; letter-spacing:.05em; + color:var(--ink); border:1px solid var(--ink); padding:0 8px; +} +.release-card time{ font-family:var(--mono); color:var(--ink-soft); font-size:12.5px; } +.release-sections{ display:grid; grid-template-columns:repeat(3,1fr); gap:28px; padding:6px 0 28px; } +.release-section h4{ margin:0 0 8px; font-size:16px; color:var(--ink) !important; } +.release-section ul{ margin:0; padding-left:20px; font-size:16.5px; line-height:1.6; } +.release-section li + li{ margin-top:6px; } +@media (max-width:860px){ .release-sections{ grid-template-columns:1fr; gap:20px; } } + +/* ---- roadmap: a sequence ---- */ +.roadmap-list{ position:relative; display:flex; flex-direction:column; border-top:var(--rule); border-bottom:var(--rule); margin-bottom:12px; } +.roadmap-list::before{ content:""; position:absolute; left:9px; top:0; bottom:0; border-left:1px dotted var(--ink-faint); } +.roadmap-item{ position:relative; display:flex; gap:20px; align-items:flex-start; padding:18px 0; border-top:var(--hair); } +.roadmap-item:first-child{ border-top:none; } .roadmap-item-mark{ - position:relative; z-index:1; flex-shrink:0; margin-top:3px; - width:20px; height:20px; border-radius:50%; - background:var(--ground); + position:relative; z-index:1; flex-shrink:0; margin-top:4px; + width:19px; height:19px; background:var(--ground); display:flex; align-items:center; justify-content:center; } .roadmap-check{ display:inline-flex; align-items:center; justify-content:center; - width:20px; height:20px; border-radius:50%; - background:var(--green); color:#fff; font-size:12px; line-height:1; -} -.roadmap-dot{ - display:inline-flex; align-items:center; justify-content:center; - width:12px; height:12px; border-radius:50%; - background:var(--red); color:var(--red); font-size:0; + width:16px; height:16px; border-radius:50%; background:var(--ink); color:#fff; font-size:10px; line-height:1; } +.roadmap-dot{ display:inline-block; width:12px; height:12px; border-radius:50%; background:var(--ink); font-size:0; } +.roadmap-dot-planned{ background:var(--ground); border:1px solid var(--ink); } .roadmap-item-body{ flex:1; min-width:0; } .roadmap-item-head{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; } -.roadmap-phase{ - font-family:var(--mono); font-size:12px; color:var(--ink-soft); - border:1px solid var(--grid-strong); border-radius:10px; padding:1px 8px; -} -.roadmap-item-head h3{ - font-family:var(--hand); font-weight:600; font-size:24px; line-height:1.02; - margin:0; color:var(--ink); -} -.roadmap-item-body p{ margin:6px 0 0; color:var(--ink-soft); font-size:15.5px; line-height:1.5; } -.roadmap-dot-planned{ - background:var(--ground); border:1.5px solid var(--ink-soft); color:transparent; -} -.roadmap-in_progress{ background:rgba(27,63,160,.045); } -.roadmap-in_progress .roadmap-item-head h3{ color:var(--ink); } -.roadmap-planned .roadmap-item-head h3{ color:var(--ink-soft); } -.badge-next{ background:var(--accent); } -.badge-planned{ background:var(--ink-soft); } -.roadmap-group{ padding-top:56px; padding-bottom:0; } -.roadmap-group:first-of-type{ padding-top:88px; } -@media (max-width:560px){ - .roadmap-list::before{ left:28px; } - .roadmap-item{ padding:16px 18px; gap:12px; } -} +.roadmap-phase{ font-family:var(--mono); font-size:12px; color:var(--ink-soft); } +.roadmap-item-head h3{ font-family:var(--serif); font-weight:700; font-size:19px; line-height:1.3; margin:0; } +.roadmap-item-body p{ margin:4px 0 0; color:var(--ink-soft); font-size:16px; line-height:1.5; font-style:italic; } +.roadmap-planned .roadmap-item-head h3{ font-weight:400; } +.roadmap-group{ padding-top:56px; padding-bottom:0; border-top:none; } +.roadmap-group:first-of-type{ padding-top:72px; } /* ---- 404 ---- */ .not-found{ text-align:center; padding:120px 0; } -.not-found .turn{ - font-family:var(--math); font-style:italic; font-size:clamp(60px,14vw,120px); - color:var(--accent); display:block; line-height:.9; -} +.not-found .turn{ font-family:var(--math); font-style:italic; font-size:clamp(60px,14vw,120px); display:block; line-height:.9; } /* ---- Copy button for docs code blocks (issue #343) ---- */ .docs-content pre{ position:relative; padding-top:2rem; } .copy-btn{ - position:absolute; top:.5rem; right:.5rem; - padding:.15rem .5rem; - font:500 .75rem/1 var(--grotesk, ui-sans-serif, system-ui, sans-serif); - color:var(--ink-soft, #54607A); - background:var(--paper, #fff); - border:1px solid var(--grid-strong, #C9D6EE); - border-radius:4px; + position:absolute; top:.45rem; right:.5rem; + padding:.1rem .5rem; + font:400 .85rem/1.2 var(--serif); + font-variant:small-caps; + color:var(--ink-soft); + background:var(--ground); + border:1px solid var(--grid-strong); cursor:pointer; opacity:0; transition:opacity .15s ease; } .docs-content pre:hover .copy-btn, .copy-btn:focus-visible{ opacity:1; } -.copy-btn.copied{ color:var(--green, #1F8A5F); border-color:var(--green, #1F8A5F); } +.copy-btn.copied{ color:var(--ink); border-color:var(--ink); } .copy-status{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0, 0, 0, 0); white-space:nowrap; border:0; } + +/* ---- home: definition, algorithm, equation ---- */ +.def-label{ font-weight:700; margin-right:.35em; } +.definition{ font-style:italic; } +.definition .def-label{ font-style:normal; } +.remark{ color:var(--ink-soft); } +.sec-intro{ max-width:38em; margin:-16px 0 32px; } +.two .sec-head{ margin-bottom:20px; } + +.algorithm{ margin:0; border-top:var(--rule); border-bottom:var(--rule); } +.algorithm figcaption{ padding:8px 0; border-bottom:var(--hair); font-size:17px; } +.algorithm ol{ margin:0; padding:14px 0 14px 2.4em; font-size:17px; line-height:1.9; } +.algorithm li::marker{ font-size:13px; color:var(--ink-faint); font-family:var(--mono); } +.algorithm li.in1{ padding-left:1.6em; } +.algorithm li.in2{ padding-left:3.2em; } +.algorithm .kw{ font-weight:700; } +.algorithm .fn{ font-variant:small-caps; } +.algorithm i{ font-family:var(--math); } +.algorithm .cmt{ float:right; color:var(--ink-faint); font-style:italic; font-size:15px; } +.algorithm .cmt::before{ content:"\25B7\00a0"; font-style:normal; } + +.dep-eq{ position:relative; text-align:center; margin:40px 0 0; font-size:20px; } +.dep-eq .pkg-m{ font-family:var(--mono); font-size:16px; margin:0 .4em; } +.dep-eq .eqno{ position:absolute; right:0; color:var(--ink-soft); } +.caption{ text-align:center; font-style:italic; color:var(--ink-soft); font-size:16px; margin:8px 0 0; } +@media (max-width:560px){ .dep-eq .eqno{ position:static; display:block; } .algorithm .cmt{ display:none; } } + +/* ---- home: hand-drawn loop diagram ---- */ +.sketch{ margin:0; } +.sketch svg{ display:block; width:100%; height:auto; color:var(--ink); } +.sketch .ink path{ fill:none; stroke:currentColor; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round; } +.sketch .hand{ font-family:"Caveat",cursive; font-size:22px; fill:var(--ink); text-anchor:middle; stroke:none; } +.sketch .hand.big{ font-size:27px; font-weight:600; } +.sketch .hand.soft{ fill:var(--ink-soft); font-size:20px; } +.sketch figcaption{ font-size:15px; color:var(--ink-soft); margin-top:6px; } +.sketch .hand.start{ text-anchor:start; } +.sketch .hand.end{ text-anchor:end; } +.sketch .ink path.pill{ fill:var(--ground); } +.sketch .ink path.lane{ stroke:var(--grid-strong); stroke-width:1.2; } +.sketch .ink path.flow{ stroke-dasharray:5 5; stroke-width:1.3; } +.sketch .code{ font-family:var(--mono); font-size:13px; fill:var(--ink); text-anchor:middle; } + +/* ---- home: code figures, syllabus ---- */ +.two.even{ grid-template-columns:1fr 1fr; align-items:start; } +@media (max-width:820px){ .two.even{ grid-template-columns:1fr; } } +.code-fig{ + margin:0; padding:18px 0; overflow-x:auto; + border-top:var(--rule); border-bottom:var(--rule); + font-family:var(--mono); font-size:12.5px; line-height:1.7; color:var(--ink); +} +.sketch .code.sm{ font-size:12px; } +.sketch .code.start{ text-anchor:start; } +.sketch .ink circle{ fill:var(--ground); stroke:currentColor; stroke-width:1.6; } +.sketch figcaption code{ font-family:var(--mono); font-size:.85em; } +.sec-intro code{ font-family:var(--mono); font-size:.82em; } +.principles-line{ font-style:italic; color:var(--ink-soft); } + +.syllabus{ width:100%; border-collapse:collapse; margin-top:32px; font-size:16.5px; border-top:var(--rule); border-bottom:var(--rule); } +.syllabus th{ text-align:left; font-weight:400; font-variant:small-caps; text-transform:lowercase; letter-spacing:.06em; color:var(--ink-soft); padding:8px 12px 8px 0; border-bottom:var(--rule); } +.syllabus td{ padding:9px 12px 9px 0; border-bottom:var(--hair); } +.syllabus tr:last-child td{ border-bottom:none; } +.syllabus .n{ font-weight:700; width:2em; } +.syllabus .num{ text-align:right; font-family:var(--math); padding-right:0; } +.syllabus code{ font-family:var(--mono); font-size:13px; color:var(--ink-soft); } +.syllabus a{ text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:3px; text-decoration-color:var(--ink-faint); } +@media (max-width:560px){ .syllabus td:nth-child(3), .syllabus th:nth-child(3){ display:none; } } +.code-fig, .sketch .code, .terminal pre, .docs-content pre, .install{ font-variant-ligatures:none; font-feature-settings:"calt" 0, "liga" 0; } + +/* ---- hero: install tabs + loop figure ---- */ +.install-tabs{ display:flex; gap:18px; margin:34px 0 8px; } +.install-tabs button{ + background:none; border:none; padding:0 0 2px; cursor:pointer; + font-family:var(--serif); font-variant:small-caps; text-transform:lowercase; + font-size:16px; letter-spacing:.05em; color:var(--ink-faint); + border-bottom:1px solid transparent; +} +.install-tabs button[aria-selected="true"]{ color:var(--ink); border-bottom-color:var(--ink); } +.install + .cta-row{ margin-top:22px; } +.hero-loop .wedge{ fill:none; stroke:rgba(0,0,0,.07); stroke-width:48; } +.hero-loop .radius{ stroke:var(--ink); stroke-width:1.6; stroke-linecap:round; } +.hero-loop .hub{ fill:var(--ink); } +.hero-loop .node{ fill:var(--ground); stroke:var(--ink); stroke-width:1.5; transition:fill .2s; } +.hero-loop .node.on{ fill:var(--ink); } +.hero-loop .ev{ opacity:.2; transition:opacity .25s; } +.hero-loop .ev.on{ opacity:1; } +.hero-loop .hand.big{ fill:var(--ink-faint); transition:fill .25s; } +.hero-loop .hand.big.on{ fill:var(--ink); } +.hero-loop .angle{ font-family:var(--math); font-style:italic; font-size:15px; fill:var(--ink-soft); } +.sketch .code.end{ text-anchor:end; } +.hero-loop .hand.big{ font-size:31px; } +.hero-loop .code.sm{ font-size:14px; } +.hero-loop .angle{ font-size:17px; } +.hero-install{ display:flex; flex-direction:column; align-items:center; margin-top:40px; } +.hero-install .install-tabs{ margin-top:0; } +.hero-install .install{ max-width:100%; } +.hero-install .cta-row{ justify-content:center; } +@media (max-width:520px){ + .install{ font-size:clamp(8.5px, 2.35vw, 13.5px); gap:8px; padding:10px 10px; } + .install .copy{ padding-left:10px; font-size:13px; } +} +@media (max-width:520px){ .install .dollar{ display:none; } .install .copy{ font-size:12px; padding-left:8px; } } + +/* ---- red pen: everything "added by hand" ---- */ +.sec-head .mark, .def-label, .pr h3::before, .closing p::after, +.eyebrow-hand, .admonition-title{ color:var(--pen); } +.hero .eyebrow-hand{ color:var(--ink-soft); } +.admonition{ border-left-color:var(--pen); } +.sketch .hand.soft{ fill:var(--pen); } +.sketch .ink path.flow{ stroke:var(--pen); } +.sketch figcaption{ color:var(--ink-soft); } +.hero-loop .node.on{ fill:var(--pen); stroke:var(--pen); } +.hero-loop .ev.on{ fill:var(--pen); } +.hero-loop .wedge{ stroke:rgba(194,64,42,.12); } +.hero-loop .angle{ fill:var(--ink-soft); } +::selection{ background:var(--pen); color:#fff; } + +/* ---- figures draw themselves on scroll (classes set by Home.astro) ---- */ +.sketch .draw{ + stroke-dasharray:1; stroke-dashoffset:0; + transition:stroke-dashoffset .5s ease-in-out calc(var(--i) * var(--step)); +} +.sketch.pending .draw{ stroke-dashoffset:1; } +.sketch .fade{ transition:opacity .4s ease calc(var(--i) * var(--step) + 250ms); } +.sketch.pending .fade{ opacity:0; } +.sketch .dot{ fill:var(--ink); } +.sketch .angle{ font-family:var(--math); font-style:italic; font-size:17px; fill:var(--ink-soft); } +.sketch .angle.end{ text-anchor:end; } diff --git a/website/astro.config.mjs b/website/astro.config.mjs index d1ad7b4fcd..7140983679 100644 --- a/website/astro.config.mjs +++ b/website/astro.config.mjs @@ -9,7 +9,7 @@ export default defineConfig({ publicDir: "./static", integrations: [sitemap()], markdown: { - shikiConfig: { theme: "monokai" }, + shikiConfig: { theme: "min-light" }, processor: unified({ remarkPlugins: [admonitions] }), }, }); diff --git a/website/src/components/Home.astro b/website/src/components/Home.astro index a3d3dbfa22..424379014e 100644 --- a/website/src/components/Home.astro +++ b/website/src/components/Home.astro @@ -1,104 +1,177 @@ --- import { site } from "../data"; +const toolCode = `from tau_agent.messages import TextContent +from tau_agent.tools import AgentTool, AgentToolResult + + +async def _run_hello(tool_call_id, arguments, + signal=None, on_update=None): + who = str(arguments.get("who", "world")) + return AgentToolResult( + content=[TextContent(text=f"Hello, {who}!")]) + + +def setup(tau): + tau.register_tool(AgentTool( + name="hello", + label="hello", + description="Greet someone by name.", + parameters={ + "type": "object", + "properties": {"who": {"type": "string"}}, + }, + execute_fn=_run_hello, + ))`; + +const frontendCode = `async for event in session.prompt(text): + match event.type: + case "message_update": + e = event.assistant_message_event + if e.type == "text_delta": + print(e.delta, end="") + case "tool_execution_start": + print(f"\\n→ {event.tool_name}({event.args})") + case "tool_execution_end": + print(" ✗" if event.is_error else " ✓") + case "agent_settled": + break`; ---
-

An educational coding-agent project

+

+ An open-source coding agent, written to be read +

- Learn how coding agents are built. + A coding agent you can read in an afternoon.

- Tau is a small Python coding agent you read like a textbook. - Watch it stream model output, call tools, manage sessions, and grow into - a terminal UI — one readable layer at a time. + Tau is a small, working coding agent in Python. It talks + to a model, reads and edits your files, and runs shell commands from your + terminal — with no framework hiding how any of it works.

- No hidden machinery. Every moving part is on the page. + Use it as a tool. Read it as a textbook. Fork it as a starting point.

-
- - $ curl -LsSf https://twotimespi.dev/install.sh - | sh - + +
+ + + + + + + + prompt - - Start with the architecture →model + tool + result + + + + + agent_start - Join the Discord community → + text_delta -
- -
- -
- θ sweeps 0 → τ - - θ = 0.00 + + tool_execution_end + 0 + τ/4 + τ/2 + 3τ/4 + θ = 0.00 + +
Fig. 1 — one turn of the loop is τ
-
-
- learnagent architecture +
+ -
-
- readsmall Python layersWindows +
-
- runa real terminal agent + ${" "} + curl -LsSf https://twotimespi.dev/install.sh | sh + + +
@@ -108,214 +181,595 @@ import { site } from "../data";
- 01 -
-

3-layers

-

A coding agent as a curriculum

-
+ 1 +

An agent is a loop

-
-
- Ⅰ - tau_ai -

Models become streams

-

- Provider adapters turn model responses into provider-neutral events - the rest of the agent consumes. +

+
+

+ Definition 1.1 + A coding agent is a language model run in a loop, where each reply + may ask for a tool — read a file, edit it, run a command — and + each tool result is fed back as the next input. The loop stops when the + model answers without asking for anything.

-
-
- Ⅱ - tau_agent -

The agent loop

- The reusable harness: messages, tools, transcript state, cancellation, - queued prompts, sessions. + That's the whole idea. Everything else in Tau — sessions, + skills, the terminal UI — is built around this loop, not inside + it.

-
-
- Ⅲ - tau_coding -

It becomes useful

- The coding environment: files, shell, durable sessions, skills, slash - commands, and a Textual TUI. + Read the loop →

+
+ + + + + + + + + + + + + your prompt + + + + model + streams events + + + + + tool calls? + + + no + answer + + + + yes + + + run tools + read · edit · bash + + + append result + + repeat until the model stops asking. + +
Fig. 2 — the agent loop
+
-
-
-

no black boxes

-

Every moving part is visible.

-

- Tau answers the questions tutorials skip: What is an agent loop? - Where do tool calls come from? How does the transcript grow? How do sessions - survive the process exiting? -

-
-
-
- model streamtokens, tool requests, thinking deltas + 2 +

Three layers, nested

+
+

+ Tau is three Python packages, nested like boxes. Each one controls its own + job and only uses what's inside it — so you can learn, or replace, + them one at a time. +

+
+ + + + you + + + + + tau_coding + the app — touches your machine -
-
↓
-
- event streamthe contract between layers -
-
↓
-
- agent loopdecide, call tools, update transcript· reads & edits files -
-
↓
-
-
- sessioninspectable JSONL history -
-
- frontendprint, Rich, or TUI -
-
-
-
- + · runs shell commands + · saves sessions to disk + · skills & slash commands + · the terminal UI -
-
-
-

the boundary

-

Separate the brain, the environment, and the face.

-

- The whole lesson is the boundary. A reusable harness must not depend - on the terminal, file paths, or Rich rendering. Those wrap the harness - — they never live inside it. -

-
- + + + tau_ai + the model + · provider adapters + · token streaming + · one event format + + + + the only way out to a model + model APIs + OpenAI · Anthropic · local + + each box only imports what’s inside it. + +
Fig. 3 — what each layer controls
+ +
+ +
+
+ 3 +

Everything is an event

+

+ The agent doesn't print, draw, or save anything itself. Each layer emits + small, typed events, and the layer above turns them into its own. Whoever + listens at the top — a one-shot CLI, the terminal UI, your own + frontend, or a JSONL session file — decides what to do with them. +

+
+ + + + + + + + + + + + + + + + + + + + + + tau_coding + the app + tau_agent + the loop + tau_ai + the model + became text + run read(README) + saved + saved + + time + prompt: “fix the typo in README” + the TUI and session.jsonl listen up here ↑ + + entry_appended + entry_appended + agent_settled + message_update + tool_execution_start + tool_execution_end + turn_end + response_start + text_delta + tool_call + response_end + +
+ Fig. 4 — one short run, as events. Each layer listens to the one + below and speaks its own vocabulary. +
+
- 02 -
-

the skills

-

What you can learn from Tau

-
+ 4 +

A tool is just a function

-
-
Provider-neutral streaming interfaces
-
Agent loops that request and execute tools
-
Typed local tools for read, write, edit, and bash
-
Durable sessions under ~/.tau/sessions
-
Session resume, branching, JSONL export, and HTML export
-
Project instructions, skills, and prompt templates
-
Slash commands and model/provider selection
-
Context accounting, compaction, and thinking controls
-
How to keep Textual behind a UI adapter boundary
+

+ Where do tool calls come from? A tool is half schema — a name, a + description, and parameters the model can read — and half plain + async function. This is a complete Tau extension, from{" "} + examples/extensions/hello_tool.py: +

+
+
{toolCode}
+
+ + + + + model + + + calls it + the model sees + your code runs + + + back into the transcript + + name="hello" + description= + "Greet someone…" + parameters={ + "who": string + } + _run_hello(args) + AgentToolResult + AgentTool + "Hello, Ada!" + +
Fig. 5 — half schema, half function
+
- 03 -
-

how we think

-

Educational principles

-
+ 5 +

A frontend in a dozen lines

-
-
-

Small layers beat magic

-

- One job per package. Study the provider layer, harness, and coding app - on their own. -

-
-
-

Events make agents teachable

-

- The agent emits a stream you can render, test, and export — not - control flow buried in callbacks. -

-
-
-

Real enough to matter

-

- Educational, not a toy. Run it as a real terminal agent while reading - the code behind it. -

-
-
-

Docs follow implementation

-

- Built phase by phase, each with notes on what was added, why, and how - it fits. -

-
+

+ The terminal UI is one listener among many. Anything that can loop over + the session's events is a frontend — here is one that prints to + stdout, using the real event names from §3. +

+
+
{frontendCode}
+
+ + + session.prompt(…) + your screen + + + + + + + + + + + + + + + you decide what each event looks like. + + message_update + message_update + tool_execution_start + tool_execution_end + message_update + agent_settled + I'll open the README… + → read(README.md) ✓ + Fixed the typo. + — done — + +
+ Fig. 6 — a frontend is a match on event types +
+
+
+
+ 6 +

A syllabus

+
+

+ Seven files, read in order, take you from a single event to a working + coding agent. Line counts are from the current source. +

+
+ + + + + 1 + 87 lines + + 2 + 93 lines + + 3 + 118 lines + + 4 + 376 lines + + 5 + 259 lines + + 6 + 171 lines + + 7 + 1,218 lines + ≈ 2,300 lines in all — about an afternoon. + circle size ∝ √lines + + events.py + _provider_events.py + tools.py + loop.py + harness.py + jsonl.py + tools.py + +
Fig. 7 — the reading route
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
§LessonFileLines
1Events, the contracttau_agent/events.py87
2Models become eventstau_ai/_provider_events.py93
3What a tool istau_agent/tools.py118
4The looptau_agent/loop.py376
5The harnesstau_agent/harness.py259
6Sessions on disktau_agent/session/jsonl.py171
7Real toolstau_coding/tools.py1,218
+
+
-

the origin

-

- Inspired by Pi, written as a Python learning path. -

+
+ 7 +

Pi, and why τ

+

- Pi is the minimalist - coding-agent harness this project borrows its architectural lesson from - — keep the harness, the environment, and the UI apart. Tau isn't a - line-by-line port; it's an educational Python take on the same core ideas. + Tau began as a way to understand{" "} + Pi, a + small coding agent written in TypeScript. Pi keeps three things apart: + the loop, the machine it works on, and the screen you watch it on. Tau + keeps that split and rebuilds it in Python, with notes on every step.

- Visit pi.dev → + The name is a joke that stuck. π is half a turn; τ = 2π is + the whole circle. Pi was the first half of the trip — Tau tries + to go the rest of the way round, slowly, and show its work.{" "} + More on τ than you asked for →

- +
+ + + + + Pi + half a turn · TypeScript + Tau + the whole turn · Python, with notes + same three parts + the loop + the machine + the screen + + + + 0 + π + τ = 2π + +
Fig. 8 — π gets you halfway
+
τ

- A map for building your own agent: start with events, add a loop, wrap it - in a harness, then give it tools and a UI. + Start with events, add a loop, give it tools, wrap it in a UI. That's a + coding agent.

@@ -333,11 +787,131 @@ import { site } from "../data"; Get started → - Follow the roadmap →Join the Discord →
+ + + + diff --git a/website/src/components/Releases.astro b/website/src/components/Releases.astro index 64c7a5245c..c57b83439e 100644 --- a/website/src/components/Releases.astro +++ b/website/src/components/Releases.astro @@ -32,7 +32,7 @@ import { releases } from "../data";
- 01

All releases

+ 1

All releases

{ diff --git a/website/src/components/WhyTau.astro b/website/src/components/WhyTau.astro index cf447d602b..9665b19cf0 100644 --- a/website/src/components/WhyTau.astro +++ b/website/src/components/WhyTau.astro @@ -50,7 +50,7 @@
- 01 + 1

Radians should make sense. π won't let them.

@@ -204,7 +204,7 @@
- 02 + 2

The famous equations were hiding a τ

diff --git a/website/static/landing.js b/website/static/landing.js index 8acb66fe8f..2df283225e 100644 --- a/website/static/landing.js +++ b/website/static/landing.js @@ -16,11 +16,11 @@ var canvas = document.getElementById("tauCanvas"); if(!canvas) return; var ctx = canvas.getContext("2d"); - var INK = "#13213C"; - var BLUE = "#1B3FA0"; - var RED = "#D6435B"; - var SOFT = "#9FB0D0"; - var GRID = "#C9D6EE"; + var INK = "#111111"; + var BLUE = "#111111"; + var RED = "#C2402A"; + var SOFT = "#9A9A9A"; + var GRID = "#E2E2E2"; var TAU = Math.PI * 2; var W = canvas.width, H = canvas.height, DPR = 1; @@ -98,11 +98,11 @@ ctx.strokeStyle = GRID; ctx.lineWidth = 1.4; ctx.beginPath(); ctx.arc(cx, cy, R, 0, TAU); ctx.stroke(); // vertical diameter guide - ctx.strokeStyle = "rgba(159,176,208,.45)"; ctx.lineWidth = 1; ctx.setLineDash([2,3]); + ctx.strokeStyle = "rgba(0,0,0,.45)"; ctx.lineWidth = 1; ctx.setLineDash([2,3]); ctx.beginPath(); ctx.moveTo(cx, cy-R); ctx.lineTo(cx, cy+R); ctx.stroke(); ctx.setLineDash([]); // --- swept angle wedge + arc --- - ctx.fillStyle = "rgba(27,63,160,.10)"; + ctx.fillStyle = "rgba(0,0,0,.05)"; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.arc(cx, cy, R*0.42, 0, -theta, true); ctx.closePath(); ctx.fill(); ctx.strokeStyle = BLUE; ctx.lineWidth = 1.4; @@ -110,7 +110,7 @@ // --- traced sine wave so far (with soft glow) --- ctx.save(); - ctx.shadowColor = "rgba(27,63,160,.35)"; ctx.shadowBlur = 6; + ctx.shadowColor = "rgba(0,0,0,0)"; ctx.shadowBlur = 6; ctx.strokeStyle = BLUE; ctx.lineWidth = 2.2; ctx.lineJoin = "round"; ctx.beginPath(); for(var i=0; i<=theta; i+=0.02){ @@ -126,7 +126,7 @@ ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(px, py); ctx.stroke(); // --- height (sin) bar on circle --- - ctx.strokeStyle = "rgba(214,67,91,.55)"; ctx.lineWidth = 1.4; + ctx.strokeStyle = "rgba(194,64,42,.6)"; ctx.lineWidth = 1.4; ctx.beginPath(); ctx.moveTo(px, cy); ctx.lineTo(px, py); ctx.stroke(); // --- projection line linking circle point to wave point --- @@ -136,7 +136,7 @@ // --- moving points (glow) --- ctx.save(); - ctx.shadowColor = "rgba(214,67,91,.5)"; ctx.shadowBlur = 8; + ctx.shadowColor = "rgba(0,0,0,0)"; ctx.shadowBlur = 8; ctx.fillStyle = RED; ctx.beginPath(); ctx.arc(px, py, 4.2, 0, TAU); ctx.fill(); ctx.beginPath(); ctx.arc(ex, ey, 4.2, 0, TAU); ctx.fill(); @@ -264,8 +264,8 @@ ctx.fillText("r", (cx + mx)/2 + 8, (cy + my)/2 - 8); dot(ctx, cx, cy, 2.4, INK); - dot(ctx, mx, my, 4, RED, "rgba(214,67,91,.5)"); - dot(ctx, contactX, baseY, 4, RED, "rgba(214,67,91,.5)"); + dot(ctx, mx, my, 4, RED, "rgba(0,0,0,0)"); + dot(ctx, contactX, baseY, 4, RED, "rgba(0,0,0,0)"); // readout ctx.fillStyle = BLUE; @@ -283,7 +283,7 @@ ctx.beginPath(); ctx.arc(cx, cy, R, 0, TAU); ctx.stroke(); // swept wedge - ctx.fillStyle = "rgba(27,63,160,.12)"; + ctx.fillStyle = "rgba(0,0,0,.05)"; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.arc(cx, cy, R, 0, -theta, true); ctx.closePath(); ctx.fill(); ctx.strokeStyle = BLUE; ctx.lineWidth = 2; @@ -308,11 +308,11 @@ ctx.strokeStyle = INK; ctx.lineWidth = 1.8; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(px, py); ctx.stroke(); dot(ctx, cx, cy, 2.4, INK); - dot(ctx, px, py, 4, RED, "rgba(214,67,91,.5)"); + dot(ctx, px, py, 4, RED, "rgba(0,0,0,0)"); // centre readout ctx.fillStyle = BLUE; ctx.textAlign = "center"; ctx.textBaseline = "middle"; - ctx.font = "600 18px 'Space Grotesk', sans-serif"; + ctx.font = "600 18px 'STIX Two Text', serif"; ctx.fillText((theta/TAU).toFixed(2) + " of a turn", cx, cy + R + 40); }, 320); @@ -336,14 +336,14 @@ // the landing point "1" var near = Math.min(theta, TAU - theta) < 0.18; ctx.fillStyle = near ? BLUE : SOFT; - dot(ctx, cx + R, cy, near ? 5 : 3.2, near ? BLUE : SOFT, near ? "rgba(27,63,160,.5)" : null); + dot(ctx, cx + R, cy, near ? 5 : 3.2, near ? BLUE : SOFT, near ? "rgba(0,0,0,0)" : null); ctx.textAlign = "center"; ctx.textBaseline = "top"; ctx.font = "12px 'JetBrains Mono', monospace"; ctx.fillText("1", cx + R, cy + 8); // rotating phasor e^{i theta} var px = cx + Math.cos(theta)*R, py = cy - Math.sin(theta)*R; // projections - ctx.strokeStyle = "rgba(159,176,208,.6)"; ctx.lineWidth = 1; ctx.setLineDash([3,3]); + ctx.strokeStyle = "rgba(0,0,0,.6)"; ctx.lineWidth = 1; ctx.setLineDash([3,3]); ctx.beginPath(); ctx.moveTo(px, py); ctx.lineTo(px, cy); ctx.stroke(); ctx.beginPath(); ctx.moveTo(px, py); ctx.lineTo(cx, py); ctx.stroke(); ctx.setLineDash([]); @@ -354,7 +354,7 @@ ctx.strokeStyle = INK; ctx.lineWidth = 1.8; ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(px, py); ctx.stroke(); dot(ctx, cx, cy, 2.4, INK); - dot(ctx, px, py, 4.2, RED, "rgba(214,67,91,.5)"); + dot(ctx, px, py, 4.2, RED, "rgba(0,0,0,0)"); // label ctx.fillStyle = near ? BLUE : INK; diff --git a/website/tests/site.test.mjs b/website/tests/site.test.mjs index 374529eddf..c737246f29 100644 --- a/website/tests/site.test.mjs +++ b/website/tests/site.test.mjs @@ -92,7 +92,7 @@ test("docs retain callouts, highlighting, navigation, and edit links", async () assert.ok(html.includes(value), value); const home = await readFile(path.join(dist, "index.html"), "utf8"); assert.ok(home.includes("https://github.com/huggingface/tau")); - assert.ok(home.includes("tauCanvas")); + assert.ok(home.includes("loopRadius")); const why = await readFile(path.join(dist, "why-tau/index.html"), "utf8"); assert.ok(why.includes("MathJax")); });