@import "tailwindcss";
@import "fumadocs-ui/css/neutral.css";
@import "fumadocs-ui/css/preset.css";
@import "./smoothui.css";

@source "../node_modules/fumadocs-ui/dist/**/*.js";
@source "../node_modules/shadcn-ui/**/*.{js,jsx,ts,tsx}";
@source "../node_modules/@repo/*/**/*.{js,jsx,ts,tsx}";
@source "../../../packages/smoothui/components/**/*.{js,jsx,ts,tsx}";
@source "../../../packages/smoothui/blocks/**/*.{js,jsx,ts,tsx}";
@source "../../../packages/smoothui/templates/**/*.{js,jsx,ts,tsx}";

@theme inline {
  --font-body: var(--font-inter);
  --font-title: var(--font-plus-jakarta-sans);
  --shiki-theme: var(--shiki--light);
  --shiki--light: var(--shiki-theme);
  --shiki--dark: var(--shiki-theme);
  --shadow-custom: var(--shadow-custom);
  --shadow-custom-brand: var(--shadow-custom-brand);
}

:root {
  --color-bt-gray: var(--bt-gray);
  --color-contrast-higher: #fff;
  --color-contrast-highest: #fff;
  --tw-ring-offset-shadow: 0 0 #0000;
  --tw-ring-shadow: 0 0 #0000;
  --bt-gray: #e5e7eb;
  --shadow-custom-brand:
    0px 1px 2px rgba(0, 0, 0, 0.4),
    0px 0px 0px 1px var(--color-brand-secondary),
    inset 0px 0.75px 0px rgba(255, 255, 255, 0.2);
  --shadow-custom:
    0px 0px 0px 1px rgba(0, 0, 0, 0.08),
    0px 1px 2px -1px rgba(0, 0, 0, 0.08), 0px 2px 4px 0px rgba(0, 0, 0, 0.04);
  --lines-page: url("/lines-b.png");
  --color-fd-primary: var(--color-brand);
  --color-fd-secondary: var(--color-smooth-50);
  /* Motion spine — match .cursor/rules/animations.mdc. Exit ~75% of enter;
     always honor prefers-reduced-motion. See .ui-craft/tokens.md. */
  --duration-fast: 0.15s;
  --duration-normal: 0.25s;
  --duration-slow: 0.4s;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
}

.dark {
  --bt-gray: black;
  --shadow-custom:
    0px -1px 0px 0px hsla(0, 0%, 100%, 0.06),
    0px 0px 0px 1px hsla(0, 0%, 100%, 0.06), 0px 0px 0px 1px #27272a,
    0px 1px 2px 0px rgba(0, 0, 0, 0.32), 0px 2px 4px 0px rgba(0, 0, 0, 0.32);
  --lines-page: url("/lines-w.png");
}

@layer base {
  *,
  ::after,
  ::before,
  ::backdrop,
  ::file-selector-button {
    border-color: var(--color-gray-200, currentColor);
  }
  * {
    scrollbar-color: gray transparent;
    scrollbar-width: thin;
    @apply border-border outline-ring/50;
  }
  body {
    @apply bg-background text-foreground antialiased;
  }

  .dark {
    --shiki-theme: var(--shiki--dark);
    --shiki--light: var(--shiki-theme);
    --shiki--dark: var(--shiki-theme);
  }
  [data-theme="dark"] {
    --shiki-theme: var(--shiki--dark);
  }
  [data-theme="light"] {
    --shiki-theme: var(--shiki--light);
  }
}

::selection {
  @apply bg-brand-secondary/20 text-brand;
}

.shiki {
  box-shadow: none;
}

.gradient-brand {
  @apply from-brand-secondary to-brand bg-gradient-to-bl;
}
.hover\:gradient-brand:hover {
  @apply from-brand-secondary to-brand bg-gradient-to-bl;
}

/* Nucleo duo-tone: color-2 inherits parent icon color at reduced opacity */
[data-color="color-2"] {
  color: color-mix(in oklch, currentColor 25%, transparent);
}

/* Active sidebar items: color-2 uses brand tint */
[data-active="true"] [data-color="color-2"] {
  color: color-mix(in oklch, var(--color-brand) 35%, transparent);
}

.shadow-custom-btgray {
  box-shadow:
    0px 1px 2px rgba(0, 0, 0, 0.4),
    0px 0px 0px 1px var(--color-bt-gray),
    inset 0px 0.75px 0px rgba(255, 255, 255, 0.2);
}

.bg-lines-page {
  background-image: var(--lines-page);
  background-repeat: repeat;
}

[data-slot="dropdown-menu-item"] {
  @apply focus:bg-primary focus:border-border text-foreground border border-transparent;
}

.float-trigger {
  @apply text-foreground flex cursor-pointer flex-row items-center justify-center rounded-full border border-transparent px-4 py-2 text-sm font-medium outline-0;
}

.float-trigger:hover {
  @apply bg-primary border-border border;
}

.prose :where(ul):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  padding-inline-start: 1rem;
  margin-top: 1.25em;
  margin-bottom: 1.25em;
  list-style-type: disc;
}
.prose
  :where(ul > li):not(
    :where([class~="not-prose"], [class~="not-prose"] *)
  )::marker {
  color: var(--color-smooth-800);
}

.frame-box {
  @apply bg-primary inset-ring-background border inset-ring-2 before:pointer-events-none before:absolute before:inset-0 before:bg-[radial-gradient(var(--dots-color)_1px,transparent_1px)] before:[background-size:16px_16px] before:[--dots-color:--alpha(var(--color-foreground)/5%)];
}

/* Price Flow Animations */
@keyframes slide-out-up {
  0% {
    transform: translateY(0%);
    opacity: 1;
  }
  100% {
    transform: translateY(-100%);
    opacity: 0;
  }
}

@keyframes slide-out-down {
  0% {
    transform: translateY(0%);
    opacity: 1;
  }
  100% {
    transform: translateY(100%);
    opacity: 0;
  }
}

@keyframes slide-in-up {
  0% {
    transform: translateY(100%);
    opacity: 0;
  }
  100% {
    transform: translateY(0%);
    opacity: 1;
  }
}

@keyframes slide-in-down {
  0% {
    transform: translateY(-100%);
    opacity: 0;
  }
  100% {
    transform: translateY(0%);
    opacity: 1;
  }
}

.slide-out-up {
  animation: slide-out-up 0.3s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.slide-out-down {
  animation: slide-out-down 0.3s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.slide-in-up {
  animation: slide-in-up 0.3s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.slide-in-down {
  animation: slide-in-down 0.3s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.prose
  :where(h1, h2, h3, h4, h5, h6):not(
    :where([class~="not-prose"], [class~="not-prose"] *)
  ) {
  @apply font-semibold text-foreground tracking-tight;
}
.prose :where(h1):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply font-extrabold text-4xl leading-tight;
}
.prose :where(h2):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply font-bold text-2xl leading-tight;
}
.prose :where(h3):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply font-semibold text-xl leading-tight;
}
.prose :where(h4):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply font-semibold text-lg leading-tight;
}
.prose :where(h5):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply font-semibold text-base;
}
.prose :where(h6):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply font-semibold text-sm;
}
.prose :where(p):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply text-base;
}
.prose
  :where(strong):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply font-semibold;
}
.prose :where(.peer):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
  @apply font-semibold;
}

/* Accordion Animations */
@keyframes accordion-down {
  from {
    height: 0;
  }
  to {
    height: var(--radix-accordion-content-height);
  }
}

@keyframes accordion-up {
  from {
    height: var(--radix-accordion-content-height);
  }
  to {
    height: 0;
  }
}

.animate-accordion-down {
  animation: accordion-down 0.2s ease-out;
}

.animate-accordion-up {
  animation: accordion-up 0.2s ease-out;
}

/* Center the docs content column within its (full-width) grid track,
   mirroring ElevenLabs' `w-content-width mx-auto` article. */
#nd-page {
  width: 100%;
  max-width: calc(900px + 2 * 2rem);
  margin-inline: auto;
}

/* Full pages (no TOC) stretch to the whole main track; also lift the
   *:max-w-[1285px] child cap fumadocs applies in full mode. Unlayered
   rules win over the layered utilities. */
#nd-page[data-full="true"] {
  max-width: none;
}

#nd-page[data-full="true"] > * {
  max-width: none;
}

/* Docs headings use the title font (Plus Jakarta Sans). */
#nd-page :is(h1, h2, h3, h4, h5, h6) {
  font-family: var(--font-title);
}

/* Override fumadocs utility classes on headings — unlayered beats @layer utilities */
#nd-page h1 {
  font-size: var(--text-4xl);
  font-weight: 800;
  line-height: var(--leading-tight);
}
#nd-page h2 {
  font-size: var(--text-2xl);
  font-weight: 700;
  line-height: var(--leading-tight);
}
#nd-page h3 {
  font-size: var(--text-xl);
  font-weight: 600;
  line-height: var(--leading-tight);
}
#nd-page h4 {
  font-size: var(--text-lg);
  font-weight: 600;
  line-height: var(--leading-tight);
}
#nd-page h5 {
  font-size: var(--text-base);
  font-weight: 600;
}
#nd-page h6 {
  font-size: var(--text-sm);
  font-weight: 600;
}

/* ElevenLabs-style docs chrome: clean white surfaces + hairline borders,
   built from our own tokens (no hardcoded colors). */
#nd-notebook-layout,
#nd-sidebar {
  --fd-sidebar-width: 240px;
}

/* The fumadocs notebook container sets grid-template via inline style using
   `calc(var(--fd-layout-width,97rem) - sidebar - toc)` for the main track.
   Percentage values in CSS vars don't resolve against the grid container's
   inline size (circular), so the outer 1fr gutter columns end up non-zero
   even with --fd-layout-width:100%. Override the column template directly
   to collapse them to 0px.

   Mobile: sidebar is max-md:hidden but with collapsible:false collapsed=false
   always, so --fd-sidebar-col stays at 240px. Force column 2 to 0px on mobile
   so the hidden sidebar doesn't occupy grid space. */
@media (max-width: 767px) {
  #nd-notebook-layout {
    grid-template-columns: 0px 0px 1fr 0px 0px !important;
  }
}
@media (min-width: 768px) and (max-width: 1279px) {
  #nd-notebook-layout {
    grid-template-columns: 0px var(--fd-sidebar-col) 1fr var(--fd-toc-width) 0px !important;
  }

  #nd-notebook-layout:has(#nd-page[data-full="true"]) {
    grid-template-columns: 0px var(--fd-sidebar-col) 1fr 0px 0px !important;
  }
}

/* At xl+, always reserve 268px for the toc column so content width is identical
   on pages with and without a TOC. --fd-toc-width on #nd-notebook-layout itself
   is overridden by the [--fd-toc-width:0px] utility class on the same element,
   so hardcode the column value directly instead of relying on the variable.
   Exception: full pages (no TOC by design, e.g. the components gallery)
   collapse the toc column and let the main track take the whole width. */
@media (min-width: 1280px) {
  #nd-notebook-layout {
    grid-template-columns: 0px var(--fd-sidebar-col) 1fr 240px 0px !important;
  }

  #nd-notebook-layout:has(#nd-page[data-full="true"]) {
    grid-template-columns: 0px var(--fd-sidebar-col) 1fr 0px 0px !important;
  }
}

/* Top nav: solid surface instead of the translucent gray. The inner
   tabs row already carries its own border-b, so no border here. */
#nd-subnav {
  background-color: var(--color-background);
}

/* Sidebar: hairline separator from the content column. */
#nd-sidebar {
  border-inline-end: 1px solid var(--color-border);
}

/* Match TOC column width to sidebar (fumadocs default 268px → 240px).
   xl:layout:[--fd-toc-width:268px] sets it on #nd-notebook-layout via :has();
   this unlayered rule wins over @layer utilities. */
#nd-notebook-layout {
  --fd-toc-width: 240px;
}

/* Three sources of top gap in the sidebar when navMode="top" + collapsible=false:
   1. Header div (p-4 pb-2) has no visible content → collapse it
   2. ScrollViewport inner div has p-4 top padding → remove it
   3. Hidden lg:hidden menu items precede the first separator so first:mt-0 never
      fires and the separator keeps mt-6; pt-0 on the viewport absorbs that. */
#nd-sidebar > div:first-child {
  padding-block: 0 !important;
}
#nd-sidebar [data-radix-scroll-area-viewport] > div {
  padding-top: 0 !important;
}

/* Line numbers for the code explorer.
   Shiki already wraps every line in `.line`, so a CSS counter numbers them
   without re-parsing the highlighted output or shipping a transformer. */
.code-explorer-lines code {
  counter-reset: line;
}

.code-explorer-lines .line::before {
  display: inline-block;
  width: 2rem;
  margin-right: 1rem;
  color: var(--color-muted-foreground);
  text-align: right;
  /* Chrome puts generated content on the clipboard, so a hand-selected copy
     would come back with a line number glued to every line. */
  user-select: none;
  content: counter(line);
  counter-increment: line;
  opacity: 0.4;
}

/* Tailwind v4 dropped `cursor: pointer` from Preflight, so a `<button>` shows
   the arrow unless every call site says otherwise. Our own components declare
   it, but the chrome that comes from Fumadocs cannot — this covers it, and
   anything added later, in one place. Disabled controls keep the default. */
@layer base {
  button:not(:disabled),
  [role="button"]:not([aria-disabled="true"]) {
    cursor: pointer;
  }
}

/* The navbar's sidebar collapse trigger, desktop only.
   The catalogue already has two ways in that read better: the breadcrumb on
   component, block and index pages, and the pointer reaching the left edge. A
   third control in the navbar meant the same sidebar was offered twice, and it
   was the one nobody used. The phone button stays — there it is the only way in,
   and it lives in a `md:hidden` container so this rule leaves it alone. */
@media (min-width: 768px) {
  #nd-subnav [aria-label="Collapse Sidebar"],
  #nd-subnav [aria-label="Expand Sidebar"] {
    display: none;
  }
}
