summaryrefslogtreecommitdiffhomepage
path: root/src/app.css
diff options
context:
space:
mode:
Diffstat (limited to 'src/app.css')
-rw-r--r--src/app.css256
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;
+}