SPB Git

Repository Public

globals.css 10.7 KB 375 lines css

1@import 'tailwindcss';23/*4 * Design tokens. `@theme` holds the LIGHT theme (the default, also what renders before any5 * script runs); `[data-theme='dark']` overrides the same variables. `data-theme` is set on6 * <html> by /theme-init.js (blocking, same-origin) and by the theme store.7 * Text-capable tokens (text, text-2, muted, accent, success, warning, error, coral-ink) meet8 * WCAG AA on bg/surface/surface-2 in both themes — verified by dev/check-contrast.mjs.9 * `*-vivid` tokens are for fills (dots, bars, rings), never for text.10 */11/*12 * Symbols for the terminal. The bundled @fontsource subsets omit box drawing, block elements,13 * arrows, braille (spinners) and dingbats, which Claude Code's UI uses; without these faces14 * they would come from a fallback font with different metrics (gaps in frames on the DOM15 * renderer). The full font files are only downloaded when such a character is displayed.16 */17@font-face {18  font-family: 'JetBrains Mono';19  font-style: normal;20  font-weight: 400;21  font-display: swap;22  src: url('../../node_modules/jetbrains-mono/fonts/webfonts/JetBrainsMonoNL-Regular.woff2') format('woff2');23  unicode-range: U+2190-21FF, U+2200-22FF, U+2300-23FF, U+2500-259F, U+25A0-25FF, U+2600-26FF, U+2700-27BF, U+2800-28FF, U+2B00-2BFF, U+E0A0-E0B3;24}25@font-face {26  font-family: 'JetBrains Mono';27  font-style: normal;28  font-weight: 700;29  font-display: swap;30  src: url('../../node_modules/jetbrains-mono/fonts/webfonts/JetBrainsMonoNL-Bold.woff2') format('woff2');31  unicode-range: U+2190-21FF, U+2200-22FF, U+2300-23FF, U+2500-259F, U+25A0-25FF, U+2600-26FF, U+2700-27BF, U+2800-28FF, U+2B00-2BFF, U+E0A0-E0B3;32}3334@theme {35  --color-bg: #f7f6f3;36  --color-surface: #ffffff;37  --color-surface-2: #f2f1ed;38  --color-elevated: #ffffff;39  --color-text: #17181c;40  --color-text-2: #555b69;41  --color-muted: #626876;42  --color-faint: #8e94a3;43  --color-accent: #5151e8;44  --color-accent-2: #8b5cf6;45  --color-accent-fg: #ffffff;46  /* Brand gradient stops (mark, primary CTA, phone home header) + ink for text on a white pill over it. */47  --color-brand-1: #5b5bf0;48  --color-brand-2: #8b5cf6;49  --color-brand-3: #ff7a59;50  --color-brand-ink: #3f3fd6;51  --color-coral: #ff7a59;52  --color-coral-ink: #b03e1c;53  --color-success: #0c7049;54  --color-warning: #805800;55  --color-error: #bf2c34;56  --color-success-vivid: #1fa971;57  --color-warning-vivid: #e0a100;58  --color-error-vivid: #e5484d;59  --color-line: #0000000f;60  --color-line-2: #00000017;61  --color-line-3: #0000002e;62  --color-card-line: #0000000a;63  --color-hover: #0000000a;64  --color-scrim: #17182059;65  --color-term-bg: #fcfcfa;66  --radius-sm: 10px;67  --radius-md: 16px;68  --radius-lg: 22px;69  --shadow-card: 0 1px 2px #1718200a, 0 4px 14px -6px #1718201a;70  --shadow-float: 0 2px 6px #1718200f, 0 12px 32px -10px #17182033;71  --shadow-pop: 0 4px 12px #17182014, 0 24px 56px -16px #17182047;72  --font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, -apple-system, 'Helvetica Neue', sans-serif;73  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;74  --ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);75  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);76}7778[data-theme='dark'] {79  --color-bg: #080b10;80  --color-surface: #10151d;81  --color-surface-2: #161d27;82  --color-elevated: #1d2632;83  --color-text: #f4f7fb;84  --color-text-2: #a1adbd;85  --color-muted: #8492a6;86  --color-faint: #5d6a7d;87  --color-accent: #8f8fff;88  --color-accent-2: #b08cff;89  --color-accent-fg: #0a0a1f;90  --color-coral: #ff8f73;91  --color-coral-ink: #ff9d85;92  --color-success: #42c995;93  --color-warning: #e7b86b;94  --color-error: #f08080;95  --color-success-vivid: #42c995;96  --color-warning-vivid: #e7b86b;97  --color-error-vivid: #ed7777;98  --color-line: #ffffff0f;99  --color-line-2: #ffffff17;100  --color-line-3: #ffffff2b;101  --color-card-line: #ffffff14;102  --color-hover: #ffffff12;103  --color-scrim: #00000099;104  --color-term-bg: #080b10;105  --shadow-card: 0 1px 2px #00000040;106  --shadow-float: 0 8px 24px -8px #000000a6;107  --shadow-pop: 0 16px 48px -12px #000000cc;108  color-scheme: dark;109}110111/*112 * Codex instance (<html data-agent="codex">, set before paint by /theme-init.js from the cached113 * branding and confirmed by the branding store once /auth/status answered). Same neutrals and114 * status colours; only the accent family changes: emerald → teal → cyan instead of indigo → violet115 * → coral. Both blocks are checked by dev/check-contrast.mjs like the default tokens.116 */117html[data-agent='codex'] {118  --color-accent: #0b7268;119  --color-accent-2: #0891b2;120  --color-accent-fg: #ffffff;121  --color-brand-1: #047857;122  --color-brand-2: #0d9488;123  --color-brand-3: #0891b2;124  --color-brand-ink: #0a6b60;125}126html[data-agent='codex'][data-theme='dark'] {127  --color-accent: #2dd4bf;128  --color-accent-2: #22d3ee;129  --color-accent-fg: #04201c;130}131132@layer base {133  html {134    color-scheme: light;135  }136  html,137  body {138    height: 100%;139    background: var(--color-bg);140    color: var(--color-text);141    -webkit-text-size-adjust: 100%;142    overscroll-behavior: none;143  }144  body {145    font-family: var(--font-sans);146    font-size: 13px;147    line-height: 1.5;148    -webkit-font-smoothing: antialiased;149    -webkit-tap-highlight-color: transparent;150    font-feature-settings: 'ss01', 'cv11';151  }152  *,153  ::before,154  ::after {155    border-color: var(--color-line-2);156  }157  :focus-visible {158    outline: 2px solid var(--color-accent);159    outline-offset: 1px;160  }161  ::selection {162    background: color-mix(in srgb, var(--color-accent) 30%, transparent);163  }164  button {165    cursor: pointer;166  }167  button:disabled {168    cursor: not-allowed;169  }170  /* Real inputs never go below 16px on touch devices: iOS zooms the page otherwise. */171  @media (pointer: coarse) {172    input,173    textarea,174    select {175      font-size: 16px !important;176    }177  }178  * {179    scrollbar-width: thin;180    scrollbar-color: var(--color-line-3) transparent;181  }182}183184@layer components {185  /* Elevated surface: soft layered shadow in light, hairline in dark. */186  .card {187    background: var(--color-surface);188    border: 1px solid var(--color-card-line);189    border-radius: var(--radius-md);190    box-shadow: var(--shadow-card);191  }192  /* Brand gradient: mark, primary call to action, phone home header, activity accents only. */193  .bg-brand {194    background-image: linear-gradient(135deg, var(--color-brand-1) 0%, var(--color-brand-2) 58%, var(--color-brand-3) 135%);195    color: #fff;196  }197  .text-brand {198    background-image: linear-gradient(120deg, var(--color-accent) 0%, var(--color-accent-2) 60%, var(--color-coral) 120%);199    -webkit-background-clip: text;200    background-clip: text;201    color: transparent;202  }203  html[data-agent='codex'] .text-brand {204    background-image: linear-gradient(120deg, var(--color-accent) 0%, var(--color-accent-2) 100%);205  }206  /* Product names in the static HTML are the default product: hidden until the branding store took over. */207  html[data-agent='codex']:not([data-brand-ready]) [data-brand-text] {208    visibility: hidden;209  }210  .pressable {211    transition: transform 140ms var(--ease-out), box-shadow 140ms var(--ease-out);212  }213  .pressable:active {214    transform: scale(0.97);215  }216  /* Skeleton / indeterminate shimmer (never a fake percentage). */217  .shimmer {218    background-image: linear-gradient(100deg, transparent 20%, color-mix(in srgb, var(--color-text) 9%, transparent) 50%, transparent 80%);219    background-size: 200% 100%;220    animation: cr-shimmer 1.4s linear infinite;221  }222  .shimmer-accent {223    background-image: linear-gradient(100deg, transparent 0%, var(--color-accent) 45%, var(--color-accent-2) 55%, transparent 100%);224    background-size: 220% 100%;225    animation: cr-shimmer 1.6s linear infinite;226  }227  .glass {228    background: color-mix(in srgb, var(--color-surface) 78%, transparent);229    -webkit-backdrop-filter: saturate(1.6) blur(18px);230    backdrop-filter: saturate(1.6) blur(18px);231  }232  .tnum {233    font-variant-numeric: tabular-nums;234  }235  .app-viewport {236    /* Height is driven by window.visualViewport (see useVisualViewport); 100dvh is the fallback. */237    height: var(--vvh, 100dvh);238  }239  .pt-safe {240    padding-top: env(safe-area-inset-top);241  }242  .pb-safe {243    padding-bottom: env(safe-area-inset-bottom);244  }245  .px-safe {246    padding-left: env(safe-area-inset-left);247    padding-right: env(safe-area-inset-right);248  }249  .no-scrollbar {250    scrollbar-width: none;251  }252  .no-scrollbar::-webkit-scrollbar {253    display: none;254  }255}256257/* xterm: the helper textarea must never trigger iOS focus-zoom nor show a caret. */258.xterm .xterm-helper-textarea {259  font-size: 16px !important;260  opacity: 0 !important;261  caret-color: transparent;262}263.xterm {264  height: 100%;265  touch-action: none;266  font-variant-ligatures: none; /* a terminal shows => as two cells, not a ligature */267}268.xterm .xterm-scrollable-element > .scrollbar.vertical,269.xterm .xterm-scrollable-element > .scrollbar.vertical > .slider {270  width: 6px !important;271  border-radius: 3px;272}273.xterm .xterm-scrollable-element > .scrollbar.vertical {274  right: 2px !important;275}276.xterm .xterm-viewport {277  background-color: transparent !important;278}279280@keyframes cr-fade-in {281  from {282    opacity: 0;283  }284}285@keyframes cr-pop-in {286  from {287    opacity: 0;288    transform: translateY(4px) scale(0.985);289  }290}291@keyframes cr-slide-right {292  from {293    transform: translateX(100%);294  }295}296@keyframes cr-slide-left {297  from {298    transform: translateX(-100%);299  }300}301@keyframes cr-slide-up {302  from {303    transform: translateY(100%);304  }305}306@keyframes cr-shimmer {307  from {308    background-position: 120% 0;309  }310  to {311    background-position: -120% 0;312  }313}314@keyframes cr-ping {315  0% {316    transform: scale(1);317    opacity: 0.55;318  }319  100% {320    transform: scale(2.6);321    opacity: 0;322  }323}324@keyframes cr-draw {325  to {326    stroke-dashoffset: 0;327  }328}329@keyframes cr-pulse {330  50% {331    opacity: 0.45;332  }333}334.anim-fade {335  animation: cr-fade-in 140ms var(--ease-out);336}337.anim-pop {338  animation: cr-pop-in 160ms var(--ease-out);339}340.anim-slide-right {341  animation: cr-slide-right 200ms var(--ease-out);342}343.anim-slide-left {344  animation: cr-slide-left 200ms var(--ease-out);345}346.anim-slide-up {347  animation: cr-slide-up 200ms var(--ease-out);348}349.anim-ping {350  animation: cr-ping 1.8s var(--ease-out) infinite;351}352.anim-draw {353  stroke-dasharray: 1;354  stroke-dashoffset: 1;355  animation: cr-draw 420ms 80ms var(--ease-out) forwards;356}357/* Cross-fade while the theme changes (class added for ~300 ms by the theme store). */358html.theme-fade,359html.theme-fade * {360  transition: background-color 260ms ease, border-color 260ms ease, color 200ms ease, fill 200ms ease, box-shadow 260ms ease !important;361}362.anim-pulse {363  animation: cr-pulse 1.6s ease-in-out infinite;364}365@media (prefers-reduced-motion: reduce) {366  *,367  ::before,368  ::after {369    animation-duration: 1ms !important;370    animation-iteration-count: 1 !important;371    transition-duration: 1ms !important;372    scroll-behavior: auto !important;373  }374}375
Files main
Menu

Theme