typeduck-codex-web 0.5.0

A standalone browser interface and Codex runtime
Documentation
/* Neutral, the built-in Topcoat theme.

   The theme is a small set of design tokens. Components refer to tokens only,
   never to raw colors, so a project restyles itself by editing the values in
   `:root` and `.dark` below.

     --background              the page background
     --foreground              text and iconography on the background
     --muted-foreground        secondary text: captions, descriptions, placeholders
     --primary                 the emphasis color: primary actions, selection, highlights
     --primary-foreground      text on a primary-filled surface
     --destructive             destructive actions and error states
     --destructive-foreground  text on a destructive-filled surface
     --border                  hairline borders and dividers
     --ring                    the focus ring
     --shadow-xs               a subtle shadow for controls: buttons, inputs
     --shadow-sm               a shadow for raised surfaces: cards, menus

   Interactive states (hover, press) have no tokens of their own: components
   derive them by applying the fill or foreground color at reduced opacity,
   which adapts to both color schemes automatically.

   The Geist font is not bundled here; provide it with topcoat-font. */

@import "tailwindcss";

/* Scan the project's Rust sources for the Tailwind classes they use. This
   file is installed at the project root, so `./src` is the crate's source. */
@source "./src/**/*.rs";
@source "./assets/*.js";

/* Dark mode is opted into by putting the `dark` class on an ancestor,
   typically <html>. */
@custom-variant dark (&:is(.dark *));

/* Expose the tokens as Tailwind utilities (`bg-background`, `text-primary`,
   `border-border`, ...). The indirection through plain variables on `:root`
   and `.dark` is what lets the values swap when the color scheme changes. */
@theme inline {
  --font-sans: "Geist", sans-serif;
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-muted-foreground: var(--muted-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-border: var(--border);
  --color-ring: var(--ring);
  --shadow-xs: var(--shadow-xs);
  --shadow-sm: var(--shadow-sm);
}

:root,
.dark {
  --background: oklch(0.17 0.012 260);
  --foreground: oklch(0.93 0.006 260);
  --muted-foreground: oklch(0.68 0.012 260);
  --primary: oklch(0.92 0.008 260);
  --primary-foreground: oklch(0.21 0.015 260);
  --destructive: oklch(0.66 0.18 25);
  --destructive-foreground: oklch(0.14 0.02 25);
  --border: oklch(0.3 0.012 260);
  --ring: oklch(0.6 0.05 260);
  --code-background: oklch(0.205 0.012 260);
  --shadow-xs: 0 1px 2px oklch(0 0 0 / 35%);
  --shadow-sm: 0 1px 2px oklch(0 0 0 / 35%), 0 2px 8px -2px oklch(0 0 0 / 30%);
}

.light {
  --background: oklch(0.992 0.003 250);
  --foreground: oklch(0.235 0.015 255);
  --muted-foreground: oklch(0.52 0.018 255);
  --primary: oklch(0.29 0.025 255);
  --primary-foreground: oklch(0.985 0.004 250);
  --destructive: oklch(0.55 0.2 27);
  --destructive-foreground: oklch(0.99 0.012 27);
  --border: oklch(0.9 0.01 255);
  --ring: oklch(0.62 0.11 245);
  --code-background: oklch(0.965 0.007 255);
  --shadow-xs: 0 1px 2px oklch(0.24 0.01 90 / 12%);
  --shadow-sm:
    0 1px 2px oklch(0.24 0.02 260 / 10%),
    0 2px 8px -2px oklch(0.24 0.02 260 / 9%);
}

@layer base {
  * {
    border-color: var(--border);
  }

  html,
  body {
    height: 100%;
  }

  body {
    margin: 0;
    @apply bg-background font-sans text-foreground;
  }

  button,
  input,
  textarea,
  select {
    font: inherit;
  }

  .prose {
    overflow-wrap: anywhere;
  }

  .prose > :first-child {
    margin-top: 0;
  }

  .prose > :last-child {
    margin-bottom: 0;
  }

  .prose :where(p, ul, ol, blockquote, pre, table, hr) {
    margin: 0 0 1rem;
  }

  .prose :where(h1, h2, h3, h4) {
    margin: 1.5rem 0 0.65rem;
    color: var(--foreground);
    font-weight: 650;
    line-height: 1.3;
    letter-spacing: -0.015em;
  }

  .prose h1 {
    font-size: 1.5rem;
  }

  .prose h2 {
    border-bottom: 1px solid var(--border);
    padding-bottom: 0.35rem;
    font-size: 1.25rem;
  }

  .prose h3 {
    font-size: 1.08rem;
  }

  .prose h4 {
    font-size: 0.95rem;
  }

  .prose :where(ul, ol) {
    padding-left: 1.5rem;
  }

  .prose ul {
    list-style: disc;
  }

  .prose ol {
    list-style: decimal;
  }

  .prose :where(ul, ol) :where(ul, ol) {
    margin: 0.35rem 0;
  }

  .prose li {
    margin: 0.25rem 0;
    padding-left: 0.15rem;
  }

  .prose li::marker {
    color: var(--muted-foreground);
  }

  .prose li > p {
    margin: 0.35rem 0;
  }

  .prose li:has(> input[type="checkbox"]) {
    list-style: none;
  }

  .prose li > input[type="checkbox"] {
    margin: 0 0.5rem 0 -1.35rem;
    accent-color: var(--primary);
  }

  .prose a {
    color: inherit;
    font-weight: 550;
    text-decoration: underline;
    text-decoration-color: color-mix(in oklch, var(--foreground) 35%, transparent);
    text-underline-offset: 0.2em;
  }

  .prose a:hover {
    text-decoration-color: currentColor;
  }

  .prose blockquote {
    border-left: 3px solid var(--border);
    padding: 0.15rem 0 0.15rem 1rem;
    color: var(--muted-foreground);
  }

  .prose blockquote > :last-child {
    margin-bottom: 0;
  }

  .prose code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    font-size: 0.86em;
  }

  .prose :not(pre) > code {
    border: 1px solid var(--border);
    border-radius: 0.35rem;
    background: var(--code-background);
    padding: 0.12rem 0.35rem;
  }

  .prose pre {
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: 0.65rem;
    background: var(--code-background);
    padding: 0.9rem 1rem;
    line-height: 1.55;
  }

  .prose pre code {
    border: 0;
    background: transparent;
    padding: 0;
    font-size: 0.78rem;
  }

  .prose table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    border-collapse: collapse;
    font-size: 0.82rem;
    line-height: 1.5;
  }

  .prose :where(th, td) {
    border: 1px solid var(--border);
    padding: 0.5rem 0.7rem;
    text-align: left;
    white-space: nowrap;
  }

  .prose th {
    background: var(--code-background);
    font-weight: 600;
  }

  .prose hr {
    border: 0;
    border-top: 1px solid var(--border);
  }

  .prose img {
    max-width: 100%;
    border-radius: 0.65rem;
  }

  .prose del {
    color: var(--muted-foreground);
  }

  .raw-transcript article {
    display: block;
    max-width: none;
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    white-space: pre-wrap;
  }

  .raw-transcript details {
    border-radius: 0;
    background: transparent;
  }
}

@keyframes live-progress {
  from { transform: translateX(-120%); }
  to { transform: translateX(420%); }
}

@keyframes live-rail {
  0%, 100% { opacity: 0.35; transform: scaleY(0.65); }
  50% { opacity: 1; transform: scaleY(1); }
}

.live-progress {
  animation: live-progress 1.25s ease-in-out infinite;
}

.live-rail {
  animation: live-rail 1.1s ease-in-out infinite;
  transform-origin: center;
}

.activity-card,
[data-session-link],
#composer {
  transition: border-color 160ms ease, background-color 160ms ease, box-shadow 160ms ease;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}