/* ============================================================
 * v2.css — Lemma v2 tokens, mirroring getcracked.io exactly.
 *
 * Token values lifted from the live cracked stylesheet so any
 * `bg-bg-primary` / `text-text-secondary` / `border-border-primary`
 * arbitrary-value Tailwind class resolves identically to the
 * reference.
 *
 * Scoped to [data-skin="v2"]. Wrap any v2 surface in
 * <div data-skin="v2"> to activate.
 * ============================================================ */

[data-skin="v2"] {
  /* Light-mode tokens (default). Dark variant overrides below. */
  --bg-primary: 255 255 255;        /* #fff */
  --bg-secondary: 245 245 245;      /* #f5f5f5 */
  --bg-tertiary: 229 229 229;       /* #e5e5e5 */

  --text-primary: 10 10 10;         /* #0a0a0a */
  --text-secondary: 115 115 115;    /* #737373 */
  --text-tertiary: 161 161 161;     /* #a1a1a1 */

  --border-primary: 229 229 229;    /* #e5e5e5 */
  --border-secondary: 212 212 212;  /* #d4d4d4 */

  --foreground: 10 10 10;
  --primary: 23 23 23;              /* #171717 */
  --accent: 245 245 245;            /* #f5f5f5 */
  --card: 255 255 255;
  --ring: 161 161 161;

  --success: 36 197 95;             /* #24c55f */
  --destructive: 228 0 20;          /* #e40014 */
  --warning: 228 158 33;            /* #e49e21 */

  --platinum: 98 99 102;            /* #626366 */
  --platinum-sheen: 157 158 160;    /* #9d9ea0 */
  --platinum-light: 127 128 131;    /* #7f8083 */
  --platinum-border: 98 99 102;     /* with /25 opacity in CSS */
  --platinum-grid-line: 34 34 34;   /* with /10 opacity in CSS */
  --platinum-btn-bg: 26 26 28;      /* #1a1a1c — primary CTA bg */
  --platinum-btn-bg-hover: 45 46 48;/* #2d2e30 */
  --platinum-btn-text: 228 228 231; /* #e4e4e7 — primary CTA text */

  /* Code-cell syntax highlighting (notebook editor + read-only blocks).
   * Catppuccin Latte palette — tuned for the light background. */
  --code-keyword: 136 57 239;   /* mauve */
  --code-string: 64 160 43;     /* green */
  --code-number: 254 100 11;    /* peach */
  --code-comment: 140 143 161;  /* overlay (muted) */
  --code-builtin: 30 102 245;   /* blue */
}

/* ============================================================
 * Dark mode — activated by setting `data-theme="dark"` anywhere
 * up the tree (root <html> is recommended). Token names stay the
 * same so component code doesn't have to branch.
 * ============================================================ */
[data-theme="dark"][data-skin="v2"],
[data-theme="dark"] [data-skin="v2"] {
  --bg-primary: 10 10 10;           /* #0a0a0a */
  --bg-secondary: 23 23 23;         /* #171717 */
  --bg-tertiary: 38 38 38;          /* #262626 */

  --text-primary: 250 250 250;      /* #fafafa */
  --text-secondary: 161 161 161;    /* #a1a1a1 */
  --text-tertiary: 115 115 115;     /* #737373 */

  --border-primary: 38 38 38;       /* #262626 */
  --border-secondary: 82 82 82;     /* #525252 */

  --foreground: 250 250 250;
  --primary: 250 250 250;
  --accent: 38 38 38;
  --card: 23 23 23;
  --ring: 115 115 115;

  --platinum-btn-bg: 50 51 53;      /* #323335 */
  --platinum-btn-bg-hover: 71 72 74;/* #47484a */
  --platinum-btn-text: 214 215 217; /* #d6d7d9 */

  /* Code-cell syntax highlighting — Catppuccin Mocha (dark). */
  --code-keyword: 203 166 247;  /* mauve */
  --code-string: 166 227 161;   /* green */
  --code-number: 250 179 135;   /* peach */
  --code-comment: 108 112 134;  /* overlay */
  --code-builtin: 137 180 250;  /* blue */
}

[data-skin="v2"] {

  --radius: 0.625rem;
  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;
  --radius-2xl: 1rem;
  --radius-3xl: 1.5rem;

  --motion-fast: 120ms;
  --motion-med: 200ms;
  --motion-slow: 320ms;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);

  /* Legacy aliases so old v2 components that referenced
     `var(--bg)` / `var(--text)` / `var(--border)` etc. still work. */
  --bg: var(--bg-primary);
  --bg-elev: var(--bg-primary);
  --bg-muted: var(--bg-secondary);
  --text: var(--text-primary);
  --text-muted: var(--text-secondary);
  --text-faint: var(--text-tertiary);
  --border: var(--border-primary);
  --border-strong: var(--border-secondary);
  --accent-hover: var(--platinum-btn-bg-hover);
  --accent-soft: var(--bg-secondary);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 1px 4px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.1);

  font-family: 'Geist Sans', 'Geist', system-ui, -apple-system, sans-serif;
  background-color: rgb(var(--bg-primary));
  color: rgb(var(--text-primary));
  font-feature-settings: 'cv11';
}

/* ============================================================
 * Typography utilities — the three cracked.io text classes.
 * Sizes follow Tailwind 4's text-Nxl scale exactly.
 * ============================================================ */

[data-skin="v2"] .header-text {
  font-family: 'Geist Sans', 'Geist', system-ui, sans-serif;
  font-weight: 500;
  font-size: 2.25rem;         /* text-4xl */
  line-height: 1.1;
  letter-spacing: -0.025em;   /* tracking-tight */
  color: rgb(var(--text-primary));
  text-wrap: balance;
}
@media (min-width: 40rem) {
  [data-skin="v2"] .header-text {
    font-size: 3rem;          /* text-5xl */
    line-height: 1.1;
  }
}
@media (min-width: 64rem) {
  [data-skin="v2"] .header-text {
    font-size: 3.75rem;       /* text-6xl */
    line-height: 1.05;
  }
}

[data-skin="v2"] .secondary-text {
  font-family: 'Geist Sans', 'Geist', system-ui, sans-serif;
  font-size: 0.875rem;        /* text-sm */
  line-height: 1.5;
  color: rgb(var(--text-secondary));
  text-wrap: balance;
}

[data-skin="v2"] .normal-text {
  font-family: 'Geist Sans', 'Geist', system-ui, sans-serif;
  font-size: 0.875rem;        /* text-sm */
  line-height: 1.6;
  color: rgb(var(--text-primary));
  text-wrap: balance;
}

[data-skin="v2"] .v2-mono {
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
  font-feature-settings: 'ss01', 'ss02';
}

/* ============================================================
 * Inline code — `<code>` inside prose, KaTeX, etc. Subtle bg
 * pill so it reads as a token without screaming.
 * ============================================================ */
/* ============================================================
 * Glassy surfaces — used on the sticky top-bar pill and on
 * dropdown panels. Replicates the platinum frosted-glass look.
 * ============================================================ */
[data-skin="v2"] .v2-glass {
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  background-color: rgb(var(--bg-primary) / 0.72);
}

[data-theme="dark"] [data-skin="v2"] .v2-glass {
  background-color: rgb(var(--bg-primary) / 0.6);
}

[data-skin="v2"] .v2-glass-strong {
  backdrop-filter: blur(28px) saturate(180%);
  -webkit-backdrop-filter: blur(28px) saturate(180%);
  background-color: rgb(var(--bg-tertiary) / 0.78);
  border: 1px solid rgb(var(--border-primary));
  box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.16);
}

[data-theme="dark"] [data-skin="v2"] .v2-glass-strong {
  background-color: rgb(var(--bg-tertiary) / 0.7);
  box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.4);
}

/* ============================================================
 * University logo treatment.
 *
 * Light mode: monochrome-on-paper, lightly faded so the wall of
 * logos doesn't fight the rest of the page.
 *
 * Dark mode: invert + grayscale + small brightness lift so dark-ink
 * marks remain legible against the dark canvas (otherwise the SVG/PNG
 * crests render as solid black blocks on a near-black background).
 * ============================================================ */
[data-skin="v2"] .v2-uni-logo {
  filter: grayscale(1) contrast(0.95);
  opacity: 0.78;
}
[data-theme="dark"] [data-skin="v2"] .v2-uni-logo {
  filter: grayscale(1) invert(1) brightness(0.92) contrast(0.95);
  opacity: 0.85;
  mix-blend-mode: normal !important;
}

/* ============================================================
 * Dropdown / menu items — the cracked menu pattern.
 * ============================================================ */
[data-skin="v2"] .v2-menu-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.5rem 0.75rem;
  border-radius: 0.75rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
  color: rgb(var(--text-primary));
  cursor: pointer;
  user-select: none;
  outline: none;
  transition: background-color 120ms var(--ease), color 120ms var(--ease);
  text-align: left;
  background: transparent;
  border: none;
}

[data-skin="v2"] .v2-menu-item:hover,
[data-skin="v2"] .v2-menu-item:focus-visible {
  background-color: rgb(var(--bg-tertiary));
  color: rgb(var(--text-primary));
}

[data-skin="v2"] .v2-menu-item[data-muted="true"] {
  color: rgb(var(--text-tertiary));
}

/* Notebook title field — reads as plain text until hovered/focused, when a
 * border fades in to signal it's editable (mirrors the IDE session name).
 * Native :hover/:focus so it never depends on runtime Tailwind JIT. */
[data-skin="v2"] .nb-title-input {
  border: 1px solid transparent;
  border-radius: 0.5rem;
  transition: border-color 120ms ease, background-color 120ms ease;
}
[data-skin="v2"] .nb-title-input:hover {
  border-color: rgb(var(--border-primary));
}
[data-skin="v2"] .nb-title-input:focus {
  border-color: rgb(var(--border-primary));
  background-color: rgb(var(--bg-secondary));
}

[data-skin="v2"] code,
[data-skin="v2"] .v2-inline-code {
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
  font-size: 0.9em;
  padding: 0.12em 0.45em;
  border-radius: 6px;
  background-color: rgb(var(--bg-secondary));
  color: rgb(var(--text-primary));
  border: 1px solid rgb(var(--border-primary));
  font-feature-settings: 'ss01';
  white-space: nowrap;
}

/* `<pre><code>` blocks shouldn't get the inline pill — they have their own card. */
[data-skin="v2"] pre code,
[data-skin="v2"] pre .v2-inline-code {
  background-color: transparent;
  border: none;
  padding: 0;
  font-size: inherit;
  border-radius: 0;
  /* Inline code uses white-space: nowrap to keep it on one line; pre
   * blocks need the opposite — preserve every newline + indent inside
   * the fenced code. Without this, multiline editorial code renders as
   * a single collapsed line. */
  white-space: pre;
}

/* Force Geist Sans on body text inside the v2 subtree. v1 page
 * components routed into v2 chrome would otherwise inherit Lemma Sans /
 * Inter from --font-body. */
[data-skin="v2"],
[data-skin="v2"] body,
[data-skin="v2"] input,
[data-skin="v2"] textarea,
[data-skin="v2"] select,
[data-skin="v2"] button {
  font-family: 'Geist Sans', 'Geist', system-ui, -apple-system, sans-serif;
}

/* ============================================================
 * Base resets for [data-skin="v2"] subtree.
 * ============================================================ */

[data-skin="v2"] a {
  color: inherit;
  text-decoration: none;
}

[data-skin="v2"] *,
[data-skin="v2"] *::before,
[data-skin="v2"] *::after {
  border-color: rgb(var(--border-primary));
}

[data-skin="v2"] table {
  border-collapse: collapse;
}

[data-skin="v2"] tr {
  border-color: rgb(var(--border-primary));
}

/* ============================================================
 * Motion.
 * ============================================================ */

@keyframes v2-fade-up {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes v2-hero-in {
  from {
    opacity: 0;
    filter: blur(6px);
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: translateY(0);
  }
}

@keyframes v2-fade-slide-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Opacity-only fade for surfaces that need to stay positioned via a
 * static `transform` (e.g. centered nav dropdowns using
 * `translateX(-50%)`). The v2-fade-slide-in keyframe rewrites
 * `transform` so it can't be combined with a custom anchor offset. */
@keyframes v2-fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes v2-draw {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes v2-bar-rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes v2-type-in {
  from {
    opacity: 0;
    transform-origin: left;
    transform: scaleX(0);
  }
  to {
    opacity: 1;
    transform-origin: left;
    transform: scaleX(1);
  }
}

@keyframes v2-blink {
  0%,
  100% {
    opacity: 0.4;
  }
  50% {
    opacity: 1;
  }
}

@keyframes v2-pulse-soft {
  0%,
  100% {
    opacity: 0.75;
    transform: scale(1);
  }
  50% {
    opacity: 1;
    transform: scale(1.03);
  }
}

[data-skin="v2"] .v2-enter {
  animation: v2-fade-up var(--motion-slow) var(--ease) both;
}

[data-skin="v2"] .v2-hero-in {
  animation: v2-hero-in 600ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

[data-skin="v2"] .v2-hero-in[data-delay="1"] {
  animation-delay: 100ms;
}
[data-skin="v2"] .v2-hero-in[data-delay="2"] {
  animation-delay: 200ms;
}
[data-skin="v2"] .v2-hero-in[data-delay="3"] {
  animation-delay: 300ms;
}
[data-skin="v2"] .v2-hero-in[data-delay="4"] {
  animation-delay: 400ms;
}

[data-skin="v2"] .v2-fade-slide {
  animation: v2-fade-slide-in 500ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

[data-skin="v2"] .v2-draw {
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
  animation: v2-draw 1.8s cubic-bezier(0.2, 0.7, 0.2, 1) forwards;
}

[data-skin="v2"] .v2-bar-rise {
  transform-origin: bottom;
  animation: v2-bar-rise 600ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

[data-skin="v2"] .v2-type-in {
  animation: v2-type-in 600ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

[data-skin="v2"] .v2-blink {
  animation: v2-blink 1.2s ease-in-out infinite;
}

[data-skin="v2"] .v2-pulse-soft {
  animation: v2-pulse-soft 3s ease-in-out infinite;
}

/* Continuous, looping bar-chart ripple — used in the "where you stand" cell. */
@keyframes v2-bar-ripple {
  0%,
  100% {
    transform: scaleY(1);
  }
  50% {
    transform: scaleY(0.78);
  }
}

[data-skin="v2"] .v2-bar-ripple {
  transform-origin: bottom;
  animation: v2-bar-ripple 2.4s ease-in-out infinite;
}

/* Progress-tree node entry — used by `pages/v2/Tree.tsx`. Each node
 * fades + scales up after a tiny per-index delay so the graph paints
 * in a single sweep rather than popping in all at once. */
@keyframes v2-tree-pop {
  from {
    opacity: 0;
    transform: scale(0.92) translateY(6px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

/* Side panel slides in from the right when a tree node is clicked. */
@keyframes v2-tree-panel-in {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-skin="v2"] .v2-enter,
  [data-skin="v2"] .v2-hero-in,
  [data-skin="v2"] .v2-fade-slide,
  [data-skin="v2"] .v2-draw,
  [data-skin="v2"] .v2-bar-rise,
  [data-skin="v2"] .v2-type-in,
  [data-skin="v2"] .v2-blink,
  [data-skin="v2"] .v2-pulse-soft,
  [data-skin="v2"] .v2-bar-ripple {
    animation: none !important;
  }
}

/* ============================================================
 * Decorative platinum grid + soft fade mask.
 * ============================================================ */

[data-skin="v2"] .platinum-grid {
  background-image:
    linear-gradient(rgb(var(--platinum-grid-line) / 0.1) 1px, transparent 1px),
    linear-gradient(90deg, rgb(var(--platinum-grid-line) / 0.1) 1px, transparent 1px);
  background-size: 32px 32px;
  background-position: -1px -1px;
}

[data-skin="v2"] .platinum-fade {
  -webkit-mask-image: radial-gradient(ellipse at center, black 30%, transparent 75%);
          mask-image: radial-gradient(ellipse at center, black 30%, transparent 75%);
}

/* ============================================================
 * Article body markdown — Theory pages + IDE Editorial tab.
 *
 * The markdown renderer emits raw h1/h2/h3/p elements; without
 * explicit font-family they inherit whichever sans font the browser
 * picked last (often Lemma Sans, not Geist). Force Geist on every
 * heading inside .v2-article-body so admissions + quant theory pages
 * agree typographically.
 * ============================================================ */
[data-skin="v2"] .v2-article-body h1,
[data-skin="v2"] .v2-article-body h2,
[data-skin="v2"] .v2-article-body h3,
[data-skin="v2"] .v2-article-body h4 {
  font-family: 'Geist Sans', system-ui, -apple-system, sans-serif;
  letter-spacing: -0.01em;
  color: rgb(var(--text-primary));
}
[data-skin="v2"] .v2-article-body h1 {
  font-size: 1.75rem;
  line-height: 1.2;
  font-weight: 500;     /* h1 keeps medium weight — section heading */
  margin-top: 2.5rem;
  margin-bottom: 1rem;
}
[data-skin="v2"] .v2-article-body h2 {
  font-size: 1.5rem;
  line-height: 1.3;
  font-weight: 400;     /* match cracked: bigger, NOT bolder */
  border-top: 1px solid rgb(var(--border-primary));
  padding-top: 2rem;
  margin-top: 2.5rem;
  margin-bottom: 0.75rem;
}
[data-skin="v2"] .v2-article-body h3,
[data-skin="v2"] .v2-article-body h4 {
  font-weight: 400;     /* same: bigger, not bolder */
}
[data-skin="v2"] .v2-article-body h2:first-child {
  border-top: none;
  padding-top: 0;
  margin-top: 0;
}
[data-skin="v2"] .v2-article-body h3 {
  font-size: 1.125rem;
  margin-top: 1.75rem;
  margin-bottom: 0.5rem;
}
[data-skin="v2"] .v2-article-body p {
  font-size: 0.9375rem;
  line-height: 1.75;
  margin-bottom: 1rem;
  color: rgb(var(--text-primary));
}
[data-skin="v2"] .v2-article-body ul,
[data-skin="v2"] .v2-article-body ol {
  font-size: 0.9375rem;
  line-height: 1.75;
  margin-bottom: 1rem;
  padding-left: 1.5rem;
}
[data-skin="v2"] .v2-article-body li {
  margin-bottom: 0.25rem;
}
[data-skin="v2"] .v2-article-body blockquote {
  border-left: 3px solid rgb(var(--border-primary));
  padding: 0.5rem 0 0.5rem 1rem;
  margin: 1.5rem 0;
  color: rgb(var(--text-secondary));
  font-style: italic;
}

/* ============================================================
 * Comments — thread connectors, avatars, and rows. Mirrors
 * getcracked.io's comment chrome. Scoped to the v2 skin so v1
 * surfaces remain untouched.
 * ============================================================ */

/* Vertical connector line through the avatar column, drawn down
 * to the bottom of the wrapper so children threads stay visually
 * linked to their parent. Cracked uses `bg-border-secondary` but
 * Lemma reserves that token for stronger separators — we use a
 * 60% alpha of `--border-primary` for the resting state and
 * `--border-secondary` on hover. */
[data-skin="v2"] .v2-comment-line {
  background-color: rgb(var(--border-primary) / 0.6);
}

[data-skin="v2"] .group\/comment:hover .v2-comment-line {
  background-color: rgb(var(--border-secondary));
}

/* Corner bend where a reply joins its parent's vertical line. */
[data-skin="v2"] .v2-comment-corner {
  border-color: rgb(var(--border-primary) / 0.6);
}

[data-skin="v2"] .group\/comment:hover .v2-comment-corner {
  border-color: rgb(var(--border-secondary));
}

/* Indent nested replies so each reply's avatar sits roughly under
 * its parent's avatar center, letting the corner-bend connect. */
[data-skin="v2"] .v2-comment-children {
  padding-left: 32px;
}

[data-skin="v2"] .v2-comment-row .v2-comment-row .v2-comment-children {
  padding-left: 28px;
}

[data-skin="v2"] .v2-comment-row .v2-comment-row .v2-comment-row .v2-comment-children {
  padding-left: 24px;
}

/* Avatar — neutral monogram pill, used when we don't have a
 * real profile image to render. */
[data-skin="v2"] .v2-comment-avatar {
  font-family: 'Geist Sans', 'Geist', system-ui, sans-serif;
  letter-spacing: 0.02em;
}

/* LatexRenderer emits raw <p> tags inside the body. Tighten the
 * vertical rhythm so the comment reads as a single prose block. */
[data-skin="v2"] .v2-comment-row p {
  margin-top: 0;
  margin-bottom: 0.5rem;
}

[data-skin="v2"] .v2-comment-row p:last-child {
  margin-bottom: 0;
}

/* ============================================================
 * Warwick logo (and other "blendOnWhite" JPEGs) need
 * mix-blend-mode: multiply in light mode so the white JPEG
 * background fades into the bg-secondary surface.
 * In dark mode the base `.v2-uni-logo` rule above already forces
 * `mix-blend-mode: normal !important` because the inverted logo
 * doesn't need (or want) multiply. This class is the explicit,
 * class-driven version of the previously-inline mixBlendMode.
 * ============================================================ */
[data-skin="v2"] .v2-uni-logo.v2-uni-logo-multiply {
  mix-blend-mode: multiply;
}
[data-theme="dark"] [data-skin="v2"] .v2-uni-logo.v2-uni-logo-multiply {
  mix-blend-mode: normal;
}

/* ============================================================
 * V2 onboarding flow — full-screen, animated.
 *
 * Each step is keyed; remounting fires `v2-step-fade-in`.
 * The decorative backdrop runs three orbs that slowly drift
 * across the viewport to give the surface life without
 * pulling focus from the question.
 * ============================================================ */

[data-skin="v2"] .v2-onboarding-step {
  animation: v2-step-fade-in 240ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

@keyframes v2-step-fade-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

[data-skin="v2"] .v2-onboarding-orb {
  position: absolute;
  border-radius: 9999px;
  filter: blur(80px);
  opacity: 0.85;
  will-change: transform;
}

[data-skin="v2"] .v2-onboarding-orb-a {
  width: 38rem;
  height: 38rem;
  top: -8rem;
  left: -10rem;
  background: radial-gradient(
    circle,
    rgb(var(--platinum-sheen) / 0.15) 0%,
    rgb(var(--platinum-sheen) / 0) 70%
  );
  animation: v2-orb-drift-a 22s ease-in-out infinite;
}

[data-skin="v2"] .v2-onboarding-orb-b {
  width: 42rem;
  height: 42rem;
  bottom: -12rem;
  right: -12rem;
  background: radial-gradient(
    circle,
    rgb(var(--platinum) / 0.10) 0%,
    rgb(var(--platinum) / 0) 70%
  );
  animation: v2-orb-drift-b 28s ease-in-out infinite;
}

[data-skin="v2"] .v2-onboarding-orb-c {
  width: 30rem;
  height: 30rem;
  top: 30%;
  left: 45%;
  background: radial-gradient(
    circle,
    rgb(var(--platinum-light) / 0.08) 0%,
    rgb(var(--platinum-light) / 0) 70%
  );
  animation: v2-orb-drift-c 26s ease-in-out infinite;
}

@keyframes v2-orb-drift-a {
  0%, 100% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  50% {
    transform: translate3d(6rem, 4rem, 0) scale(1.08);
  }
}

@keyframes v2-orb-drift-b {
  0%, 100% {
    transform: translate3d(0, 0, 0) scale(1);
  }
  50% {
    transform: translate3d(-5rem, -3rem, 0) scale(1.05);
  }
}

@keyframes v2-orb-drift-c {
  0%, 100% {
    transform: translate3d(-50%, -50%, 0) scale(1);
  }
  50% {
    transform: translate3d(-40%, -60%, 0) scale(1.12);
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-skin="v2"] .v2-onboarding-step {
    animation: none;
  }
  [data-skin="v2"] .v2-onboarding-orb {
    animation: none;
  }
}

/* ============================================================
 * Pair-coding remote cursors.
 *
 * `.v2-pair-cursor-{slot}` is the Monaco *content widget cursor* —
 * a 2px-wide vertical bar drawn over the line/column position of a
 * remote participant. `colorSlotForUid()` in `lib/pairSession.ts`
 * hashes each uid into one of 8 slots.
 *
 * The flag (with tooltip text) is rendered separately as a Monaco
 * content widget; see `pages/v2/Coding.tsx`.
 * ============================================================ */
.v2-pair-cursor-bar {
  width: 2px !important;
  margin-left: -1px;
  pointer-events: none;
}

.v2-pair-cursor-line {
  background-color: transparent;
}

.v2-pair-cursor-0 { background-color: rgb(244 114 182) !important; } /* pink-400 */
.v2-pair-cursor-1 { background-color: rgb(251 146 60) !important; }  /* orange-400 */
.v2-pair-cursor-2 { background-color: rgb(250 204 21) !important; }  /* yellow-400 */
.v2-pair-cursor-3 { background-color: rgb(74 222 128) !important; }  /* green-400 */
.v2-pair-cursor-4 { background-color: rgb(34 211 238) !important; }  /* cyan-400 */
.v2-pair-cursor-5 { background-color: rgb(96 165 250) !important; }  /* blue-400 */
.v2-pair-cursor-6 { background-color: rgb(167 139 250) !important; } /* violet-400 */
.v2-pair-cursor-7 { background-color: rgb(232 121 249) !important; } /* fuchsia-400 */

.v2-pair-flag {
  position: absolute;
  white-space: nowrap;
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, monospace;
  font-size: 10px;
  line-height: 1;
  padding: 2px 5px;
  border-radius: 3px;
  color: white;
  pointer-events: none;
  transform: translateY(-100%);
  z-index: 30;
  font-weight: 500;
  letter-spacing: 0.01em;
}

.v2-pair-flag-0 { background-color: rgb(244 114 182); }
.v2-pair-flag-1 { background-color: rgb(251 146 60); }
.v2-pair-flag-2 { background-color: rgb(250 204 21); color: rgb(38 38 38); }
.v2-pair-flag-3 { background-color: rgb(74 222 128); color: rgb(38 38 38); }
.v2-pair-flag-4 { background-color: rgb(34 211 238); color: rgb(38 38 38); }
.v2-pair-flag-5 { background-color: rgb(96 165 250); }
.v2-pair-flag-6 { background-color: rgb(167 139 250); }
.v2-pair-flag-7 { background-color: rgb(232 121 249); }

/* ============================================================
 * Monaco read-only message widget — replaces the default light-grey
 * "Cannot edit in read-only editor" tooltip with the v2 cracked
 * read-only pill chrome (bg-secondary, text-secondary, border-primary,
 * rounded-xl, small font). Monaco renders this widget when the user
 * tries to type into a read-only editor; the override here keeps it
 * visually consistent with the ReadOnlyPill used elsewhere on the
 * IDE surface (IdeTopBar, IdeChatPanel, InlineCommentsLayer).
 * ============================================================ */
[data-skin="v2"] .monaco-editor .monaco-editor-overlaymessage .message,
[data-skin="v2"] .monaco-editor .read-only-message-widget {
  background-color: rgb(var(--bg-secondary)) !important;
  color: rgb(var(--text-secondary)) !important;
  border: 1px solid rgb(var(--border-primary)) !important;
  border-radius: 0.75rem !important;
  padding: 0.375rem 0.625rem !important;
  font-size: 11px !important;
  font-weight: 500 !important;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12) !important;
}
[data-skin="v2"] .monaco-editor .monaco-editor-overlaymessage .anchor {
  border-top-color: rgb(var(--border-primary)) !important;
  border-bottom-color: rgb(var(--border-primary)) !important;
}
