From 1f5508bf6d59c0232f775c265751dd5b79346a2f Mon Sep 17 00:00:00 2001 From: melsonic Date: Sat, 29 Mar 2025 14:39:40 +0530 Subject: [PATCH] refactored Shape & connection renderers --- d2exporter/export.go | 5 +- d2renderers/d2svg/d2svg.go | 84 +++++----- d2renderers/d2svg/table.go | 22 --- d2target/d2target.go | 16 +- .../txtar/icon-style/dagre/board.exp.json | 4 +- .../txtar/icon-style/dagre/sketch.exp.svg | 152 +++++++++--------- .../txtar/icon-style/elk/board.exp.json | 4 +- .../txtar/icon-style/elk/sketch.exp.svg | 152 +++++++++--------- 8 files changed, 208 insertions(+), 231 deletions(-) diff --git a/d2exporter/export.go b/d2exporter/export.go index 99e8db2d0..56f4b9146 100644 --- a/d2exporter/export.go +++ b/d2exporter/export.go @@ -194,11 +194,8 @@ func applyStyles(shape *d2target.Shape, obj *d2graph.Object) { if obj.Style.DoubleBorder != nil { shape.DoubleBorder, _ = strconv.ParseBool(obj.Style.DoubleBorder.Value) } - if obj.IconStyle != (d2graph.Style{}) { - shape.IconStyle = &d2target.ShapeIconStyle{} - } if obj.IconStyle.BorderRadius != nil { - shape.IconStyle.BorderRadius, _ = strconv.Atoi(obj.IconStyle.BorderRadius.Value) + shape.IconBorderRadius, _ = strconv.Atoi(obj.IconStyle.BorderRadius.Value) } } diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go index 0d0bb44fc..a71580121 100644 --- a/d2renderers/d2svg/d2svg.go +++ b/d2renderers/d2svg/d2svg.go @@ -853,25 +853,18 @@ func drawConnection(writer io.Writer, diagramHash string, connection d2target.Co if connection.Icon != nil { iconPos := connection.GetIconPosition() if iconPos != nil { + connectionIconClipPath := "" if connection.IconBorderRadius != 0 { - fmt.Fprintf(writer, ``, - html.EscapeString(connection.Icon.String()), - iconPos.X, - iconPos.Y, - d2target.DEFAULT_ICON_SIZE, - d2target.DEFAULT_ICON_SIZE, - connection.IconBorderRadius, - ) - } else { - - fmt.Fprintf(writer, ``, - html.EscapeString(connection.Icon.String()), - iconPos.X, - iconPos.Y, - d2target.DEFAULT_ICON_SIZE, - d2target.DEFAULT_ICON_SIZE, - ) + connectionIconClipPath = fmt.Sprintf(` clip-path="inset(0 round %fpx)"`, connection.IconBorderRadius) } + fmt.Fprintf(writer, ``, + html.EscapeString(connection.Icon.String()), + iconPos.X, + iconPos.Y, + d2target.DEFAULT_ICON_SIZE, + d2target.DEFAULT_ICON_SIZE, + connectionIconClipPath, + ) } } @@ -1447,9 +1440,10 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape el.Fill = fill el.Stroke = stroke el.Style = style - if targetShape.IconStyle != nil && targetShape.IconStyle.BorderRadius != 0 { - fmt.Fprint(writer, clipPathForIconBorderRadius(diagramHash, targetShape)) - el.ClipPath = fmt.Sprintf("%v-%v-icon", diagramHash, targetShape.ID) + if targetShape.IconBorderRadius != 0 { + clipPathId := fmt.Sprintf("%v-%v-icon", diagramHash, svg.SVGID(targetShape.ID)) + fmt.Fprint(writer, applyIconBorderRadius(clipPathId, targetShape)) + el.ClipPath = clipPathId } fmt.Fprint(writer, el.Render()) @@ -1643,24 +1637,18 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape tl := iconPosition.GetPointOnBox(box, label.PADDING, float64(iconSize), float64(iconSize)) - if targetShape.IconStyle != nil && targetShape.IconStyle.BorderRadius != 0 { - fmt.Fprintf(writer, ``, - html.EscapeString(targetShape.Icon.String()), - tl.X, - tl.Y, - iconSize, - iconSize, - targetShape.IconStyle.BorderRadius, - ) - } else { - fmt.Fprintf(writer, ``, - html.EscapeString(targetShape.Icon.String()), - tl.X, - tl.Y, - iconSize, - iconSize, - ) + shapeIconClipPath := "" + if targetShape.IconBorderRadius != 0 { + shapeIconClipPath = fmt.Sprintf(` clip-path="inset(0 round %dpx)"`, targetShape.IconBorderRadius) } + fmt.Fprintf(writer, ``, + html.EscapeString(targetShape.Icon.String()), + tl.X, + tl.Y, + iconSize, + iconSize, + shapeIconClipPath, + ) } if targetShape.Label != "" && targetShape.Opacity != 0 { @@ -1889,6 +1877,28 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape return labelMask, nil } +func applyIconBorderRadius(clipPathId string, shape d2target.Shape) string { + box := geo.NewBox( + geo.NewPoint(float64(shape.Pos.X), float64(shape.Pos.Y)), + float64(shape.Width), + float64(shape.Height), + ) + topX, topY := box.TopLeft.X+box.Width, box.TopLeft.Y + + out := fmt.Sprintf(``, clipPathId) + out += fmt.Sprintf(` ` +} + func addAppendixItems(writer io.Writer, diagramHash string, targetShape d2target.Shape, s shape.Shape) { var p1, p2 *geo.Point if targetShape.Tooltip != "" || targetShape.Link != "" { diff --git a/d2renderers/d2svg/table.go b/d2renderers/d2svg/table.go index 2499836fc..f7b2782db 100644 --- a/d2renderers/d2svg/table.go +++ b/d2renderers/d2svg/table.go @@ -41,28 +41,6 @@ func clipPathForBorderRadius(diagramHash string, shape d2target.Shape) string { return out + `fill="none" /> ` } -func clipPathForIconBorderRadius(diagramHash string, shape d2target.Shape) string { - box := geo.NewBox( - geo.NewPoint(float64(shape.Pos.X), float64(shape.Pos.Y)), - float64(shape.Width), - float64(shape.Height), - ) - topX, topY := box.TopLeft.X+box.Width, box.TopLeft.Y - - out := fmt.Sprintf(``, diagramHash, shape.ID) - out += fmt.Sprintf(` ` -} - func tableHeader(diagramHash string, shape d2target.Shape, box *geo.Box, text string, textWidth, textHeight, fontSize float64, inlineTheme *d2themes.Theme) string { rectEl := d2themes.NewThemableElement("rect", inlineTheme) rectEl.X, rectEl.Y = box.TopLeft.X, box.TopLeft.Y diff --git a/d2target/d2target.go b/d2target/d2target.go index 81518a966..4880c2859 100644 --- a/d2target/d2target.go +++ b/d2target/d2target.go @@ -503,12 +503,12 @@ type Shape struct { Multiple bool `json:"multiple"` DoubleBorder bool `json:"double-border"` - Tooltip string `json:"tooltip"` - Link string `json:"link"` - PrettyLink string `json:"prettyLink,omitempty"` - Icon *url.URL `json:"icon"` - IconStyle *ShapeIconStyle `json:"iconStyle,omitempty"` - IconPosition string `json:"iconPosition"` + Tooltip string `json:"tooltip"` + Link string `json:"link"` + PrettyLink string `json:"prettyLink,omitempty"` + Icon *url.URL `json:"icon"` + IconBorderRadius int `json:"iconBorderRadius,omitempty"` + IconPosition string `json:"iconPosition"` // Whether the shape should allow shapes behind it to bleed through // Currently just used for sequence diagram groups @@ -532,10 +532,6 @@ type Shape struct { NeutralAccentColor string `json:"neutralAccentColor,omitempty"` } -type ShapeIconStyle struct { - BorderRadius int `json:"borderRadius"` -} - func (s Shape) GetFontColor() string { if s.Type == ShapeClass || s.Type == ShapeSQLTable { if !color.IsThemeColor(s.Color) { diff --git a/e2etests/testdata/txtar/icon-style/dagre/board.exp.json b/e2etests/testdata/txtar/icon-style/dagre/board.exp.json index 768640279..ae8607e6d 100644 --- a/e2etests/testdata/txtar/icon-style/dagre/board.exp.json +++ b/e2etests/testdata/txtar/icon-style/dagre/board.exp.json @@ -46,9 +46,7 @@ "Fragment": "", "RawFragment": "" }, - "iconStyle": { - "borderRadius": 20 - }, + "iconBorderRadius": 20, "iconPosition": "INSIDE_MIDDLE_CENTER", "blend": false, "fields": null, diff --git a/e2etests/testdata/txtar/icon-style/dagre/sketch.exp.svg b/e2etests/testdata/txtar/icon-style/dagre/sketch.exp.svg index 7e69de058..f8018d37f 100644 --- a/e2etests/testdata/txtar/icon-style/dagre/sketch.exp.svg +++ b/e2etests/testdata/txtar/icon-style/dagre/sketch.exp.svg @@ -1,9 +1,9 @@ - lambda + .d2-2397759342 .fill-N1{fill:#0A0F25;} + .d2-2397759342 .fill-N2{fill:#676C7E;} + .d2-2397759342 .fill-N3{fill:#9499AB;} + .d2-2397759342 .fill-N4{fill:#CFD2DD;} + .d2-2397759342 .fill-N5{fill:#DEE1EB;} + .d2-2397759342 .fill-N6{fill:#EEF1F8;} + .d2-2397759342 .fill-N7{fill:#FFFFFF;} + .d2-2397759342 .fill-B1{fill:#0D32B2;} + .d2-2397759342 .fill-B2{fill:#0D32B2;} + .d2-2397759342 .fill-B3{fill:#E3E9FD;} + .d2-2397759342 .fill-B4{fill:#E3E9FD;} + .d2-2397759342 .fill-B5{fill:#EDF0FD;} + .d2-2397759342 .fill-B6{fill:#F7F8FE;} + .d2-2397759342 .fill-AA2{fill:#4A6FF3;} + .d2-2397759342 .fill-AA4{fill:#EDF0FD;} + .d2-2397759342 .fill-AA5{fill:#F7F8FE;} + .d2-2397759342 .fill-AB4{fill:#EDF0FD;} + .d2-2397759342 .fill-AB5{fill:#F7F8FE;} + .d2-2397759342 .stroke-N1{stroke:#0A0F25;} + .d2-2397759342 .stroke-N2{stroke:#676C7E;} + .d2-2397759342 .stroke-N3{stroke:#9499AB;} + .d2-2397759342 .stroke-N4{stroke:#CFD2DD;} + .d2-2397759342 .stroke-N5{stroke:#DEE1EB;} + .d2-2397759342 .stroke-N6{stroke:#EEF1F8;} + .d2-2397759342 .stroke-N7{stroke:#FFFFFF;} + .d2-2397759342 .stroke-B1{stroke:#0D32B2;} + .d2-2397759342 .stroke-B2{stroke:#0D32B2;} + .d2-2397759342 .stroke-B3{stroke:#E3E9FD;} + .d2-2397759342 .stroke-B4{stroke:#E3E9FD;} + .d2-2397759342 .stroke-B5{stroke:#EDF0FD;} + .d2-2397759342 .stroke-B6{stroke:#F7F8FE;} + .d2-2397759342 .stroke-AA2{stroke:#4A6FF3;} + .d2-2397759342 .stroke-AA4{stroke:#EDF0FD;} + .d2-2397759342 .stroke-AA5{stroke:#F7F8FE;} + .d2-2397759342 .stroke-AB4{stroke:#EDF0FD;} + .d2-2397759342 .stroke-AB5{stroke:#F7F8FE;} + .d2-2397759342 .background-color-N1{background-color:#0A0F25;} + .d2-2397759342 .background-color-N2{background-color:#676C7E;} + .d2-2397759342 .background-color-N3{background-color:#9499AB;} + .d2-2397759342 .background-color-N4{background-color:#CFD2DD;} + .d2-2397759342 .background-color-N5{background-color:#DEE1EB;} + .d2-2397759342 .background-color-N6{background-color:#EEF1F8;} + .d2-2397759342 .background-color-N7{background-color:#FFFFFF;} + .d2-2397759342 .background-color-B1{background-color:#0D32B2;} + .d2-2397759342 .background-color-B2{background-color:#0D32B2;} + .d2-2397759342 .background-color-B3{background-color:#E3E9FD;} + .d2-2397759342 .background-color-B4{background-color:#E3E9FD;} + .d2-2397759342 .background-color-B5{background-color:#EDF0FD;} + .d2-2397759342 .background-color-B6{background-color:#F7F8FE;} + .d2-2397759342 .background-color-AA2{background-color:#4A6FF3;} + .d2-2397759342 .background-color-AA4{background-color:#EDF0FD;} + .d2-2397759342 .background-color-AA5{background-color:#F7F8FE;} + .d2-2397759342 .background-color-AB4{background-color:#EDF0FD;} + .d2-2397759342 .background-color-AB5{background-color:#F7F8FE;} + .d2-2397759342 .color-N1{color:#0A0F25;} + .d2-2397759342 .color-N2{color:#676C7E;} + .d2-2397759342 .color-N3{color:#9499AB;} + .d2-2397759342 .color-N4{color:#CFD2DD;} + .d2-2397759342 .color-N5{color:#DEE1EB;} + .d2-2397759342 .color-N6{color:#EEF1F8;} + .d2-2397759342 .color-N7{color:#FFFFFF;} + .d2-2397759342 .color-B1{color:#0D32B2;} + .d2-2397759342 .color-B2{color:#0D32B2;} + .d2-2397759342 .color-B3{color:#E3E9FD;} + .d2-2397759342 .color-B4{color:#E3E9FD;} + .d2-2397759342 .color-B5{color:#EDF0FD;} + .d2-2397759342 .color-B6{color:#F7F8FE;} + .d2-2397759342 .color-AA2{color:#4A6FF3;} + .d2-2397759342 .color-AA4{color:#EDF0FD;} + .d2-2397759342 .color-AA5{color:#F7F8FE;} + .d2-2397759342 .color-AB4{color:#EDF0FD;} + .d2-2397759342 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker-d2-2397759342);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker-d2-2397759342);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark-d2-2397759342);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker-d2-2397759342);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark-d2-2397759342);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal-d2-2397759342);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal-d2-2397759342);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright-d2-2397759342);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]> lambda \ No newline at end of file diff --git a/e2etests/testdata/txtar/icon-style/elk/board.exp.json b/e2etests/testdata/txtar/icon-style/elk/board.exp.json index 429ca832b..67f46fcbf 100644 --- a/e2etests/testdata/txtar/icon-style/elk/board.exp.json +++ b/e2etests/testdata/txtar/icon-style/elk/board.exp.json @@ -46,9 +46,7 @@ "Fragment": "", "RawFragment": "" }, - "iconStyle": { - "borderRadius": 20 - }, + "iconBorderRadius": 20, "iconPosition": "INSIDE_MIDDLE_CENTER", "blend": false, "fields": null, diff --git a/e2etests/testdata/txtar/icon-style/elk/sketch.exp.svg b/e2etests/testdata/txtar/icon-style/elk/sketch.exp.svg index 9c23b0493..223b98b4c 100644 --- a/e2etests/testdata/txtar/icon-style/elk/sketch.exp.svg +++ b/e2etests/testdata/txtar/icon-style/elk/sketch.exp.svg @@ -1,9 +1,9 @@ - lambda + .d2-2677970358 .fill-N1{fill:#0A0F25;} + .d2-2677970358 .fill-N2{fill:#676C7E;} + .d2-2677970358 .fill-N3{fill:#9499AB;} + .d2-2677970358 .fill-N4{fill:#CFD2DD;} + .d2-2677970358 .fill-N5{fill:#DEE1EB;} + .d2-2677970358 .fill-N6{fill:#EEF1F8;} + .d2-2677970358 .fill-N7{fill:#FFFFFF;} + .d2-2677970358 .fill-B1{fill:#0D32B2;} + .d2-2677970358 .fill-B2{fill:#0D32B2;} + .d2-2677970358 .fill-B3{fill:#E3E9FD;} + .d2-2677970358 .fill-B4{fill:#E3E9FD;} + .d2-2677970358 .fill-B5{fill:#EDF0FD;} + .d2-2677970358 .fill-B6{fill:#F7F8FE;} + .d2-2677970358 .fill-AA2{fill:#4A6FF3;} + .d2-2677970358 .fill-AA4{fill:#EDF0FD;} + .d2-2677970358 .fill-AA5{fill:#F7F8FE;} + .d2-2677970358 .fill-AB4{fill:#EDF0FD;} + .d2-2677970358 .fill-AB5{fill:#F7F8FE;} + .d2-2677970358 .stroke-N1{stroke:#0A0F25;} + .d2-2677970358 .stroke-N2{stroke:#676C7E;} + .d2-2677970358 .stroke-N3{stroke:#9499AB;} + .d2-2677970358 .stroke-N4{stroke:#CFD2DD;} + .d2-2677970358 .stroke-N5{stroke:#DEE1EB;} + .d2-2677970358 .stroke-N6{stroke:#EEF1F8;} + .d2-2677970358 .stroke-N7{stroke:#FFFFFF;} + .d2-2677970358 .stroke-B1{stroke:#0D32B2;} + .d2-2677970358 .stroke-B2{stroke:#0D32B2;} + .d2-2677970358 .stroke-B3{stroke:#E3E9FD;} + .d2-2677970358 .stroke-B4{stroke:#E3E9FD;} + .d2-2677970358 .stroke-B5{stroke:#EDF0FD;} + .d2-2677970358 .stroke-B6{stroke:#F7F8FE;} + .d2-2677970358 .stroke-AA2{stroke:#4A6FF3;} + .d2-2677970358 .stroke-AA4{stroke:#EDF0FD;} + .d2-2677970358 .stroke-AA5{stroke:#F7F8FE;} + .d2-2677970358 .stroke-AB4{stroke:#EDF0FD;} + .d2-2677970358 .stroke-AB5{stroke:#F7F8FE;} + .d2-2677970358 .background-color-N1{background-color:#0A0F25;} + .d2-2677970358 .background-color-N2{background-color:#676C7E;} + .d2-2677970358 .background-color-N3{background-color:#9499AB;} + .d2-2677970358 .background-color-N4{background-color:#CFD2DD;} + .d2-2677970358 .background-color-N5{background-color:#DEE1EB;} + .d2-2677970358 .background-color-N6{background-color:#EEF1F8;} + .d2-2677970358 .background-color-N7{background-color:#FFFFFF;} + .d2-2677970358 .background-color-B1{background-color:#0D32B2;} + .d2-2677970358 .background-color-B2{background-color:#0D32B2;} + .d2-2677970358 .background-color-B3{background-color:#E3E9FD;} + .d2-2677970358 .background-color-B4{background-color:#E3E9FD;} + .d2-2677970358 .background-color-B5{background-color:#EDF0FD;} + .d2-2677970358 .background-color-B6{background-color:#F7F8FE;} + .d2-2677970358 .background-color-AA2{background-color:#4A6FF3;} + .d2-2677970358 .background-color-AA4{background-color:#EDF0FD;} + .d2-2677970358 .background-color-AA5{background-color:#F7F8FE;} + .d2-2677970358 .background-color-AB4{background-color:#EDF0FD;} + .d2-2677970358 .background-color-AB5{background-color:#F7F8FE;} + .d2-2677970358 .color-N1{color:#0A0F25;} + .d2-2677970358 .color-N2{color:#676C7E;} + .d2-2677970358 .color-N3{color:#9499AB;} + .d2-2677970358 .color-N4{color:#CFD2DD;} + .d2-2677970358 .color-N5{color:#DEE1EB;} + .d2-2677970358 .color-N6{color:#EEF1F8;} + .d2-2677970358 .color-N7{color:#FFFFFF;} + .d2-2677970358 .color-B1{color:#0D32B2;} + .d2-2677970358 .color-B2{color:#0D32B2;} + .d2-2677970358 .color-B3{color:#E3E9FD;} + .d2-2677970358 .color-B4{color:#E3E9FD;} + .d2-2677970358 .color-B5{color:#EDF0FD;} + .d2-2677970358 .color-B6{color:#F7F8FE;} + .d2-2677970358 .color-AA2{color:#4A6FF3;} + .d2-2677970358 .color-AA4{color:#EDF0FD;} + .d2-2677970358 .color-AA5{color:#F7F8FE;} + .d2-2677970358 .color-AB4{color:#EDF0FD;} + .d2-2677970358 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker-d2-2677970358);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker-d2-2677970358);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark-d2-2677970358);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker-d2-2677970358);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark-d2-2677970358);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal-d2-2677970358);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal-d2-2677970358);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]> lambda \ No newline at end of file