diff options
| author | soryu-co <bot@soryu.co> | 2026-04-24 13:15:29 +0000 |
|---|---|---|
| committer | soryu-co <bot@soryu.co> | 2026-04-24 13:21:12 +0000 |
| commit | db092c79a175e3283f479ee0b234b24bde3c736e (patch) | |
| tree | 16ae5ba1f2f2f6089ad9f625953fa02d19463ab0 /makima/ios/Sources/Makima | |
| parent | 3679ceb3325033faa2f889ef3dfee5668ef7aeea (diff) | |
| download | soryu-makima-ios-scaffold.tar.gz soryu-makima-ios-scaffold.zip | |
Add Makima iOS app scaffold (M0 + M1 design system)makima-ios-scaffold
Pure-native SwiftUI client for makima.jp under makima/ios/.
M0 (scaffold)
- XcodeGen project (iOS 18+, Swift 5.10, bundle co.soryu.makima)
- Makefile targets: bootstrap, xcgen, ios-sim-fast, ios-device-fast, test, lint
- GitHub Actions workflow ios-ci.yml — builds + runs XCTest on macos-14
- MIT repo root license already in place
M1 (design system, web-aesthetic port)
- Palette: #0c1729 background, #9bc3ff accent, #3f6fb3 border (ported from Tailwind)
- Typography: SF Mono for chrome, uppercase tracked nav labels
- Components: DashedBorder, GridOverlay, MastheadBar + WebSocketStatus pill,
NavStripPlaceholder (NAV// prefix), JapaneseLongPressText (mobile analogue
of JapaneseHoverText), Logo (reuses frontend/public/logo/makima-logo.svg with
Canvas concentric-ring fallback), Badge
- RootView demo screen: masthead, nav strip, logo, CONTROL SYSTEM badge,
SYSTEM// status card, GLOSSARY// card with 命令/契約/聴取/史料 long-press terms
Auth (v1 plan, not wired here): x-makima-api-key header — verified against
src/server/auth.rs. Authorization: Bearer reserved for v1.1 Supabase OAuth.
v1 plan doc: makima/ios/docs/ios-v1-plan.md
Not in this PR: networking, WebSocket client, stores, feature surfaces
(Home/Contracts/Tasks/Directives/Daemons/Listen), notifications. Those land
across M2-M8 per the plan.
Diffstat (limited to 'makima/ios/Sources/Makima')
17 files changed, 554 insertions, 0 deletions
diff --git a/makima/ios/Sources/Makima/App/Info.plist b/makima/ios/Sources/Makima/App/Info.plist new file mode 100644 index 0000000..39a5741 --- /dev/null +++ b/makima/ios/Sources/Makima/App/Info.plist @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> +</dict> +</plist> diff --git a/makima/ios/Sources/Makima/App/MakimaApp.swift b/makima/ios/Sources/Makima/App/MakimaApp.swift new file mode 100644 index 0000000..907bf8e --- /dev/null +++ b/makima/ios/Sources/Makima/App/MakimaApp.swift @@ -0,0 +1,12 @@ +import SwiftUI + +@main +struct MakimaApp: App { + var body: some Scene { + WindowGroup { + RootView() + .preferredColorScheme(.dark) + .tint(Palette.accent) + } + } +} diff --git a/makima/ios/Sources/Makima/App/RootView.swift b/makima/ios/Sources/Makima/App/RootView.swift new file mode 100644 index 0000000..bb724fc --- /dev/null +++ b/makima/ios/Sources/Makima/App/RootView.swift @@ -0,0 +1,125 @@ +import SwiftUI + +/// Root view for M1. Shows the masthead + a placeholder "system online" card +/// so we can judge the aesthetic port against makima.jp side-by-side. +struct RootView: View { + var body: some View { + ZStack { + Palette.background.ignoresSafeArea() + GridOverlay() + + VStack(spacing: 0) { + MastheadBar( + serverLabel: "makima.jp", + wsStatus: .idle, + version: Bundle.main.shortVersion + ) + NavStripPlaceholder() + + ScrollView { + VStack(spacing: 24) { + Spacer(minLength: 32) + + Logo(size: 140) + + VStack(spacing: 6) { + Badge(text: "支配する", subtitle: "CONTROL SYSTEM") + Text("Mesh Orchestration Platform") + .font(Typography.titleChrome) + .foregroundStyle(Palette.foreground) + .tracking(1) + Text("Makima is listening.") + .font(Typography.body) + .foregroundStyle(Palette.foregroundMuted) + } + + statusCard + .padding(.horizontal, 16) + + languageDemoCard + .padding(.horizontal, 16) + + Spacer(minLength: 40) + } + .padding(.top, 12) + } + } + } + } + + private var statusCard: some View { + VStack(alignment: .leading, spacing: 10) { + HStack { + Text("SYSTEM//") + .font(Typography.navLabel) + .foregroundStyle(Palette.foregroundMuted) + Spacer() + Text("M0 + M1") + .font(Typography.navLabel) + .foregroundStyle(Palette.accent) + } + Divider().overlay(Palette.borderMuted) + ForEach(StatusRow.samples) { row in + HStack { + Circle() + .fill(row.ok ? Palette.ok : Palette.warn) + .frame(width: 6, height: 6) + Text(row.label) + .font(Typography.body) + .foregroundStyle(Palette.foreground) + Spacer() + Text(row.value) + .font(Typography.mono) + .foregroundStyle(Palette.foregroundMuted) + } + } + } + .padding(14) + .dashedBorder() + } + + private var languageDemoCard: some View { + VStack(alignment: .leading, spacing: 8) { + Text("GLOSSARY//") + .font(Typography.navLabel) + .foregroundStyle(Palette.foregroundMuted) + Divider().overlay(Palette.borderMuted) + VStack(alignment: .leading, spacing: 8) { + JapaneseLongPressText(japanese: "命令", english: "Directives") + JapaneseLongPressText(japanese: "契約", english: "Contracts") + JapaneseLongPressText(japanese: "聴取", english: "Listen") + JapaneseLongPressText(japanese: "史料", english: "History") + } + Text("Long-press any term to reveal the English gloss.") + .font(Typography.caption) + .foregroundStyle(Palette.foregroundMuted) + .padding(.top, 4) + } + .padding(14) + .dashedBorder() + } +} + +private struct StatusRow: Identifiable { + let id = UUID() + let label: String + let value: String + let ok: Bool + + static let samples: [StatusRow] = [ + StatusRow(label: "Scaffold", value: "READY", ok: true), + StatusRow(label: "Design Sys", value: "M1", ok: true), + StatusRow(label: "Network", value: "NOT WIRED", ok: false), + StatusRow(label: "WebSocket", value: "NOT WIRED", ok: false) + ] +} + +private extension Bundle { + var shortVersion: String { + (infoDictionary?["CFBundleShortVersionString"] as? String) ?? "0.0.0" + } +} + +#Preview { + RootView() +} diff --git a/makima/ios/Sources/Makima/Design/Components/Badge.swift b/makima/ios/Sources/Makima/Design/Components/Badge.swift new file mode 100644 index 0000000..4c870a7 --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Components/Badge.swift @@ -0,0 +1,28 @@ +import SwiftUI + +/// Small inline badge — mirrors the web's +/// `px-2 py-1 border border-[#3f6fb3] bg-[#0f1c2f] text-[#9bc3ff] font-mono text-xs tracking-wide uppercase` +struct Badge: View { + let text: String + var subtitle: String? + + var body: some View { + HStack(spacing: 6) { + Text(text) + .font(.system(.footnote, design: .default)) + .foregroundStyle(Palette.accent) + if let subtitle { + Text("·") + .font(Typography.navLabel) + .foregroundStyle(Palette.borderMuted) + Text(subtitle) + .font(Typography.navLabel) + .foregroundStyle(Palette.foregroundMuted) + } + } + .padding(.horizontal, 8) + .padding(.vertical, 4) + .background(Palette.panel) + .overlay(Rectangle().strokeBorder(Palette.border, lineWidth: 1)) + } +} diff --git a/makima/ios/Sources/Makima/Design/Components/DashedBorder.swift b/makima/ios/Sources/Makima/Design/Components/DashedBorder.swift new file mode 100644 index 0000000..c0af431 --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Components/DashedBorder.swift @@ -0,0 +1,24 @@ +import SwiftUI + +/// Mirrors Tailwind's `border-dashed border-[rgba(117,170,252,0.35)]`. +struct DashedBorderModifier: ViewModifier { + var color: Color = Palette.borderMuted + var dash: [CGFloat] = [4, 4] + var cornerRadius: CGFloat = 0 + + func body(content: Content) -> some View { + content + .overlay( + RoundedRectangle(cornerRadius: cornerRadius) + .strokeBorder(color, style: StrokeStyle(lineWidth: 1, dash: dash)) + ) + } +} + +extension View { + func dashedBorder(color: Color = Palette.borderMuted, + dash: [CGFloat] = [4, 4], + cornerRadius: CGFloat = 0) -> some View { + modifier(DashedBorderModifier(color: color, dash: dash, cornerRadius: cornerRadius)) + } +} diff --git a/makima/ios/Sources/Makima/Design/Components/GridOverlay.swift b/makima/ios/Sources/Makima/Design/Components/GridOverlay.swift new file mode 100644 index 0000000..824d0b2 --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Components/GridOverlay.swift @@ -0,0 +1,29 @@ +import SwiftUI + +/// Subtle grid, mirrors the makima.jp body background texture. +/// Drawn as a `Canvas` so there's no asset dependency. +struct GridOverlay: View { + var spacing: CGFloat = 32 + var opacity: Double = 0.04 + + var body: some View { + Canvas { ctx, size in + let color = GraphicsContext.Shading.color(.white.opacity(opacity)) + var path = Path() + var x = spacing + while x < size.width { + path.move(to: CGPoint(x: x, y: 0)) + path.addLine(to: CGPoint(x: x, y: size.height)) + x += spacing + } + var y = spacing + while y < size.height { + path.move(to: CGPoint(x: 0, y: y)) + path.addLine(to: CGPoint(x: size.width, y: y)) + y += spacing + } + ctx.stroke(path, with: color, lineWidth: 0.5) + } + .allowsHitTesting(false) + } +} diff --git a/makima/ios/Sources/Makima/Design/Components/JapaneseLongPressText.swift b/makima/ios/Sources/Makima/Design/Components/JapaneseLongPressText.swift new file mode 100644 index 0000000..fb57154 --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Components/JapaneseLongPressText.swift @@ -0,0 +1,37 @@ +import SwiftUI + +/// Mobile-native equivalent of the web's `JapaneseHoverText`. +/// Shows the Japanese term; long-press (or tap) reveals the English gloss +/// via a brief animated flip. +struct JapaneseLongPressText: View { + let japanese: String + let english: String + + @State private var revealed = false + + var body: some View { + HStack(spacing: 6) { + Text(japanese) + .font(Typography.japanese) + .foregroundStyle(Palette.foreground) + .padding(.vertical, 3) + .padding(.horizontal, 6) + .background(Palette.panel) + .overlay( + Rectangle().strokeBorder(Palette.borderMuted, lineWidth: 1) + ) + .contentShape(Rectangle()) + .onTapGesture { withAnimation(.easeInOut(duration: 0.2)) { revealed.toggle() } } + .onLongPressGesture(minimumDuration: 0.15, pressing: { pressing in + withAnimation(.easeInOut(duration: 0.15)) { revealed = pressing } + }, perform: {}) + + Text(english) + .font(Typography.navLabel) + .foregroundStyle(revealed ? Palette.accent : Palette.foregroundMuted.opacity(0.4)) + .animation(.easeInOut(duration: 0.2), value: revealed) + } + .accessibilityElement(children: .combine) + .accessibilityLabel("\(japanese), \(english)") + } +} diff --git a/makima/ios/Sources/Makima/Design/Components/Logo.swift b/makima/ios/Sources/Makima/Design/Components/Logo.swift new file mode 100644 index 0000000..01d263e --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Components/Logo.swift @@ -0,0 +1,51 @@ +import SwiftUI + +/// Makima concentric-ring logo. +/// Loads from bundled `makima-logo.svg` if present; otherwise falls back to +/// a Canvas-rendered concentric-ring approximation so the app always builds +/// even if the SVG copy step is skipped. +struct Logo: View { + var size: CGFloat = 120 + + var body: some View { + Group { + if let uiImage = Self.loadedSVG(named: "makima-logo") { + Image(uiImage: uiImage) + .resizable() + .renderingMode(.template) + .foregroundStyle(Palette.accent) + } else { + Canvas { ctx, canvasSize in + let center = CGPoint(x: canvasSize.width / 2, y: canvasSize.height / 2) + let maxR = min(canvasSize.width, canvasSize.height) / 2 + let rings = 5 + for i in 0..<rings { + let t = CGFloat(i + 1) / CGFloat(rings) + let r = maxR * t + let rect = CGRect(x: center.x - r, y: center.y - r, + width: r * 2, height: r * 2) + let shading = GraphicsContext.Shading.color( + Palette.accent.opacity(1.0 - Double(i) * 0.15) + ) + ctx.stroke(Circle().path(in: rect), with: shading, lineWidth: 1.25) + } + let dotR = maxR * 0.06 + ctx.fill(Circle().path(in: CGRect(x: center.x - dotR, y: center.y - dotR, + width: dotR * 2, height: dotR * 2)), + with: .color(Palette.accent)) + } + } + } + .frame(width: size, height: size) + .accessibilityLabel("Makima") + } + + /// SwiftUI 18 doesn't natively decode SVG through UIImage, so we try PDF + /// fallback first (Xcode auto-converts SVGs placed in asset catalogs to PDF). + /// If the file ships as a raw `.svg` bundle resource, we decline and fall back + /// to the Canvas drawing. This keeps M1 buildable without additional deps. + private static func loadedSVG(named name: String) -> UIImage? { + if let img = UIImage(named: name) { return img } + return nil + } +} diff --git a/makima/ios/Sources/Makima/Design/Components/MastheadBar.swift b/makima/ios/Sources/Makima/Design/Components/MastheadBar.swift new file mode 100644 index 0000000..a304f95 --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Components/MastheadBar.swift @@ -0,0 +1,100 @@ +import SwiftUI + +enum WebSocketStatus { + case idle, connecting, online, offline + + var label: String { + switch self { + case .idle: return "WS//IDLE" + case .connecting: return "WS//…" + case .online: return "WS//ONLINE" + case .offline: return "WS//OFFLINE" + } + } + + var color: Color { + switch self { + case .idle: return Palette.foregroundMuted + case .connecting: return Palette.warn + case .online: return Palette.ok + case .offline: return Palette.danger + } + } +} + +/// Top chrome strip, replaces a traditional nav bar. +/// Composition: small logo + "MAKIMA" brand + spacer + ws-pill + server label + version. +struct MastheadBar: View { + let serverLabel: String + let wsStatus: WebSocketStatus + let version: String + + var body: some View { + HStack(spacing: 10) { + Logo(size: 22) + Text("MAKIMA") + .font(.system(.caption, design: .monospaced).weight(.semibold)) + .tracking(2) + .foregroundStyle(Palette.foreground) + + Spacer(minLength: 8) + + Text(wsStatus.label) + .font(Typography.navLabel) + .foregroundStyle(wsStatus.color) + Text("·") + .foregroundStyle(Palette.borderMuted) + Text(serverLabel) + .font(Typography.navLabel) + .foregroundStyle(Palette.accent) + Text("·") + .foregroundStyle(Palette.borderMuted) + Text("v\(version)") + .font(Typography.navLabel) + .foregroundStyle(Palette.foregroundMuted) + } + .padding(.horizontal, 14) + .padding(.vertical, 10) + .background( + LinearGradient( + colors: [Palette.backgroundDeep.opacity(0.95), Palette.panel.opacity(0.7)], + startPoint: .top, endPoint: .bottom + ) + ) + .overlay(alignment: .bottom) { + Rectangle().fill(Palette.border).frame(height: 2) + } + } +} + +struct NavStripPlaceholder: View { + private let labels = ["LISTEN", "DIRECTIVES", "ORDERS", "CONTRACTS", "DAEMONS", "HISTORY"] + + var body: some View { + HStack(spacing: 10) { + Text("NAV//") + .font(Typography.navLabel) + .foregroundStyle(Palette.accent) + .padding(.trailing, 4) + .overlay(alignment: .trailing) { + Rectangle().fill(Palette.borderMuted).frame(width: 1, height: 14) + .offset(x: 4) + } + ForEach(labels, id: \.self) { l in + Text(l) + .font(Typography.navLabel) + .foregroundStyle(Palette.accent.opacity(0.8)) + } + Spacer() + } + .padding(.horizontal, 12) + .padding(.vertical, 10) + .background(Palette.panel) + .overlay(alignment: .top) { + Rectangle().fill(Palette.borderMuted).frame(height: 1) + } + .overlay(alignment: .bottom) { + Rectangle().fill(Palette.borderMuted).frame(height: 1) + } + } +} diff --git a/makima/ios/Sources/Makima/Design/Palette.swift b/makima/ios/Sources/Makima/Design/Palette.swift new file mode 100644 index 0000000..abb531d --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Palette.swift @@ -0,0 +1,41 @@ +import SwiftUI + +/// Central color palette, ported from the makima.jp Tailwind config. +/// Keep in lockstep with `frontend/src/index.css` and component classes. +enum Palette { + /// `#0c1729` — app background + static let background = Color(hex: 0x0C1729) + /// Slightly lighter panel inset (`#0f1c2f`) + static let panel = Color(hex: 0x0F1C2F) + /// Deeper backdrop used behind masthead gradients + static let backgroundDeep = Color(hex: 0x0B1220) + /// `#f0f5ff` — brightest foreground (titles) + static let foreground = Color(hex: 0xF0F5FF) + /// `#9bc3ff` — primary foreground (nav, labels) + static let accent = Color(hex: 0x9BC3FF) + /// `#dbe7ff` — body text + static let body = Color(hex: 0xDBE7FF) + /// `#e4edff` — softer body + static let bodySoft = Color(hex: 0xE4EDFF) + /// Muted / secondary foreground + static let foregroundMuted = Color(hex: 0x9BC3FF).opacity(0.65) + /// `#3f6fb3` — primary border + static let border = Color(hex: 0x3F6FB3) + /// Subtle dashed-border tint (`rgba(117,170,252,0.35)`) + static let borderMuted = Color(red: 117/255, green: 170/255, blue: 252/255).opacity(0.35) + /// Amber alert (pending questions) + static let warn = Color(hex: 0xF59E0B) + /// OK / running + static let ok = Color(hex: 0x4ADE80) + /// Error / failed + static let danger = Color(hex: 0xF87171) +} + +extension Color { + init(hex: UInt32, alpha: Double = 1.0) { + let r = Double((hex >> 16) & 0xFF) / 255 + let g = Double((hex >> 8) & 0xFF) / 255 + let b = Double( hex & 0xFF) / 255 + self.init(.sRGB, red: r, green: g, blue: b, opacity: alpha) + } +} diff --git a/makima/ios/Sources/Makima/Design/Typography.swift b/makima/ios/Sources/Makima/Design/Typography.swift new file mode 100644 index 0000000..d697834 --- /dev/null +++ b/makima/ios/Sources/Makima/Design/Typography.swift @@ -0,0 +1,16 @@ +import SwiftUI + +enum Typography { + /// SF Mono, uppercase, tracked — used for NAV// prefixes, section labels + static let navLabel = Font.system(.caption2, design: .monospaced).weight(.medium) + /// Section titles ("Mesh Orchestration Platform") + static let titleChrome = Font.system(size: 20, weight: .medium, design: .default) + /// Body text + static let body = Font.system(.body, design: .default) + /// Caption-level body + static let caption = Font.system(.caption, design: .default) + /// Inline monospace (values, IDs, hostnames) + static let mono = Font.system(.footnote, design: .monospaced) + /// Japanese hover/long-press words + static let japanese = Font.system(size: 15, weight: .regular, design: .default) +} diff --git a/makima/ios/Sources/Makima/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/makima/ios/Sources/Makima/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..caefc04 --- /dev/null +++ b/makima/ios/Sources/Makima/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images": [ + { + "idiom": "universal", + "platform": "ios", + "size": "1024x1024" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +}
\ No newline at end of file diff --git a/makima/ios/Sources/Makima/Resources/Assets.xcassets/BrandAccent.colorset/Contents.json b/makima/ios/Sources/Makima/Resources/Assets.xcassets/BrandAccent.colorset/Contents.json new file mode 100644 index 0000000..81e0580 --- /dev/null +++ b/makima/ios/Sources/Makima/Resources/Assets.xcassets/BrandAccent.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors": [ + { + "idiom": "universal", + "color": { + "color-space": "srgb", + "components": { + "red": "0.608", + "green": "0.765", + "blue": "1.000", + "alpha": "1.000" + } + } + } + ], + "info": { + "author": "xcode", + "version": 1 + } +}
\ No newline at end of file diff --git a/makima/ios/Sources/Makima/Resources/Assets.xcassets/BrandBackground.colorset/Contents.json b/makima/ios/Sources/Makima/Resources/Assets.xcassets/BrandBackground.colorset/Contents.json new file mode 100644 index 0000000..64d84a0 --- /dev/null +++ b/makima/ios/Sources/Makima/Resources/Assets.xcassets/BrandBackground.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors": [ + { + "idiom": "universal", + "color": { + "color-space": "srgb", + "components": { + "red": "0.047", + "green": "0.090", + "blue": "0.161", + "alpha": "1.000" + } + } + } + ], + "info": { + "author": "xcode", + "version": 1 + } +}
\ No newline at end of file diff --git a/makima/ios/Sources/Makima/Resources/Assets.xcassets/Contents.json b/makima/ios/Sources/Makima/Resources/Assets.xcassets/Contents.json new file mode 100644 index 0000000..c47b5f2 --- /dev/null +++ b/makima/ios/Sources/Makima/Resources/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "author": "xcode", + "version": 1 + } +}
\ No newline at end of file diff --git a/makima/ios/Sources/Makima/Resources/Logo/makima-icon-red.svg b/makima/ios/Sources/Makima/Resources/Logo/makima-icon-red.svg new file mode 100644 index 0000000..ec21830 --- /dev/null +++ b/makima/ios/Sources/Makima/Resources/Logo/makima-icon-red.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" aria-hidden="true"> + <circle cx="12" cy="12" r="9.5" stroke="#b30000" stroke-width="2" /> + <circle cx="12" cy="12" r="6.5" stroke="#b30000" stroke-width="1.6" /> + <circle cx="12" cy="12" r="3.6" stroke="#b30000" stroke-width="1.6" /> + <circle cx="12" cy="12" r="1.4" fill="#b30000" /> +</svg> diff --git a/makima/ios/Sources/Makima/Resources/Logo/makima-logo.svg b/makima/ios/Sources/Makima/Resources/Logo/makima-logo.svg new file mode 100644 index 0000000..4872d43 --- /dev/null +++ b/makima/ios/Sources/Makima/Resources/Logo/makima-logo.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"> + <circle cx="12" cy="12" r="10" stroke="#003366" stroke-width="2" /> + <circle cx="12" cy="12" r="7" stroke="#003366" stroke-width="1.6" /> + <circle cx="12" cy="12" r="4" stroke="#003366" stroke-width="1.6" /> + <circle cx="12" cy="12" r="1.6" fill="#003366" /> +</svg> |
