packages/app/src/index.css
Rama dev · réplica de lectura del repositorio original.
@import "@opencode/ui/styles/tailwind";
@import "@opencode/session-ui/styles";
@import "@opencode/ui/styles/tokens";
@import "tw-animate-css";
/* Set on the timeline viewport and changed on every frame while the composer region grows. Neither inherits, so a change
restyles the viewport alone instead of every row inside it. */
@property --session-timeline-inset {
syntax: "<length>";
inherits: false;
initial-value: 0px;
}
@property --session-timeline-fade-start {
syntax: "<length>";
inherits: false;
initial-value: 0px;
}
@font-face {
font-family: "JetBrainsMono Nerd Font Mono";
src: url("/assets/JetBrainsMonoNerdFontMono-Regular.woff2") format("woff2");
font-weight: normal;
font-style: normal;
}
/* The terminal draws bold cells with a bold canvas font. */
@font-face {
font-family: "JetBrainsMono Nerd Font Mono";
src: url("/assets/JetBrainsMonoNerdFontMono-Bold.woff2") format("woff2");
font-weight: bold;
font-style: normal;
}
@font-face {
font-family: "Inter";
src: url("/assets/Inter.ttf") format("truetype");
font-weight: 100 900;
font-style: normal;
}
/* Text covers every weight below bold, so only bold syntax tokens and markup load the Bold face. */
@font-face {
font-family: "IBM Plex Mono";
src: url("@ibm/plex/IBM-Plex-Mono/fonts/complete/woff2/IBMPlexMono-Text.woff2") format("woff2");
font-weight: 100 599;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "IBM Plex Mono";
src: url("@ibm/plex/IBM-Plex-Mono/fonts/complete/woff2/IBMPlexMono-Bold.woff2") format("woff2");
font-weight: 600 900;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "IBM Plex Mono";
src: url("@ibm/plex/IBM-Plex-Mono/fonts/complete/woff2/IBMPlexMono-TextItalic.woff2") format("woff2");
font-weight: 100 599;
font-style: italic;
font-display: swap;
}
/* Panel motion sets this on the one element whose own layout reads it. An inherited property would restyle every
element under that element each time a flight starts or lands. */
@property --panel-hold-width {
syntax: "*";
inherits: false;
}
@media (display-mode: standalone) {
/* WebKit excludes safe-area insets from dvh in installed apps. */
#root {
height: 100vh;
}
}
/* iOS can report navigator.standalone without matching display-mode. */
#root[data-standalone="true"] {
height: 100vh;
}
@layer components {
[data-slot="session-chat-panel"][data-scrollbar-hidden="true"]
[data-slot="session-timeline-visible"]
.scroll-view__thumb {
visibility: hidden;
}
/* The timeline scrolls on under the composer region, passing behind its floating pill, and fades out as it reaches
the region's opaque card. A mask fades the content itself, so the edge works over any theme's background;
smoothstep stops avoid a visible horizon. */
[data-slot="session-timeline-scroll"] > .scroll-view__viewport {
--session-timeline-fade-start: var(--session-timeline-inset, 0px);
scroll-padding-bottom: var(--session-timeline-inset, 0px);
mask-image: linear-gradient(
to top,
transparent var(--session-timeline-fade-start),
rgb(0 0 0 / 0.16) calc(var(--session-timeline-fade-start) + 5px),
rgb(0 0 0 / 0.5) calc(var(--session-timeline-fade-start) + 10px),
rgb(0 0 0 / 0.84) calc(var(--session-timeline-fade-start) + 15px),
#000 calc(var(--session-timeline-fade-start) + 20px)
);
}
/* The review panel's visible width, which the header fade below tracks while the panel animates. Its fixed-width
content holds nothing else that reads it. */
#review-panel,
#bottom-panel {
container-type: inline-size;
}
/* Like the composer toolbar, fade only clipped content without reserving layout space.
The fade contracts as overflow clears; the second mask preserves the header divider. */
#review-panel .session-review-v2-tabs-bar {
--session-review-header-fade: clamp(0px, calc(100% - 100cqi), 24px);
mask-image:
linear-gradient(
to right,
#000 calc(100cqi - 40px - var(--session-review-header-fade)),
transparent calc(100cqi - 40px)
),
linear-gradient(to top, #000 1px, transparent 1px);
&:dir(rtl) {
mask-image:
linear-gradient(
to left,
#000 calc(100cqi - 40px - var(--session-review-header-fade)),
transparent calc(100cqi - 40px)
),
linear-gradient(to top, #000 1px, transparent 1px);
}
}
/* Root rules reach every element where highlights inherit; see quote-highlight.css in session-ui. */
@supports selector(:host-context(*)) {
:root::highlight(timeline-search-hit) {
background-color: color-mix(in srgb, var(--v2-icon-icon-accent) 28%, transparent);
}
:root::highlight(timeline-search-hit-active) {
background-color: var(--v2-icon-icon-accent);
color: var(--v2-background-bg-deep);
}
}
@supports not selector(:host-context(*)) {
::highlight(timeline-search-hit) {
background-color: color-mix(in srgb, var(--v2-icon-icon-accent) 28%, transparent);
}
::highlight(timeline-search-hit-active) {
background-color: var(--v2-icon-icon-accent);
color: var(--v2-background-bg-deep);
}
}
[data-component="menu-v2-content"].desktop-app-menu {
min-width: 160px;
padding: 2px;
}
[data-component="menu-v2-content"].desktop-app-menu:not(.desktop-app-menu-sub) {
width: 160px;
}
[data-component="menu-v2-content"].desktop-app-menu-sub {
width: max-content;
min-width: 240px;
max-width: min(320px, calc(100vw - 24px));
}
[data-component="menu-v2-content"].desktop-app-menu [data-slot="menu-v2-group-label"] {
display: flex;
align-items: center;
height: 28px;
padding: 0 12px;
font-size: var(--font-size-x-small);
font-weight: var(--font-weight-medium);
line-height: 1;
color: var(--text-weak);
}
[data-component="menu-v2-content"].desktop-app-menu [data-component="menu-v2-item"] {
min-height: 28px;
padding: 0 12px;
gap: 8px;
font-weight: var(--font-weight-regular);
line-height: 1;
}
[data-component="menu-v2-content"].desktop-app-menu [data-slot="menu-v2-item-content"] {
white-space: nowrap;
}
[data-component="menu-v2-content"].desktop-app-menu [data-slot="menu-v2-item-shortcut"] {
margin-left: auto;
color: var(--text-weak);
font-size: var(--font-size-x-small);
font-weight: var(--font-weight-regular);
white-space: nowrap;
}
.home-session-group-header::before {
content: "";
position: absolute;
top: -12px;
left: 0;
width: 100%;
height: 12px;
background: var(--v2-background-bg-base);
}
.home-session-group-header::after {
content: "";
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 16px;
pointer-events: none;
background: linear-gradient(
180deg,
var(--v2-background-bg-base) 0%,
color-mix(in srgb, var(--v2-background-bg-base) 92.0456%, transparent) 7.93%,
color-mix(in srgb, var(--v2-background-bg-base) 84.9947%, transparent) 14.14%,
color-mix(in srgb, var(--v2-background-bg-base) 78.6813%, transparent) 19%,
color-mix(in srgb, var(--v2-background-bg-base) 72.9394%, transparent) 22.85%,
color-mix(in srgb, var(--v2-background-bg-base) 67.6028%, transparent) 26.05%,
color-mix(in srgb, var(--v2-background-bg-base) 62.5055%, transparent) 28.95%,
color-mix(in srgb, var(--v2-background-bg-base) 57.4815%, transparent) 31.91%,
color-mix(in srgb, var(--v2-background-bg-base) 52.3647%, transparent) 35.27%,
color-mix(in srgb, var(--v2-background-bg-base) 46.989%, transparent) 39.4%,
color-mix(in srgb, var(--v2-background-bg-base) 41.1884%, transparent) 44.65%,
color-mix(in srgb, var(--v2-background-bg-base) 34.7969%, transparent) 51.36%,
color-mix(in srgb, var(--v2-background-bg-base) 27.6484%, transparent) 59.9%,
color-mix(in srgb, var(--v2-background-bg-base) 19.5767%, transparent) 70.62%,
color-mix(in srgb, var(--v2-background-bg-base) 10.416%, transparent) 83.87%,
transparent 100%
);
}
[data-slot="titlebar-update-loader"] {
display: block;
flex-shrink: 0;
margin: 1px;
width: 12px;
height: 12px;
border-radius: 9999px;
border: 2px solid color-mix(in srgb, var(--v2-icon-icon-accent) 30%, transparent);
border-top-color: var(--v2-icon-icon-accent);
animation: titlebar-update-loader-spin 0.67s linear infinite;
transform-origin: 50% 50%;
}
:root[data-motion="reduce"] {
[data-slot="titlebar-update-loader"] {
animation: none;
}
}
@keyframes titlebar-update-loader-spin {
to {
transform: rotate(360deg);
}
}
@keyframes home-projects-fade-top {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@keyframes session-dropzone-enter {
from {
opacity: 0;
}
}
@keyframes session-dropzone-content-enter {
from {
opacity: 0;
transform: translateY(4px) scale(0.96);
}
}
@keyframes session-dropzone-upload-enter {
from {
opacity: 0;
transform: translateY(4px) scale(0.92);
}
}
@keyframes session-dropzone-stripes-drift {
to {
background-position: 33.941px 0;
}
}
[data-component="session-dropzone"][data-visible="true"] {
animation: session-dropzone-enter 200ms cubic-bezier(0.215, 0.61, 0.355, 1);
}
[data-component="session-dropzone"][data-visible="true"] [data-slot="session-dropzone-content"] {
animation: session-dropzone-content-enter 200ms cubic-bezier(0.215, 0.61, 0.355, 1);
}
[data-component="session-dropzone"][data-visible="true"] [data-slot="session-dropzone-upload"] {
animation: session-dropzone-upload-enter 240ms cubic-bezier(0.215, 0.61, 0.355, 1);
}
[data-component="session-dropzone"][data-visible="true"] [data-slot="session-dropzone-stripes"] {
animation: session-dropzone-stripes-drift 3s linear infinite;
}
[data-component="session-dropzone"] {
--session-dropzone-wash: 4%;
--session-dropzone-stripe: 7%;
--session-dropzone-card: var(--v2-background-bg-base);
}
[data-color-scheme="dark"] [data-component="session-dropzone"] {
--session-dropzone-wash: 6%;
--session-dropzone-stripe: 14%;
--session-dropzone-card: var(--v2-background-bg-layer-01);
}
[data-component="timeline-quote"] {
background-color: var(--v2-background-bg-base);
}
[data-color-scheme="dark"] [data-component="timeline-quote"] {
background-color: var(--v2-background-bg-layer-02);
}
:root[data-motion="reduce"] {
[data-component="session-dropzone"][data-visible="true"],
[data-component="session-dropzone"][data-visible="true"] [data-slot="session-dropzone-content"],
[data-component="session-dropzone"][data-visible="true"] [data-slot="session-dropzone-upload"],
[data-component="session-dropzone"][data-visible="true"] [data-slot="session-dropzone-stripes"] {
animation: none;
}
}
/* A mask fades the rows themselves, so the edges work over any background, including the dropdown's. */
[data-slot="home-projects-viewport"][data-fade-top] {
--mask-start: 16px;
}
[data-slot="home-projects-viewport"][data-fade-bottom] {
--mask-end: 16px;
}
[data-slot="home-projects-viewport"]:is([data-fade-top], [data-fade-bottom]) {
-webkit-mask-image: linear-gradient(
to bottom,
transparent,
black var(--mask-start, 0px),
black calc(100% - var(--mask-end, 0px)),
transparent
);
mask-image: linear-gradient(
to bottom,
transparent,
black var(--mask-start, 0px),
black calc(100% - var(--mask-end, 0px)),
transparent
);
}
[data-slot="manage-models-scroll"] {
timeline-scope: --manage-models-scroll;
}
[data-slot="manage-models-scroll"]::before {
content: "";
position: absolute;
left: 0;
right: 0;
z-index: 10;
height: 16px;
pointer-events: none;
visibility: hidden;
}
[data-slot="manage-models-scroll"]::before {
top: 0;
background: linear-gradient(to bottom, var(--v2-background-bg-base), transparent);
}
@supports (animation-timeline: --manage-models-scroll) and (timeline-scope: --manage-models-scroll) {
[data-slot="manage-models-scroll"] .settings-panel {
scroll-timeline: --manage-models-scroll y;
}
[data-slot="manage-models-scroll"]::before {
animation: home-projects-fade-top linear both;
animation-timeline: --manage-models-scroll;
animation-range: 0 0.1px;
}
}
:root body [data-slot="session-turn-diffs-header"] {
height: 24px;
padding-block: 0;
}
}