package gui import clay "clay:." import "core:fmt" import "../core" import "../shared" workspace_nav :: proc(id_prefix, pos_label: string) { if clay.UI(clay.ID(fmt.tprintf("%sNav", id_prefix)))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(34)}, layoutDirection = .LeftToRight, childGap = 8, childAlignment = {y = .Center}}, }) { clay_body_text(pos_label, color = CLAY_ACCENT, size = CLAY_FONT_SIZE_SM) clay.UI(clay.ID(fmt.tprintf("%sNavSpacer", id_prefix)))({layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}}}) declare_button_small(fmt.tprintf("btn_%s_prev", id_prefix), "< Prev") declare_button_small(fmt.tprintf("btn_%s_next", id_prefix), "Next >") } } declare_script_workspace :: proc(app: ^GUI_App_State) { page_count := len(app.controller.state.script.pages) if page_count == 0 { declare_empty_state("ScriptEmpty", "No Script Yet", "Go to Story screen to set up your story idea", "Generate Script (F5) to create pages") return } idx := clamp_script_cursor(page_count, app.summary_opts.script_page_cursor) workspace_nav("script", fmt.tprintf("Page %d/%d", idx+1, page_count)) title := app.controller.state.script.title if len(title) > 50 { title = fmt.tprintf("%s...", title[:47]) } clay_muted_text(title) declare_script_detail(app) } declare_panels_workspace :: proc(app: ^GUI_App_State) { panel_count := count_script_panels(app.controller.state.script) if panel_count == 0 { declare_empty_state("PanelsEmpty", "No Panels Yet", "Generate a script first, then create panel images", "Generate Panels (F6) after having a script") return } generated_count := 0 for _, _ in app.controller.state.panel_images { generated_count += 1 } if clay.UI(clay.ID("PanelsHeader"))({ layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 8, childAlignment = {y = .Center}}, }) { clay_body_text(fmt.tprintf("%d of %d panels generated", generated_count, panel_count), color = CLAY_ACCENT, size = CLAY_FONT_SIZE_SM) clay.UI(clay.ID("PanelsHeaderSpacer"))({layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}}}) declare_button_primary("btn_panels_gen_all", "Generate All") } idx_cur := clamp_panel_cursor(panel_count, app.summary_opts.panel_cursor) if clay.UI(clay.ID("PanelGrid"))({ layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}, childGap = CLAY_SPACE_12}, }) { if clay.UI(clay.ID("PanelGridLeft"))({ layout = {sizing = {width = clay.SizingPercent(0.55), height = clay.SizingGrow({})}, layoutDirection = .TopToBottom, childGap = 4}, }) { workspace_nav("panels", fmt.tprintf("Panel %d/%d", idx_cur+1, panel_count)) panel, page_num, rok := panel_by_flat_index(app.controller.state.script, idx_cur) if rok { declare_panel_card(app, panel, page_num, idx_cur, panel_count) } } if clay.UI(clay.ID("PanelGridRight"))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}, layoutDirection = .TopToBottom, childGap = 2}, clip = {vertical = true, childOffset = clay.GetScrollOffset()}, }) { clay_label_text("ALL PANELS") for ri := 0; ri < panel_count; ri += 1 { row_panel, row_page, row_ok := panel_by_flat_index(app.controller.state.script, ri) if !row_ok { continue } is_cur := ri == idx_cur is_hov := clay.Hovered() row_color := CLAY_TEXT_TERTIARY if is_cur { row_color = CLAY_TEXT_BRIGHT } else if is_hov { row_color = CLAY_TEXT_PRIMARY } ready_mark := "✗" ready_color := CLAY_TEXT_TERTIARY if _, ex := app.controller.state.panel_images[row_panel.panel_id]; ex { ready_mark = "✓"; ready_color = CLAY_SUCCESS } if _, er := app.controller.state.panel_errors[row_panel.panel_id]; er { ready_mark = "!"; ready_color = CLAY_ERROR } row_bg := clay.Color{0, 0, 0, 0} if is_cur { row_bg = CLAY_BG_SELECTED } else if is_hov { row_bg = CLAY_BG_HOVER } if clay.UI(clay.ID(fmt.tprintf("panel_row_%d", ri)))({ layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(24)}, padding = {top = 2, right = 6, bottom = 2, left = 6}, childGap = 6, childAlignment = {y = .Center}}, backgroundColor = row_bg, cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_XS), }) { clay.Text(ready_mark, {fontId = CLAY_FONT_BODY, fontSize = CLAY_FONT_SIZE_XS, textColor = ready_color}) clay.Text(fmt.tprintf("%02d p%d#%d", ri+1, row_page, row_panel.panel_number), {fontId = CLAY_FONT_MONO, fontSize = CLAY_FONT_SIZE_XS, textColor = row_color}) } } } } } declare_panel_card :: proc(app: ^GUI_App_State, panel: core.Panel, page_num, panel_idx, total: int) { if clay.UI(clay.ID(fmt.tprintf("panel_card_%s", panel.panel_id)))(clay_card_style()) { if clay.UI(clay.ID(fmt.tprintf("panel_card_top_%s", panel.panel_id)))({ layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childAlignment = {y = .Center}, childGap = 8}, }) { clay_body_text(fmt.tprintf("Panel %d/%d", panel_idx+1, total), color = CLAY_ACCENT, size = CLAY_FONT_SIZE_SM) clay_muted_text(fmt.tprintf("Page %d", page_num)) } status := "missing" status_color := CLAY_WARNING if _, has := app.controller.state.panel_images[panel.panel_id]; has { status = "ready"; status_color = CLAY_SUCCESS } if _, er := app.controller.state.panel_errors[panel.panel_id]; er { status = "error"; status_color = CLAY_ERROR } if clay.UI(clay.ID(fmt.tprintf("panel_card_badges_%s", panel.panel_id)))({layout = clay_row_layout()}) { declare_status_badge(fmt.tprintf("panel_status_%s", panel.panel_id), status, status == "ready") declare_status_badge(fmt.tprintf("panel_shot_%s", panel.panel_id), shot_type_label(panel.shot_type), true) } desc := panel.description if len(desc) == 0 { desc = "(no description)" } clay_body_text(desc, color = CLAY_TEXT_SECONDARY, size = CLAY_FONT_SIZE_SM) if len(panel.characters_present) > 0 { if clay.UI(clay.ID(fmt.tprintf("panel_card_chars_%s", panel.panel_id)))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 4}}) { for cid in panel.characters_present { declare_nav_chip(fmt.tprintf("char_tag_%s", cid), cid, false) } } } if clay.UI(clay.ID(fmt.tprintf("panel_card_actions_%s", panel.panel_id)))({layout = clay_row_layout()}) { if _, has := app.controller.state.panel_images[panel.panel_id]; has { declare_button_small("btn_panel_regenerate", "Regen") declare_button_small("btn_panel_draw", "Draw") } else { declare_button_small("btn_panel_regenerate", "Generate") } if app.editing_panel_id == panel.panel_id { declare_button_small("btn_panel_save", "Save Prompt") } else { declare_button_small("btn_panel_edit", "Edit Prompt") } } if panel_img, has_img := app.controller.state.panel_images[panel.panel_id]; has_img { img_url := pool_clone(panel_img.url) _, loaded := load_panel_texture(&app.panel_textures, panel.panel_id, img_url) if loaded { tex_ptr := &app.panel_textures[panel.panel_id] if tex_ptr.id != 0 { if clay.UI(clay.ID(fmt.tprintf("panel_card_img_%s", panel.panel_id)))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(160)}}, cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_SM), image = {imageData = rawptr(tex_ptr)}, }) {} } } } } } declare_layout_workspace :: proc(app: ^GUI_App_State) { layout_count := len(app.controller.state.page_layouts) if layout_count == 0 { if clay.UI(clay.ID("LayoutEmpty"))(clay_card_style()) { declare_section_header("LayoutHeader", "Layout", "Arrange panels into comic pages") clay_label_text("PAGE SIZE") if clay.UI(clay.ID("PageSizeChips"))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 4}}) { sizes := []core.Page_Size_Name{.A4, .Letter, .Manga, .Webtoon, .Square} names := []string{"A4", "Letter", "Manga", "Webtoon", "Square"} for s, i in sizes { is_sel := app.controller.state.page_size == s declare_nav_chip(fmt.tprintf("btn_pgsize_%d", i), names[i], is_sel) } } clay_label_text("LAYOUT PATTERN") if clay.UI(clay.ID("PatternCards"))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 6}}) { patterns := []string{"grid-2x2", "manga-3-tier", "action-dynamic", "splash-page", "webtoon-scroll", "western-3x3", "dialogue-heavy", "cinematic-widescreen"} pnames := []string{"Grid", "Manga", "Action", "Splash", "Webtoon", "Western", "Dialogue", "Cinematic"} for p, j in patterns { is_hov := clay.Hovered() bg := CLAY_BG_STRIP if is_hov { bg = CLAY_BG_HOVER } if clay.UI(clay.ID(fmt.tprintf("btn_pattern_%s", p)))({ layout = {layoutDirection = .TopToBottom, sizing = {width = clay.SizingFixed(88), height = clay.SizingFixed(52)}, padding = {top = 6, right = 6, bottom = 6, left = 6}, childAlignment = {x = .Center}, childGap = 2}, backgroundColor = bg, cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_SM), border = {color = CLAY_BORDER_SUBTLE, width = clay.BorderOutside(1)}, }) { clay_body_text(pnames[j], color = CLAY_TEXT_PRIMARY, size = CLAY_FONT_SIZE_SM) clay.Text(fmt.tprintf("%d max", core.pattern_max_panels(p)), {fontId = CLAY_FONT_BODY, fontSize = CLAY_FONT_SIZE_XS, textColor = CLAY_TEXT_TERTIARY}) } } } } } else { idx := clamp_layout_cursor(layout_count, app.summary_opts.layout_page_cursor) workspace_nav("layout", fmt.tprintf("Page %d/%d", idx+1, layout_count)) declare_layout_detail(app) } } declare_bubbles_workspace :: proc(app: ^GUI_App_State) { layout_count := len(app.controller.state.page_layouts) if layout_count == 0 { declare_empty_state("BubblesEmpty", "No Bubbles Yet", "Run Layout Auto first to create page layouts", "Then use this screen to edit speech bubbles") return } page_idx := clamp_layout_cursor(layout_count, app.summary_opts.bubble_page_cursor) layout_val := app.controller.state.page_layouts[page_idx] panel_count := len(layout_val.panels) if clay.UI(clay.ID("BubblesNav"))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingFixed(34)}, layoutDirection = .LeftToRight, childGap = 6, childAlignment = {y = .Center}}, }) { clay_body_text(fmt.tprintf("Page %d/%d", page_idx+1, layout_count), color = CLAY_ACCENT, size = CLAY_FONT_SIZE_SM) clay_muted_text(fmt.tprintf("%d panels", panel_count)) clay.UI(clay.ID("BubblesNavSpacer"))({layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}}}) declare_button_small("btn_bubbles_prev_page", "< Page") declare_button_small("btn_bubbles_next_page", "Page >") declare_button_small("btn_bubbles_prev_panel", "< Panel") declare_button_small("btn_bubbles_next_panel", "Panel >") } declare_bubbles_detail(app) } declare_story_workspace :: proc(app: ^GUI_App_State, bp: shared.Breakpoint) { if clay.UI(clay.ID("StoryCard"))(clay_card_style()) { declare_section_header("StoryHeader", "Story Setup", "Define your comic's premise") clay_label_text("STORY IDEA") if clay.UI(clay.ID("field_idea"))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({min = 80, max = 0})}, padding = {top = 10, right = 12, bottom = 10, left = 12}}, backgroundColor = CLAY_BG_INPUT, cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_SM), border = {color = CLAY_INPUT_BORDER if app.selected_field != 0 else CLAY_BORDER_FOCUS, width = clay.BorderOutside(1)}, }) { placeholder := len(app.controller.state.story_idea) == 0 clay_body_text( app.controller.state.story_idea if !placeholder else "Enter your story idea...", color = CLAY_TEXT_TERTIARY if placeholder else CLAY_TEXT_PRIMARY, size = CLAY_FONT_SIZE_SM, ) } clay_label_text("GENRE") if clay.UI(clay.ID("GenreChips"))({ layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 4}, clip = {horizontal = true, childOffset = clay.GetScrollOffset()}, }) { genres := []string{"action", "comedy", "drama", "scifi", "fantasy", "horror", "romance", "mystery", "slice-of-life"} for g in genres { is_sel := app.controller.state.story_genre == g declare_nav_chip(fmt.tprintf("btn_genre_%s", g), g, is_sel) } } clay_label_text("ART STYLE") if clay.UI(clay.ID("ArtStyleChips"))({ layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 4}, clip = {horizontal = true, childOffset = clay.GetScrollOffset()}, }) { styles := []string{"manga", "western-comic", "pixel-art", "watercolor", "noir", "chibi", "sketch", "cyberpunk"} for s in styles { is_sel := app.controller.state.art_style == s declare_nav_chip(fmt.tprintf("btn_style_%s", s), s, is_sel) } } clay_label_text("AUDIENCE") if clay.UI(clay.ID("AudienceChips"))({ layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 4}, clip = {horizontal = true, childOffset = clay.GetScrollOffset()}, }) { auds := []string{"general", "children", "teen", "mature"} for a in auds { is_sel := app.controller.state.target_audience == a declare_nav_chip(fmt.tprintf("btn_aud_%s", a), a, is_sel) } } } if clay.UI(clay.ID("PathCard"))(clay_card_style()) { declare_section_header("PathHeader", "Project Paths", "Configure output locations") clay_label_text("EXPORT PATH") if clay.UI(clay.ID("ExportPathRow"))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 4, childAlignment = {y = .Center}}}) { if clay.UI(clay.ID("field_export"))({ layout = clay_input_layout(), backgroundColor = CLAY_BG_INPUT, cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_SM), border = {color = CLAY_INPUT_BORDER if app.selected_field != 3 else CLAY_BORDER_FOCUS, width = clay.BorderOutside(1)}, }) { display := app.export_path if len(display) == 0 { display = "(not set)" } clay_body_text(display, color = CLAY_TEXT_SECONDARY if len(app.export_path) > 0 else CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_SM) } declare_button_small("btn_browse_export", "Browse") } clay_label_text("PROJECT PATH") if clay.UI(clay.ID("ProjectPathRow"))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 4, childAlignment = {y = .Center}}}) { if clay.UI(clay.ID("field_project"))({ layout = clay_input_layout(), backgroundColor = CLAY_BG_INPUT, cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_SM), border = {color = CLAY_INPUT_BORDER if app.selected_field != 5 else CLAY_BORDER_FOCUS, width = clay.BorderOutside(1)}, }) { display := app.project_path if len(display) == 0 { display = "(not set)" } clay_body_text(display, color = CLAY_TEXT_SECONDARY if len(app.project_path) > 0 else CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_SM) } declare_button_small("btn_browse_project", "Browse") } declare_divider("PathDivider") if clay.UI(clay.ID("StoryConfigRow"))({layout = clay_row_layout()}) { clay_label_text("PAGES") if clay.UI(clay.ID("field_pages"))({ layout = {sizing = {width = clay.SizingFixed(60), height = clay.SizingFixed(f32(CLAY_HEIGHT_SM))}}, backgroundColor = CLAY_BG_INPUT, cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_SM), border = {color = CLAY_INPUT_BORDER if app.selected_field != 4 else CLAY_BORDER_FOCUS, width = clay.BorderOutside(1)}, }) { clay_body_text(app.local_script_pages, size = CLAY_FONT_SIZE_SM) } clay_label_text("FORMAT") declare_nav_chip("btn_pdf", "PDF", app.export_format == .PDF) declare_nav_chip("btn_png", "PNG", app.export_format == .PNG) declare_nav_chip("btn_cbz", "CBZ", app.export_format == .CBZ) } } } declare_characters_workspace :: proc(app: ^GUI_App_State) { char_count := len(app.controller.state.characters) script_char_count := len(app.controller.state.script.characters) if clay.UI(clay.ID("CharsCard"))(clay_card_style()) { declare_section_header("CharsHeader", "Characters", fmt.tprintf("%d characters defined", char_count)) if char_count == 0 { clay_body_text("No characters yet.", color = CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_SM) clay_body_text("Characters are extracted when you generate a script.", color = CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_XS) } else { with_refs := 0 with_templates := 0 for c in app.controller.state.characters { if len(c.reference_image_url) > 0 { with_refs += 1 } if len(c.prompt_template.age) > 0 || len(c.prompt_template.gender) > 0 { with_templates += 1 } } if clay.UI(clay.ID("CharStats"))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 12}}) { declare_stat_chip("stat_chars", "Total", char_count) declare_stat_chip("stat_refs", "Refs", with_refs) declare_stat_chip("stat_tmpl", "Parsed", with_templates) } if clay.UI(clay.ID("CharActionsRow"))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 8}}) { declare_button_small("btn_char_parse_all", "Parse Descriptions") declare_button_primary("btn_char_gen_all", "Generate All Refs") } } if clay.UI(clay.ID("CharsScroll"))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}, layoutDirection = .TopToBottom, childGap = 6}, clip = {vertical = true, childOffset = clay.GetScrollOffset()}, }) { for i in 0.. 0 else "Enter description...", color = CLAY_TEXT_PRIMARY if len(app.char_edit_text) > 0 else CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_SM) } } else { if len(char.description) > 0 { clay_body_text(char.description, color = CLAY_TEXT_SECONDARY, size = CLAY_FONT_SIZE_SM) } else { clay_body_text("No description", color = CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_XS) } } if clay.UI(clay.ID(fmt.tprintf("char_actions_%s", char.id)))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 8}}) { declare_button_small(fmt.tprintf("btn_char_ref_%s", char.id), "Generate Ref") declare_button_small(fmt.tprintf("btn_char_sheet_%s", char.id), "Generate Sheet") } } } } } } character_role_label :: proc(role: core.Character_Role) -> string { switch role { case .Protagonist: return "Protagon." case .Antagonist: return "Antagon." case .Supporting: return "Support." case .Extra: return "Extra" } return "Unknown" } shot_type_label :: proc(st: core.Shot_Type) -> string { switch st { case .Establishing: return "Establishing" case .Wide: return "Wide" case .Medium: return "Medium" case .Close_Up: return "Close Up" case .Extreme_Close_Up: return "Extreme CU" case .Over_Shoulder: return "O/S" case .Aerial: return "Aerial" } return "Unknown" } declare_export_workspace :: proc(app: ^GUI_App_State) { if clay.UI(clay.ID("ExportCard"))(clay_card_style()) { declare_section_header("ExportHeader", "Export", "Package your comic for distribution") ready, total := ready_stage_count(app.controller) all_ready := ready == total panel_count := len(app.controller.state.panel_images) page_count := len(app.controller.state.page_layouts) if clay.UI(clay.ID("ExportStats"))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 12}}) { declare_stat_chip("exp_pages", "Pages", page_count) declare_stat_chip("exp_panels", "Panels", panel_count) declare_stat_chip("exp_ready", "Ready", ready) } clay_body_text(fmt.tprintf("Format: %v", app.controller.state.export_format), color = CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_XS) reason := export_block_reason(app.controller.state) if len(reason) > 0 { declare_info_callout("ExportBlocked", fmt.tprintf("Blocked: %s", reason), false) clay_body_text("Complete all pipeline stages before exporting.", color = CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_XS) } else { declare_info_callout("ExportReady", "All pipeline stages complete. Ready to export!", true) } declare_divider("ExportDivider") if clay.UI(clay.ID("ExportActions"))({layout = {layoutDirection = .LeftToRight, sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({})}, childGap = 8}}) { format := app.controller.state.export_format declare_button_state_export("btn_export_now", "Export as PDF", format == .PDF) declare_button_state_export("btn_export_png", "Export as PNG", format == .PNG) declare_button_state_export("btn_export_cbz", "Export as CBZ", format == .CBZ) } if page_count > 0 { if clay.UI(clay.ID("ExportPagesList"))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}, layoutDirection = .TopToBottom, childGap = 2}, }) { clay_label_text("PAGES") for l in app.controller.state.page_layouts { clay_body_text(fmt.tprintf("Page %d - %s - %d panels", l.page_number, l.pattern_id, len(l.panels)), color = CLAY_TEXT_TERTIARY, size = CLAY_FONT_SIZE_SM) } } } } } declare_button_state_export :: proc(id: string, label: string, is_current_format: bool) { is_hov := clay.Hovered() bg := CLAY_BTN_DEFAULT if is_current_format { bg = CLAY_BTN_SOFT } if is_hov { if is_current_format { bg = CLAY_BTN_SOFT_HOVER } else { bg = CLAY_BTN_DEFAULT_HOVER } } if clay.UI(clay.ID(id))({ layout = clay_button_layout(), backgroundColor = bg, cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_MD), border = {color = CLAY_ACCENT if is_current_format else clay.Color{0, 0, 0, 0}, width = clay.BorderOutside(1)}, }) { clay_body_text(label, color = CLAY_TEXT_BRIGHT if is_current_format else CLAY_TEXT_PRIMARY, size = CLAY_FONT_SIZE_SM) } } declare_community_workspace :: proc(app: ^GUI_App_State) { declare_empty_state("CommunityCard", "Community", "Community features coming soon", "Share and discover comics made with comic-odin") }