feat(web): 2x reading column on wide desktops — 92rem at >=1500px (chat, shared, document view)

This commit is contained in:
2026-09-01 00:39:19 -04:00
parent 140b97ebf3
commit 7b7a834a1a
5 changed files with 727 additions and 34 deletions
+56 -20
View File
@@ -33,6 +33,11 @@
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
--header-h: 64px;
/* Reading column: 46rem base (PLAN §7 lineage); 2x on wide desktops
(owner instruction 2026-08-31, TODO L5 / D2 — chat + shared +
document view). */
--chat-column: 46rem;
}
* { box-sizing: border-box; }
@@ -394,9 +399,11 @@ html::after {
/* Chat is a vertical conversation: a centered, capped column is the
correct layout here (PLAN §UI/UX). The surrounding frame keeps it
from collapsing into a hairline on wide screens. */
from collapsing into a hairline on wide screens. The cap is the
--chat-column token: 46rem base, 2x (92rem) at >=1500px wide
desktops (owner instruction 2026-08-31, TODO.md L5 / D2). */
.chat-shell {
max-width: 46rem;
max-width: var(--chat-column);
margin-inline: auto;
display: flex;
flex-direction: column;
@@ -413,8 +420,9 @@ html::after {
on desktop. The ≤640px block flips this to a vertical stack
(flex-direction: column + align-items: stretch — full-width pills,
New chat above Share; the existing ≤640px pill rules apply to the
stacked pills unchanged). The 46rem column contract is untouched
(PLAN §7). */
stacked pills unchanged). The reading-column contract is untouched
(--chat-column: 46rem base, 92rem at >=1500px — PLAN §7 lineage).
*/
.chat-actions {
display: flex;
flex-direction: row;
@@ -493,7 +501,8 @@ html::after {
/* GFM pipe tables (phase 44, 2026-08-27, TODO.md L6): the shared
renderer wraps every table in .md-table-wrap — the horizontal
scroller, so a wide table scrolls inside the bubble instead of
breaking the 46rem column — around a semantic <table class="md-table">
breaking the reading column (--chat-column: 46rem base, 92rem at
>=1500px) — around a semantic <table class="md-table">
(escape-first cells; alignment colons render left, owner decision).
Phase-08 tokens only: --line hairline borders and the thead tinted
from the plain surface family — --ink on --surface is 14.5:1 (PLAN
@@ -590,9 +599,9 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
own icon, own accent left border. Contrast: --accent-ink on the row's
--surface ≈10.4:1 (11.6:1 on the page bg), and --ink on --brand-soft
in the path `code` ≈11.5:1 — all comfortably AA in the (single dark)
theme. Inline rows only: appending lines never shifts the 46rem chat
column (no new container), and the rows are not interactive — no
focus targets. */
theme. Inline rows only: appending lines never shifts the chat
column (46rem base; 92rem at >=1500px — no new container), and the
rows are not interactive — no focus targets. */
.tool-calls {
display: flex;
flex-direction: column;
@@ -1144,7 +1153,8 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
/* ---------- Composer ---------- */
/* Phase 52 (2026-08-30, TODO.md L3): the composer is PINNED to the
viewport bottom. The page scrolls at the document level and
`.chat-shell` (the centered 46rem column) is the composer's sticky
`.chat-shell` (the centered reading column — 46rem base, 92rem at
>=1500px) is the composer's sticky
containing block, so the box sticks to the bottom edge of the
viewport at every scroll position and settles back into its normal
flow position (above the footer) once the document bottom is
@@ -2138,7 +2148,8 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
/* ---------- Shared page (phase 51, task 03) ----------
/shared/<token>: the anonymous read-only conversation (owner-locked
2026-08-29, TODO.md L6). The shell maps to the PLAN §7 centered
46rem chat column — the conversation reads exactly like the chat
chat column (--chat-column: 46rem base, 92rem at >=1500px) — the
conversation reads exactly like the chat
page (the .msg/.bubble/.thinking/.tool-calls/.msg-meta rules apply
unchanged) with NO composer, so the column contract holds for a
guest. Zero interactive controls (owner-locked): the chips are
@@ -2150,7 +2161,8 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
fonts. */
.shared-shell {
width: 100%;
max-width: 46rem; /* the PLAN §7 centered chat column */
max-width: var(--chat-column); /* the PLAN §7 centered chat column
(46rem base; 92rem at >=1500px — phase 58) */
margin-inline: auto;
display: flex;
flex-direction: column;
@@ -2313,10 +2325,12 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
#doc-content { display: flex; flex-direction: column; }
.doc-loading { margin: 1.5rem auto; text-align: center; color: var(--ink-soft); }
/* Markdown: the centered, ≤46rem reading column (PLAN §7.1). */
/* Markdown: the centered reading column — 46rem base, 2x (92rem) at
>=1500px (PLAN §7.1 lineage; owner instruction 2026-08-31, TODO.md
L5 / D2). */
.doc-md {
width: 100%;
max-width: 46rem;
max-width: var(--chat-column);
margin-inline: auto;
background: var(--surface);
border: 1px solid var(--line);
@@ -2361,12 +2375,13 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
margin-bottom: 1rem;
overflow-wrap: anywhere;
}
/* md/markdown: the panel matches the .doc-md ≤46rem centered reading
column — it is the column's label. Raw formats stay full width (the
/* md/markdown: the panel matches the .doc-md centered reading column
(46rem base; 92rem at >=1500px — the same --chat-column token) —
it is the column's label. Raw formats stay full width (the
.doc-raw default above), matching the full-width pre; in engines
without :has() the panel degrades to that full-width default. */
.doc-summary:has(+ .doc-md) {
max-width: 46rem;
max-width: var(--chat-column);
margin-inline: auto;
}
.doc-summary-title {
@@ -2528,7 +2543,8 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
/* ---------- Document modal (phase 26) ----------
"New documents should open in an almost-fullscreen modal, not in a new
page" (TODO.md L4). The overlay reuses the viewer page's .doc-meta
badge classes, the .doc-md ≤46rem reading column, and the .doc-raw
badge classes, the .doc-md reading column (46rem base; 92rem at
>=1500px), and the .doc-raw
pre — this block only adds the chrome (backdrop, panel, header,
actions, scroll container). Phase-08 tokens only; NO blur (the
phase-08 no-blur perf anchor); no new assets; system fonts.
@@ -2667,7 +2683,8 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
}
/* The scroll container: vertical scroll lives HERE, never the viewport.
.doc-md keeps its ≤46rem centered reading column inside; .doc-raw keeps
.doc-md keeps its centered reading column inside (46rem base;
92rem at >=1500px, capped there by the 1100px panel); .doc-raw keeps
its own overflow-x. tabindex="-1" in the markup is the JS focus target. */
.doc-modal-content {
flex: 1;
@@ -2951,8 +2968,9 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
.history-actions { flex-wrap: wrap; }
/* Phase 51: the shared page squeezes like the chat column — the
title and the note step down (the empty-state-title family); the
shell keeps its 46rem column (it is already the narrowest box on
the page) and .msg-body's 92% override above applies. */
shell keeps its base 46rem column (the >=1500px 92rem override
never applies here — it is already the narrowest box on the
page) and .msg-body's 92% override above applies. */
#shared-title { font-size: 1.35rem; }
.shared-note { font-size: 0.88rem; }
.footer-inner { flex-direction: column; gap: 0.2rem; text-align: center; }
@@ -2973,6 +2991,24 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
}
}
/* Phase 58: wide desktops (viewport >=1500px) read the 2x column —
--chat-column doubles to 92rem for the four reading shells (chat,
shared, the document viewer's .doc-md and its summary panel). The
chat and shared shells ARE their .container (the token max-width
overrides the .container's 72rem cap — same specificity, later in
the file), but the document page's .container.doc-shell WRAPS the
column, so the 72rem cap would bind first and pin .doc-md at
~1112px: the wide block lifts the shell's cap to the column plus
the container's two 1.25rem gutters, letting .doc-md's own 92rem
cap bind (1472px at the 16px root). Everything below 1500px
renders exactly as before, and .tuning-shell (a form, not a
reading surface) keeps its hard-coded 46rem at every width
(owner instruction 2026-08-31, TODO.md L5 / D2). */
@media (min-width: 1500px) {
:root { --chat-column: 92rem; }
.doc-shell { max-width: calc(var(--chat-column) + 2 * 1.25rem); }
}
/* Phase 46: prefers-reduced-motion stills the mobile menu — no
180ms slide+fade; open/close snaps (the visibility/opacity flip
applies instantly) and stays correct. BOTH states are named: the