@import 'tailwindcss';

@custom-variant dark (&:is(.dark *));

/* ── Self-hosted type (cyberspace terminal aesthetic) ── */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/JetBrainsMono-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/JetBrainsMono-Bold.woff2') format('woff2');
}
@font-face {
  font-family: 'VT323';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/VT323-Regular.woff2') format('woff2');
}

/* bits-ui components (Slider, and any future orientation/disabled-aware
   primitive) style themselves via shorthand data-* variants that Tailwind
   v4 doesn't ship — it only auto-generates variants for bare boolean data
   attributes (data-disabled), not attribute=value pairs like
   data-orientation="horizontal". Without these, e.g. Slider's track silently
   collapses to 0 height (no h-1.5 class survives), leaving only the thumb
   visible with no visible rail. */
@custom-variant data-horizontal (&[data-orientation='horizontal']);
@custom-variant data-vertical (&[data-orientation='vertical']);
@custom-variant data-disabled (&[data-disabled]);

@theme inline {
  --font-sans: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --font-heading: 'JetBrains Mono', ui-monospace, Menlo, monospace;
  /* Square corners across the whole radius scale (--radius is pinned to 0
     by both themes below). Kept as a 4-step scale so any future softer theme
     can relax just --radius and get graded corners back for free. */
  --radius-sm: var(--radius);
  --radius-md: var(--radius);
  --radius-lg: var(--radius);
  --radius-xl: var(--radius);
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-success: var(--success);
  --color-warning: var(--warning);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --color-sidebar: var(--sidebar);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-ring: var(--sidebar-ring);
  --color-chart-1: var(--chart-1);
  --color-chart-2: var(--chart-2);
  --color-chart-3: var(--chart-3);
  --color-chart-4: var(--chart-4);
  --color-chart-5: var(--chart-5);
}

/* ── Cyberspace Light (black ink on warm cream paper) ──
   Ported from cyberspace.online's 3-color model (fg/bg/fgDim). Light and
   dark are exact inverses of the same cream (#efe5c0). Emphasis is by
   inversion (primary = fg ink), borders are fg-derived hairlines, and the
   radius is 0 so every surface is square. */
:root {
  --radius: 0px;
  --background: #efe5c0;
  --foreground: #000000;
  --card: #efe5c0;
  --card-foreground: #000000;
  --popover: #efe5c0;
  --popover-foreground: #000000;
  --primary: #000000;
  --primary-foreground: #efe5c0;
  --secondary: #e0d6b0;
  --secondary-foreground: #000000;
  --muted: #e6dcc0;
  --muted-foreground: #3a3a3a;
  --accent: #000000;
  --accent-foreground: #efe5c0;
  --destructive: #9d0006;
  --destructive-foreground: #efe5c0;
  --border: color-mix(in oklab, #000000 22%, transparent);
  --input: color-mix(in oklab, #000000 30%, transparent);
  --ring: #000000;
  --chart-1: #000000;
  --chart-2: #3a3a3a;
  --chart-3: #b57614;
  --chart-4: #79740e;
  --chart-5: #076678;
  --sidebar: #efe5c0;
  --sidebar-foreground: #000000;
  --sidebar-primary: #000000;
  --sidebar-primary-foreground: #efe5c0;
  --sidebar-accent: #e0d6b0;
  --sidebar-accent-foreground: #000000;
  --sidebar-border: color-mix(in oklab, #000000 22%, transparent);
  --sidebar-ring: #000000;
  --success: #79740e;
  --warning: #b57614;

  --bg: var(--background);
  --bg-surface: var(--card);
  --bg-deeper: #e6dcc0;
  --bg-hover: var(--secondary);
  --bg-active: var(--accent);
  --text: var(--foreground);
  --text-muted: var(--muted-foreground);
  --accent-blue: #076678;
  --accent-green: var(--success);
  --accent-red: var(--destructive);
  --accent-orange: var(--warning);
}

/* ── Cyberspace Dark (warm cream on black) — exact inverse of Light ── */
.dark {
  --radius: 0px;
  --background: #000000;
  --foreground: #efe5c0;
  --card: #000000;
  --card-foreground: #efe5c0;
  --popover: #000000;
  --popover-foreground: #efe5c0;
  --primary: #efe5c0;
  --primary-foreground: #000000;
  --secondary: #1a1a1a;
  --secondary-foreground: #efe5c0;
  --muted: #141414;
  --muted-foreground: #a89984;
  --accent: #efe5c0;
  --accent-foreground: #000000;
  --destructive: #cc241d;
  --destructive-foreground: #efe5c0;
  --border: color-mix(in oklab, #efe5c0 22%, transparent);
  --input: color-mix(in oklab, #efe5c0 30%, transparent);
  --ring: #efe5c0;
  --chart-1: #efe5c0;
  --chart-2: #a89984;
  --chart-3: #fabd2f;
  --chart-4: #b8bb26;
  --chart-5: #83a598;
  --sidebar: #000000;
  --sidebar-foreground: #efe5c0;
  --sidebar-primary: #efe5c0;
  --sidebar-primary-foreground: #000000;
  --sidebar-accent: #1a1a1a;
  --sidebar-accent-foreground: #efe5c0;
  --sidebar-border: color-mix(in oklab, #efe5c0 22%, transparent);
  --sidebar-ring: #efe5c0;
  --success: #b8bb26;
  --warning: #fabd2f;

  --bg: var(--background);
  --bg-surface: var(--card);
  --bg-deeper: #050505;
  --bg-hover: var(--secondary);
  --bg-active: var(--accent);
  --text: var(--foreground);
  --text-muted: var(--muted-foreground);
  --accent-blue: #83a598;
  --accent-green: var(--success);
  --accent-red: var(--destructive);
  --accent-orange: var(--warning);
}

/* Terminal-style block cursor — outside @layer so it overrides CodeMirror */
.cm-cursor,
.cm-cursor-primary {
  border-left-color: var(--primary) !important;
  border-left-width: 0.5em !important;
}

@layer base {
  * {
    @apply border-border outline-ring/50;
  }

  html,
  body {
    @apply bg-background text-foreground;
    height: 100%;
    font-size: 15px;
    line-height: 1.4;
    -webkit-font-smoothing: antialiased;
  }

  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    font-family: var(--font-heading);
  }

  ::selection {
    background: var(--primary);
    color: var(--primary-foreground);
  }

  .cm-content {
    background: var(--background);
  }

  /* Theme-aware scrollbars */
  * {
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
  }

  *::-webkit-scrollbar {
    width: 6px;
    height: 6px;
  }

  *::-webkit-scrollbar-track {
    background: transparent;
  }

  *::-webkit-scrollbar-thumb {
    background: var(--border);
    border-radius: 3px;
  }

  *::-webkit-scrollbar-thumb:hover {
    background: var(--primary);
  }

  *::-webkit-scrollbar-corner {
    background: transparent;
  }

  /* Pointer cursor on all interactive elements */
  button:not(:disabled),
  [role='button']:not([aria-disabled='true']),
  a[href],
  summary,
  select {
    cursor: pointer;
  }

  a,
  [role='link'],
  [role='tab'],
  [role='option'],
  [data-slot='popover-trigger'],
  [data-slot='toggle-group-item'],
  [data-slot='alert-dialog-action'],
  [data-slot='alert-dialog-cancel'],
  .cm-tooltip-autocomplete [role='option'] {
    cursor: pointer;
  }

  [data-slot='table-container'] {
    border: none;
    box-shadow: none;
  }
}

#app {
  height: 100%;
}

/* wmkit floating windows (EntityDesktop.svelte) — mapped onto the app's own
   card/border/ring tokens instead of an imported wmkit theme, so windows
   follow the terracotta/dark theme toggle for free. */
[data-wm-desktop] {
  overflow: visible;
}

[data-wm-window] {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  pointer-events: auto;
  background: var(--card);
  color: var(--card-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  /* Hard offset shadow (DOS-style), not a soft drop shadow — keeps the
     border-driven system and still separates stacked windows, which matters
     because --card now equals the desktop background. */
  box-shadow: 3px 3px 0 0 var(--border);
  overflow: hidden;
  outline: none;
}

[data-wm-window][data-wm-focused] {
  border-color: var(--ring);
  box-shadow: 3px 3px 0 0 var(--ring);
}

[data-wm-window][data-wm-dragging],
[data-wm-window][data-wm-resizing] {
  user-select: none;
}

[data-wm-window][data-wm-stage='minimized'] {
  display: none;
}

[data-wm-resize] {
  position: absolute;
}

a {
  color: var(--accent-blue);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* svelte-splitpanes theming (TaskContextPanel, SessionChatWindow rail) —
   mapped onto the app's border/primary tokens instead of the library's
   default-theme, so splitters follow the terracotta/dark theme toggle. */
.splitpanes.oikos-theme .splitpanes__pane {
  background: transparent;
}

.splitpanes.oikos-theme .splitpanes__splitter {
  background-color: transparent;
  transition: background-color 0.15s;
}

.splitpanes.oikos-theme .splitpanes__splitter:hover,
.splitpanes.oikos-theme .splitpanes__splitter.splitpanes__splitter__active {
  background-color: color-mix(in oklab, var(--primary) 30%, transparent);
}

.oikos-theme.splitpanes--horizontal > .splitpanes__splitter {
  height: 6px;
  border-bottom: 1px solid var(--border);
  cursor: row-resize;
}

.oikos-theme.splitpanes--vertical > .splitpanes__splitter {
  width: 6px;
  border-left: 1px solid var(--border);
  cursor: col-resize;
}

/* Base markdown rendering — used by every {@html marked.parse(...)} output
   (EntityDetailContent, the Knowledge wiki's WikiReader, and as the
   foundation ChatThread's fuller "Art Nouveau" chat styling builds on top
   of). Global rather than a per-component <style> block: Svelte scopes
   <style> to one component, so three separate copies of this same ~50-line
   ruleset had accumulated (EntityDetailContent's copy was already a
   documented "can't share, Svelte scopes styles" duplicate of ChatThread's,
   and WikiReader added a third when the Knowledge wiki was built). Anything
   that renders sanitized markdown into an .markdown-body container gets
   this for free; a component only needs its own <style> block for looks
   that genuinely diverge from this baseline (see ChatThread.svelte's
   trimmed-down block for the pattern: same class, only the deltas kept,
   using a two-class selector so its overrides win on specificity rather
   than depending on <style> injection order).
   Includes explicit list-style-type — Tailwind's preflight reset (@import
   'tailwindcss' above) strips it from every <ul>/<ol>, so without this,
   markdown bullet/numbered lists silently render with no markers. */
.markdown-body p {
  margin: 0 0 0.5rem;
}
.markdown-body p:last-child {
  margin-bottom: 0;
}
.markdown-body ul,
.markdown-body ol {
  margin: 0 0 0.5rem;
  padding-left: 1.25rem;
}
.markdown-body ul {
  list-style-type: disc;
}
.markdown-body ol {
  list-style-type: decimal;
}
.markdown-body li {
  margin-bottom: 0.125rem;
}
.markdown-body code {
  background: var(--muted);
  border-radius: 4px;
  padding: 0.1em 0.35em;
  font-family: var(--font-mono);
  font-size: 0.85em;
}
.markdown-body pre {
  background: var(--muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.625rem 0.75rem;
  overflow-x: auto;
  margin: 0 0 0.5rem;
}
.markdown-body pre code {
  background: none;
  padding: 0;
  font-size: 0.8125rem;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3 {
  font-weight: 600;
  margin: 0.75rem 0 0.375rem;
  font-size: 1em;
}
.markdown-body table {
  border-collapse: collapse;
  margin: 0 0 0.5rem;
  font-size: 0.8125rem;
}
.markdown-body th,
.markdown-body td {
  border: 1px solid var(--border);
  padding: 0.25rem 0.5rem;
  text-align: left;
}
.markdown-body blockquote {
  border-left: 3px solid var(--border);
  padding-left: 0.75rem;
  color: var(--muted-foreground);
  margin: 0 0 0.5rem;
}
.markdown-body a {
  color: var(--primary);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
}
.markdown-body a:hover {
  text-decoration-style: solid;
}

/* ── cyberspace idioms (work in any theme; idiomatic for the terminal look) ── */

/* Pixel/terminal display face for stylized wordmarks & hero titles. Maps to
   VT323 when available, JetBrains Mono fallback. Headings use --font-heading
   (JetBrains Mono) by default; opt into this per-element for the "de-imagined"
   title voice. */
.font-vt {
  font-family: 'VT323', var(--font-mono);
  letter-spacing: 0.02em;
}

/* Bordered square card with a 2px fg focus ring — the universal cyberspace
   surface. Use on any container that wants the terminal-box look. */
.terminal-box {
  border: 1px solid var(--border);
  border-radius: 0;
}
.terminal-box:focus-within {
  box-shadow: 0 0 0 2px var(--ring);
}

/* ════════════════════════════════════════════════════════════════════════
   TERMINAL DESIGN SYSTEM — cyberspace.online adoption
   These rules are UNLAYERED (written after Tailwind's @layer utilities),
   so they override utility classes — shadow-*, ring-*, rounded-* — on the
   shadcn data-slot primitives regardless of specificity. The system is:
     • border-driven   — hairline borders separate surfaces; no soft shadows
     • square          — every corner is 0 (also enforced via --radius tokens)
     • focus by color  — :focus signals via border/text color, not glow rings
     • DOS modals      — dialogs get a double fg-line frame + hatched corner
   ════════════════════════════════════════════════════════════════════════ */
:root {
  --dos-border: 1px; /* DOS frame line width (used doubled for the modal edge) */
  --dos-dither: 4px; /* hatch tile size for the modal corner shadow */
  --dos-offset: 7px; /* how far the hatched corner sits out from the frame */
}

/* ── Containers → terminal-box: solid hairline border, square, no shadow.
   Replaces shadcn's `shadow-xs ring-1 ring-foreground/10 rounded-xl/md`. ── */
[data-slot='card'],
[data-slot='popover-content'],
[data-slot='hover-card-content'],
[data-slot='dropdown-menu-content'],
[data-slot='select-content'],
[data-slot='tooltip-content'],
[data-slot='sheet-content'],
[data-slot='menubar-content'],
[data-slot='alert-dialog-content'] {
  border: 1px solid var(--border);
  border-radius: 0;
  box-shadow: none;
}

/* ── Dialogs → the DOS frame. A 1px fg border, then a bg gap, then a 1px fg
   ring (two stacked box-shadows) = the double-line terminal window edge. ── */
[data-slot='dialog-content'] {
  position: fixed;
  border: var(--dos-border) solid var(--foreground);
  border-radius: 0;
  box-shadow:
    0 0 0 var(--dos-border) var(--background),
    0 0 0 calc(var(--dos-border) * 2) var(--foreground);
}
/* Hatched corner shadow (fg-dim 45° checks) bottom-right — the DOS window
   tell. Clipped to a small square outside the frame. */
[data-slot='dialog-content']::after {
  content: '';
  position: absolute;
  right: calc(-1 * var(--dos-offset));
  bottom: calc(-1 * var(--dos-offset));
  width: var(--dos-offset);
  height: var(--dos-offset);
  pointer-events: none;
  background-color: var(--muted-foreground);
  background-image:
    linear-gradient(
      45deg,
      var(--background) 25%,
      transparent 25%,
      transparent 75%,
      var(--background) 75%
    ),
    linear-gradient(
      45deg,
      var(--background) 25%,
      transparent 25%,
      transparent 75%,
      var(--background) 75%
    );
  background-size: var(--dos-dither) var(--dos-dither);
  background-position:
    0 0,
    calc(var(--dos-dither) / 2) calc(var(--dos-dither) / 2);
}

/* ── Overlays: opaque-ish theme background, no blur (terminal, not glass). ── */
[data-slot='dialog-overlay'],
[data-slot='alert-dialog-overlay'],
[data-slot='sheet-overlay'] {
  background-color: color-mix(in oklab, var(--background) 82%, transparent);
  backdrop-filter: none;
}

/* ── Inputs: square, no resting shadow; focus = solid fg border (cyberspace
   signals focus by border color, not a glow ring). ── */
[data-slot='input'],
[data-slot='textarea'] {
  border-radius: 0;
  box-shadow: none;
}
[data-slot='input']:focus,
[data-slot='input']:focus-visible,
[data-slot='textarea']:focus,
[data-slot='textarea']:focus-visible {
  border-color: var(--foreground);
  box-shadow: none;
  outline: none;
}

/* ── Buttons: square, no resting shadow. Focus keeps the cva border-color
   shift to fg (focus-visible:border-ring) rather than a ring. ── */
[data-slot='button'] {
  border-radius: 0;
  box-shadow: none;
}

/* ── Badges & tabs: square. ── */
[data-slot='badge'] {
  border-radius: 0;
}
[data-slot='tabs-trigger'],
[data-slot='tabs-list'] {
  border-radius: 0;
}

/* ── Window controls (titlebar minimize/maximize/close + taskbar item close).
   ONE style across all window chrome: bordered square, invert on hover — the
   same idiom as desktop icons and taskbar buttons. Close is intentionally not
   "danger"-colored so every control reads as the same component. ── */
.win-ctrl {
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  background: var(--background);
  color: var(--muted-foreground);
  transition:
    color 0.12s,
    border-color 0.12s,
    background 0.12s;
}
.win-ctrl:hover {
  border-color: var(--foreground);
  background: var(--foreground);
  color: var(--background);
}

/* Pin every window titlebar to one exact height, targeted by attribute so it
   holds for every window regardless of its titlebar classes — including
   already-open wmkit windows whose titlebar markup can lag behind on HMR
   (component HMR is unreliable for wmkit windows; CSS HMR is not).
   `flex: 0 0 2.25rem` is the strongest guarantee a flex item won't grow or
   shrink — it stops a scrolling/growing content pane from compressing the
   titlebar (the chat-window symptom). */
[data-wm-drag] {
  flex: 0 0 2.25rem !important;
}
