diff options
Diffstat (limited to 'src/app.css')
| -rw-r--r-- | src/app.css | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/src/app.css b/src/app.css index f5b269c..3c7b17c 100644 --- a/src/app.css +++ b/src/app.css @@ -12,6 +12,237 @@ themes: monokai --default; } +/* Inset "well" — the Artix wiki's code blocks (darkstrap `pre`): a panel that + reads as pressed INTO the page — the page colour darkened, a dark inner + shadow under the top edge, a faint light catch-line under the bottom edge. + Shared by the chat's thinking/tool blocks (LazyCollapse) and the sidebar + views (TilePanels). darkstrap: background rgba(0,0,0,.3); box-shadow + rgba(255,255,255,.1) 0 1px 0, rgba(0,0,0,.8) 0 1px 7px 0 inset; radius 4px. + Ported onto the active daisyUI theme so it always matches, and toned down a + step: the fill is the theme's page colour (base-100 — both the chat and the + sidebar sit on it) darkened 18% (darkstrap: 30%), computed OPAQUE and exposed + as --inset-well-bg so sticky children can paint the same colour; the inner + shadow is 0.6 (darkstrap: 0.8); the catch-line is the theme's text colour at + 10% instead of plain white. In @layer components so utilities can override. */ +@layer components { + .inset-well { + --inset-well-bg: color-mix(in srgb, var(--color-base-100) 82%, black); + background-color: var(--inset-well-bg); + border: 0; + border-radius: var(--radius-box); + box-shadow: + 0 1px 0 color-mix(in srgb, var(--color-base-content) 10%, transparent), + inset 0 1px 7px 0 rgb(0 0 0 / 0.6); + } +} + +/* App navbar — the Artix wiki's navbar (darkstrap `.navbar-inner` on a + fixed-top bar): a top-to-bottom gradient (#444 → #222), a soft drop shadow + under the bar (0 1px 10px), and engraved text (1px black text-shadow). + Shared by the workspace top bar (App) and the home page header. Ported onto + the active daisyUI theme so it always matches. darkstrap's bar is LIGHTER + than its near-black page (that's what makes the shadow read), so the + gradient is shifted to keep that relationship on our lighter page: it runs + from the page colour (base-100) lifted 20% toward the text colour down to + base-100 lifted 3%. No bottom border (darkstrap has a 1px #030303 one — + removed by user request; the gradient + shadow carry the edge). The shadow + is 0.5 (darkstrap: 0.1 — invisible on our lighter page). Positioned + + z-indexed so the shadow paints over the content below. */ +@layer components { + .app-navbar { + position: relative; + z-index: 10; + flex-shrink: 0; + background-image: linear-gradient( + to bottom, + color-mix(in srgb, var(--color-base-100) 80%, var(--color-base-content)), + color-mix(in srgb, var(--color-base-100) 97%, var(--color-base-content)) + ); + box-shadow: 0 1px 10px rgb(0 0 0 / 0.5); + } + /* Engraved navbar text — titles only; on tiny faint labels it muddies. */ + .app-navbar-engraved { + text-shadow: 0 1px 0 black; + } +} + +/* Navbar buttons — the navbar's (`.app-navbar`) raised button, in the + same depth language as the rest of the UI: at rest they're RAISED (a + gradient a step lighter than the bar, a light highlight inside the top edge, + a thin dark edge + small drop below, light primary-blue text), and when + PRESSED they flip to the inset well (dark inner shadow) — pushed into the + bar. `.navbar-btn-primary` is the main action: the same button, tinted with + the theme's primary colour. `.navbar-btn-icon` is the square icon-only form. + Self-contained (not DaisyUI .btn) so nothing fights the gradients; colours + all come from the theme. */ +@layer components { + .navbar-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.375rem; + height: 2rem; + padding-inline: 0.75rem; + border-radius: var(--radius-field); + font-size: 0.875rem; + font-weight: 600; + line-height: 1; + white-space: nowrap; + cursor: pointer; + user-select: none; + /* The theme's primary, lifted toward white: crisp on the grey gradient + (plain primary read dim, and an engraved text-shadow muddied it at this + size — the shadow stays on the big titles only). */ + color: color-mix(in srgb, var(--color-primary) 75%, white); + border: 1px solid rgb(0 0 0 / 0.55); + background-image: linear-gradient( + to bottom, + color-mix(in srgb, var(--color-base-100) 72%, var(--color-base-content)), + color-mix(in srgb, var(--color-base-100) 90%, var(--color-base-content)) + ); + box-shadow: + inset 0 1px 0 rgb(255 255 255 / 0.12), + 0 1px 2px rgb(0 0 0 / 0.45); + transition: + filter 120ms ease-out, + box-shadow 120ms ease-out; + } + .navbar-btn:hover { + filter: brightness(1.12); + } + .navbar-btn:active, + .navbar-btn[aria-expanded="true"] { + /* Pressed → the inset well: pushed into the bar. */ + filter: none; + background-image: none; + background-color: color-mix(in srgb, var(--color-base-100) 82%, black); + box-shadow: + inset 0 1px 5px rgb(0 0 0 / 0.7), + 0 1px 0 color-mix(in srgb, var(--color-base-content) 10%, transparent); + } + .navbar-btn:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; + } + .navbar-btn-icon { + width: 2rem; + padding-inline: 0; + } + /* Secondary navbar actions: visually just text — no background, border or + shadow. The light primary-blue colour (same as the buttons' text) and the + spacing mark them as clickable; hover brightens + underlines, press dims. */ + .navbar-link { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.375rem; + height: 2rem; + min-width: 2rem; /* icon-only (compact) links keep a comfortable tap target */ + padding-inline: 0.375rem; + border-radius: var(--radius-field); + font-size: 0.875rem; + font-weight: 600; + line-height: 1; + white-space: nowrap; + cursor: pointer; + user-select: none; + background: none; + border: 0; + color: color-mix(in srgb, var(--color-primary) 75%, white); + text-underline-offset: 4px; + transition: color 120ms ease-out; + } + .navbar-link:hover { + color: color-mix(in srgb, var(--color-primary) 45%, white); + text-decoration: underline; + } + .navbar-link:active { + color: var(--color-primary); + } + .navbar-link:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; + } + .navbar-btn-primary { + color: var(--color-primary-content); + background-image: linear-gradient( + to bottom, + color-mix(in srgb, var(--color-primary) 82%, white), + color-mix(in srgb, var(--color-primary) 88%, black) + ); + box-shadow: + inset 0 1px 0 rgb(255 255 255 / 0.35), + 0 1px 2px rgb(0 0 0 / 0.45); + } + .navbar-btn-primary:active { + background-color: color-mix(in srgb, var(--color-primary) 80%, black); + } +} + +/* Raised button — the exact mirror of `.inset-well`, for a neutral surface + that pops OUT where the wells sink in (the sidebar's "+ Add view" under the + view wells). The well = page colour darkened 18%, dark shadow INSIDE under + the top edge (inset 0 1px 7px), light catch-line OUTSIDE below (0 1px 0). + Mirrored: page colour LIFTED toward the text colour, light highlight INSIDE + the top edge (inset 0 1px 0), the dark shadow OUTSIDE below (0 1px 7px), + plus a faint top-lit gradient. Pressed → it becomes the well (pushed in). */ +@layer components { + .raised-btn { + display: flex; + align-items: center; + justify-content: center; + border: 0; + border-radius: var(--radius-box); + cursor: pointer; + color: color-mix(in srgb, var(--color-primary) 75%, white); + background-color: color-mix(in srgb, var(--color-base-100) 90%, var(--color-base-content)); + background-image: linear-gradient(to bottom, rgb(255 255 255 / 0.06), rgb(0 0 0 / 0.1)); + box-shadow: + inset 0 1px 0 color-mix(in srgb, var(--color-base-content) 18%, transparent), + 0 1px 7px 0 rgb(0 0 0 / 0.6); + transition: + filter 120ms ease-out, + box-shadow 120ms ease-out; + } + .raised-btn:hover { + filter: brightness(1.12); + } + .raised-btn:active { + filter: none; + background-image: none; + background-color: color-mix(in srgb, var(--color-base-100) 82%, black); + box-shadow: + 0 1px 0 color-mix(in srgb, var(--color-base-content) 10%, transparent), + inset 0 1px 7px 0 rgb(0 0 0 / 0.6); + } + .raised-btn:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; + } +} + +/* Raised — the INVERSE of `.inset-well`, for things that pop OUT of the page + (the home page's workspace tiles). Where the well has a dark shadow INSIDE + under its top edge and a light catch-line OUTSIDE below it, a raised surface + has a light highlight INSIDE along its top edge, a soft shadow OUTSIDE below + it, and a faint top-lit gradient over its own colour (lighter top → darker + bottom — convex, where the well is concave). Built on Tailwind's shadow + variables (not a bare box-shadow) so it COMPOSES with the ring / shadow + utilities: the inner highlight rides --tw-inset-shadow (kept by + `hover:shadow-xl`, rings, drag), the drop rides --tw-shadow (which + `hover:shadow-xl` / `shadow-2xl` swap for a bigger lift). Works on any + background colour (the tiles' tone colours), so it always matches the theme. */ +@layer components { + .raised { + --tw-inset-shadow: inset 0 1px 0 rgb(255 255 255 / 0.45), inset 0 -1px 0 rgb(0 0 0 / 0.25); + --tw-shadow: 0 2px 9px 0 rgb(0 0 0 / 0.7); + box-shadow: + var(--tw-inset-shadow), var(--tw-inset-ring-shadow, 0 0 #0000), + var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + background-image: linear-gradient(to bottom, rgb(255 255 255 / 0.14), rgb(0 0 0 / 0.14)); + } +} + /* Rendered-Markdown (assistant messages) typography — scoped to .markdown-body so it never leaks into the rest of the app. */ .markdown-body { @@ -127,3 +358,28 @@ body, body { overflow: hidden; } + +/* App-shell height. NOT `h-screen` (100vh): on iOS/iPadOS WebKit (Safari, + Vivaldi, …) 100vh is the viewport with the browser toolbars RETRACTED, so + while they're showing the bottom of the app sits underneath them (the + sidebar's last item / the composer looked flush against the bottom edge). + 100dvh tracks the visible viewport as the toolbars show/hide; 100vh stays as + the fallback for engines without dvh. */ +.h-app { + height: 100vh; +} +@supports (height: 100dvh) { + .h-app { + height: 100dvh; + } +} + +/* Transcript rows: skip layout + paint for rows scrolled out of view. A long + turn has hundreds of rows; without this every one is laid out on first + paint (and on every resize). `contain-intrinsic-size: auto <h>` makes the + browser remember each row's last rendered height, so scrolling back up + doesn't jump; the 64px is only the estimate for never-rendered rows. */ +.chat-row { + content-visibility: auto; + contain-intrinsic-size: auto 64px; +} |
