packages/runtime-dom/src/helpers/useCssVars.ts
<<<<<<< SEARCH
function setStyleVar(
  el: HTMLElement,
  key: string,
  value: string | number | null | undefined,
) {
  el.style.setProperty(`--${key}`, value == null ? '' : String(value))
}
=======
function setStyleVar(
  el: HTMLElement,
  key: string,
  value: string | number | null | undefined,
) {
  // Text nodes (slot content e.g. "Hello 👋") have no style.
  if (!el.style) return
  // null/undefined (vs. defaults e.g. 'blue') and '' omit the var on
  // SSR and client alike, so CSS fallbacks apply without mismatch.
  if (value == null || value === '') {
    el.style.removeProperty(`--${key}`)
  } else {
    el.style.setProperty(`--${key}`, String(value))
  }
}
>>>>>>> REPLACE
packages/runtime-dom/src/helpers/useCssVars.ts
<<<<<<< SEARCH
  // drill down HOCs until it's a non-component vnode
  while (vnode.component) {
    vnode = vnode.component.subTree
  }
=======
  // drill down HOCs until it's a non-component vnode
  while (vnode.component) {
    vnode = vnode.component.subTree
  }
  // Parent vars fall through a Fragment/slot root to its child root;
  // an empty default slot has no child and is safely skipped.
  if (
    !(vnode.shapeFlag & ShapeFlags.ELEMENT) &&
    vnode.shapeFlag & ShapeFlags.ARRAY_CHILDREN &&
    Array.isArray(vnode.children)
  ) {
    for (const child of vnode.children) {
      if (child && typeof child === 'object') {
        setVarsOnVNode(child as VNode, key, value)
      }
    }
    if (vnode.children.length) return
  }
>>>>>>> REPLACE
packages/runtime-dom/src/helpers/useCssVars.ts
<<<<<<< SEARCH
      watchPostEffect(setVars)
=======
      // Post-flush only: async v-bind updates run after the hydration
      // patchStyle merge, never during it or after unmount.
      watchPostEffect(() => {
        if (!instance.isUnmounted) setVars()
      })
>>>>>>> REPLACE
packages/shared/src/normalizeProp.ts
<<<<<<< SEARCH
  for (const key in styles) {
    const value = styles[key]
    const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key)
    if (isString(value) || typeof value === 'number') {
      ret += `${normalizedKey}:${value};`
    }
  }
=======
  for (const key in styles) {
    const value = styles[key]
    const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key)
    // Omit null/undefined/'' vars (client removeProperty parity) and
    // invalid numeric display (e.g. 0), keeping stylesheet defaults.
    if (
      value !== '' &&
      (isString(value) ||
        (typeof value === 'number' && normalizedKey !== 'display'))
    ) {
      ret += `${normalizedKey}:${value};`
    }
  }
>>>>>>> REPLACE
packages/runtime-dom/src/modules/style.ts
<<<<<<< SEARCH
    if (name.startsWith('--')) {
      // custom property
      style.setProperty(name, val)
    } else {
=======
    if (name.startsWith('--')) {
      // custom property: ''/null removes it, matching SSR omission
      if (val === '') {
        style.removeProperty(name)
      } else {
        style.setProperty(name, val)
      }
    } else if (name === 'display' && typeof val !== 'string') {
      // e.g. display: 0 - drop invalid value, keep default ('flex')
      style.removeProperty(name)
    } else {
>>>>>>> REPLACE