///|
/// Parse border-collapse value
fn parse_border_collapse(value : String) -> @style.BorderCollapse {
  match value.trim() {
    "collapse" => Collapse
    "separate" => Separate
    _ => Separate
  }
}

///|
/// Border style keywords that suppress used border width.
fn is_none_border_style_enum(style : @style.BorderStyle) -> Bool {
  style == None || style == Hidden
}

///|
fn is_none_border_style(value : String) -> Bool {
  let v = value.trim().to_lower()
  v == "none" || v == "hidden"
}

///|
fn extract_border_color_from_shorthand(
  value : String,
  ctx : ComputeContext,
) -> @types.Color {
  let parts = split_whitespace(value)
  for part in parts {
    let lower = part.to_lower()
    // Skip border-style keywords and width keywords/values
    match lower {
      "none"
      | "hidden"
      | "dotted"
      | "dashed"
      | "solid"
      | "double"
      | "groove"
      | "ridge"
      | "inset"
      | "outset"
      | "thin"
      | "medium"
      | "thick" => continue
      _ => ()
    }
    // Skip numeric values (border width)
    if lower.length() > 0 && lower[0] >= '0' && lower[0] <= '9' {
      continue
    }
    if lower == "0" {
      continue
    }
    // Try to parse as color
    let color_val = parse_color_with_ctx(part, ctx)
    match color_val.get_color() {
      Some(c) => return c
      None => ()
    }
  }
  @types.Color::black() // CSS default: currentColor → approximate as black
}

///|
fn extract_border_style_from_shorthand(value : String) -> @style.BorderStyle {
  let parts = split_whitespace(value)
  let mut found_style = false
  let mut result = @style.BorderStyle::None
  for part in parts {
    let lower = part.to_lower()
    match lower {
      "none"
      | "hidden"
      | "dotted"
      | "dashed"
      | "solid"
      | "double"
      | "groove"
      | "ridge"
      | "inset"
      | "outset" => {
        found_style = true
        result = parse_border_style_value(part)
      }
      _ => ()
    }
  }
  if found_style {
    result
  } else {
    Solid // Default when only width/color specified
  }
}

///|
fn parse_border_style_value(value : String) -> @style.BorderStyle {
  match value.trim().to_lower() {
    "none" => None
    "hidden" => Hidden
    "dotted" => Dotted
    "dashed" => Dashed
    "solid" => Solid
    "double" => Double
    "groove" => Groove
    "ridge" => Ridge
    "inset" => Inset
    "outset" => Outset
    _ => None
  }
}

///|
/// Resolve border width from width/style/color shorthand tokens.
/// Falls back to the existing default 1.5px for style-only shorthands.
fn resolve_border_width(
  value : String,
  ctx : ComputeContext,
) -> @types.Dimension {
  let v = value.trim().to_lower()
  if v == "none" || v == "hidden" || v == "0" {
    return Length(0.0)
  }

  let mut has_visible_style = false
  let mut has_none_style = false

  let parts = v
    .split(" ")
    .map(fn(part) { part.to_owned().trim().to_owned() })
    .filter(fn(part) { !part.is_empty() })
    .collect()

  for part in parts {
    match part {
      "none" | "hidden" => {
        has_none_style = true
        continue
      }
      "thin" => return Length(1.0)
      "medium" => return Length(3.0)
      "thick" => return Length(5.0)
      "solid"
      | "dotted"
      | "dashed"
      | "double"
      | "groove"
      | "ridge"
      | "inset"
      | "outset" => {
        has_visible_style = true
        continue
      }
      _ => ()
    }

    // Length-like token found in shorthand.
    match resolve_dimension(part, ctx) {
      Length(px) => return Length(px)
      _ => ()
    }
  }

  if has_none_style {
    Length(0.0)
  } else if has_visible_style {
    Length(1.5)
  } else {
    Length(0.0)
  }
}

///|
/// Parse table-layout value
fn parse_table_layout(value : String) -> @style.TableLayout {
  match value.trim() {
    "fixed" => Fixed
    "auto" => Auto
    _ => Auto
  }
}

///|
/// Parse caption-side value
fn parse_caption_side(value : String) -> @style.CaptionSide {
  match value.trim() {
    "top" => Top
    "bottom" => Bottom
    _ => Top
  }
}

///|
/// Parse margin-trim value
fn parse_margin_trim(value : String) -> @style.MarginTrim {
  match value.trim().to_lower() {
    "none" => None
    "block-start" => BlockStart
    "block-end" => BlockEnd
    "block" => Block
    "inline-start" => InlineStart
    "inline-end" => InlineEnd
    "inline" => Inline
    _ => None
  }
}

///|
/// Parse border-spacing value (single value or two values)
fn parse_border_spacing(
  value : String,
  ctx : ComputeContext,
) -> (Double, Double) {
  let v = value.trim()
  // Split by whitespace
  let parts : Array[StringView] = v
    .split(" ")
    .filter(fn(s) { !s.is_empty() })
    .collect()
  if parts.length() == 0 {
    return (0.0, 0.0)
  }
  let horizontal = match resolve_dimension(parts[0].to_owned(), ctx) {
    Length(px) => px
    _ => 0.0
  }
  let vertical = if parts.length() >= 2 {
    match resolve_dimension(parts[1].to_owned(), ctx) {
      Length(px) => px
      _ => horizontal
    }
  } else {
    horizontal
  }
  (horizontal, vertical)
}

///|
/// Parse border-radius shorthand (1-4 values)
/// Returns (top-left, top-right, bottom-right, bottom-left) in px
fn resolve_border_radius(
  value : String,
  ctx : ComputeContext,
) -> (Double, Double, Double, Double) {
  let v = value.trim()
  // Handle slash syntax (horizontal / vertical) - take only horizontal for now
  let effective = if v.contains("/") {
    let slash_parts : Array[StringView] = v.split("/").collect()
    slash_parts[0].to_owned().trim()
  } else {
    v
  }
  let parts : Array[StringView] = effective
    .split(" ")
    .filter(fn(s) { !s.is_empty() })
    .collect()
  if parts.length() == 0 {
    return (0.0, 0.0, 0.0, 0.0)
  }
  let values : Array[Double] = parts.map(fn(p) {
    let dim = resolve_dimension(p.to_owned(), ctx)
    match dim {
      Percent(pct) => -pct // Negative encodes percentage (fraction) for render-time resolution
      _ => resolve_dimension_to_px(dim)
    }
  })
  match values.length() {
    1 => (values[0], values[0], values[0], values[0])
    2 => (values[0], values[1], values[0], values[1])
    3 => (values[0], values[1], values[2], values[1])
    _ => (values[0], values[1], values[2], values[3])
  }
}