fix: Rename pkd_codes column to ceidg_pkd_list to avoid backref conflict
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
13
blueprints/CLAUDE.md
Normal file
@ -0,0 +1,13 @@
|
||||
<claude-mem-context>
|
||||
# Recent Activity
|
||||
|
||||
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
||||
|
||||
### Jan 31, 2026
|
||||
|
||||
| ID | Time | T | Title | Read |
|
||||
|----|------|---|-------|------|
|
||||
| #248 | 6:33 PM | 🔵 | Nordabiz register_blueprints() function implements phased migration with 407 lines of endpoint aliasing for backward compatibility | ~1102 |
|
||||
| #180 | 6:25 PM | 🔵 | Nordabiz project architecture analyzed revealing 16+ Flask blueprints with modular organization | ~831 |
|
||||
| #166 | 6:23 PM | 🔵 | Nordabiz implements phased blueprint registration with backward-compatible endpoint aliases | ~801 |
|
||||
</claude-mem-context>
|
||||
14
blueprints/admin/CLAUDE.md
Normal file
@ -0,0 +1,14 @@
|
||||
<claude-mem-context>
|
||||
# Recent Activity
|
||||
|
||||
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
||||
|
||||
### Jan 31, 2026
|
||||
|
||||
| ID | Time | T | Title | Read |
|
||||
|----|------|---|-------|------|
|
||||
| #250 | 6:33 PM | 🔵 | Nordabiz admin blueprint imports 14 separate routes modules demonstrating extreme modularization | ~677 |
|
||||
| #180 | 6:25 PM | 🔵 | Nordabiz project architecture analyzed revealing 16+ Flask blueprints with modular organization | ~831 |
|
||||
| #170 | 6:23 PM | 🔵 | Nordabiz admin routes handle recommendations moderation with Polish localization | ~713 |
|
||||
| #168 | " | 🔵 | Nordabiz admin blueprint splits functionality across 15 route modules | ~726 |
|
||||
</claude-mem-context>
|
||||
12
blueprints/api/CLAUDE.md
Normal file
@ -0,0 +1,12 @@
|
||||
<claude-mem-context>
|
||||
# Recent Activity
|
||||
|
||||
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
||||
|
||||
### Jan 31, 2026
|
||||
|
||||
| ID | Time | T | Title | Read |
|
||||
|----|------|---|-------|------|
|
||||
| #245 | 6:33 PM | 🔵 | Nordabiz API blueprint aggregates 7 specialized route modules for frontend interactions | ~574 |
|
||||
| #180 | 6:25 PM | 🔵 | Nordabiz project architecture analyzed revealing 16+ Flask blueprints with modular organization | ~831 |
|
||||
</claude-mem-context>
|
||||
7
blueprints/auth/CLAUDE.md
Normal file
@ -0,0 +1,7 @@
|
||||
<claude-mem-context>
|
||||
# Recent Activity
|
||||
|
||||
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
||||
|
||||
*No recent activity*
|
||||
</claude-mem-context>
|
||||
12
blueprints/public/CLAUDE.md
Normal file
@ -0,0 +1,12 @@
|
||||
<claude-mem-context>
|
||||
# Recent Activity
|
||||
|
||||
<!-- This section is auto-generated by claude-mem. Edit content outside the tags. -->
|
||||
|
||||
### Jan 31, 2026
|
||||
|
||||
| ID | Time | T | Title | Read |
|
||||
|----|------|---|-------|------|
|
||||
| #180 | 6:25 PM | 🔵 | Nordabiz project architecture analyzed revealing 16+ Flask blueprints with modular organization | ~831 |
|
||||
| #169 | 6:23 PM | 🔵 | Nordabiz public blueprint organized into three route modules for homepage, ZOPK integration, and announcements | ~551 |
|
||||
</claude-mem-context>
|
||||
BIN
data/ceidg_search_results/ceidg_debug_95.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
18
data/ceidg_search_results/ceidg_search_20260201_070809.json
Normal file
@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"company_id": 119,
|
||||
"company_name": "3W",
|
||||
"search_query": "3W",
|
||||
"found_nip": null,
|
||||
"found_regon": null,
|
||||
"found_name": null,
|
||||
"found_owner": null,
|
||||
"found_address": null,
|
||||
"found_status": null,
|
||||
"matches": [],
|
||||
"confidence": "low",
|
||||
"verified": false,
|
||||
"error": "Timeout",
|
||||
"searched_at": "2026-02-01T07:07:32.763556"
|
||||
}
|
||||
]
|
||||
18
data/ceidg_search_results/ceidg_search_20260201_071218.json
Normal file
@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"company_id": 95,
|
||||
"company_name": "Kancelaria Notarialna Henryk Mizak",
|
||||
"search_query": "Kancelaria Notarialna Henryk Mizak",
|
||||
"found_nip": null,
|
||||
"found_regon": null,
|
||||
"found_name": null,
|
||||
"found_owner": null,
|
||||
"found_address": null,
|
||||
"found_status": null,
|
||||
"matches": [],
|
||||
"confidence": "low",
|
||||
"verified": false,
|
||||
"error": "Nie znaleziono pola wyszukiwania. Screenshot: /Users/maciejpi/claude/projects/active/nordabiz/data/ceidg_search_results/ceidg_debug_95.png",
|
||||
"searched_at": "2026-02-01T07:12:10.623430"
|
||||
}
|
||||
]
|
||||
19
data/nip_scan_results/scan_20260201_065905.json
Normal file
@ -0,0 +1,19 @@
|
||||
[
|
||||
{
|
||||
"company_id": 113,
|
||||
"company_name": "Piotrex",
|
||||
"domain": "piotrex.info",
|
||||
"url_scanned": "https://piotrex.info/kontakt",
|
||||
"nip_found": "5881846715",
|
||||
"regon_found": null,
|
||||
"nips_all": [
|
||||
"5881846715"
|
||||
],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T06:59:00.521605"
|
||||
}
|
||||
]
|
||||
331
data/nip_scan_results/scan_20260201_070032.json
Normal file
@ -0,0 +1,331 @@
|
||||
[
|
||||
{
|
||||
"company_id": 119,
|
||||
"company_name": "3W",
|
||||
"domain": "3wdb.pl",
|
||||
"url_scanned": "https://3wdb.pl/o-nas",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:12.777529"
|
||||
},
|
||||
{
|
||||
"company_id": 121,
|
||||
"company_name": "BIS Maszyny",
|
||||
"domain": "bis-bau.pl",
|
||||
"url_scanned": "https://bis-bau.pl/o-nas",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:17.025257"
|
||||
},
|
||||
{
|
||||
"company_id": 93,
|
||||
"company_name": "Dom Dziecka Pro-Sport",
|
||||
"domain": "prosport.wejher.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:24.231589"
|
||||
},
|
||||
{
|
||||
"company_id": 122,
|
||||
"company_name": "Elgreen EM",
|
||||
"domain": "elgreen.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:26.087690"
|
||||
},
|
||||
{
|
||||
"company_id": 117,
|
||||
"company_name": "Elzit",
|
||||
"domain": "elzit.pl",
|
||||
"url_scanned": "https://elzit.pl",
|
||||
"nip_found": "9581160890",
|
||||
"regon_found": "191427842",
|
||||
"nips_all": [
|
||||
"9581160890"
|
||||
],
|
||||
"regons_all": [
|
||||
"191427842"
|
||||
],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T06:59:27.702428"
|
||||
},
|
||||
{
|
||||
"company_id": 94,
|
||||
"company_name": "Event Investycje",
|
||||
"domain": "bombera.pl",
|
||||
"url_scanned": "https://bombera.pl",
|
||||
"nip_found": "5892024537",
|
||||
"regon_found": null,
|
||||
"nips_all": [
|
||||
"5892024537"
|
||||
],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T06:59:30.031341"
|
||||
},
|
||||
{
|
||||
"company_id": 112,
|
||||
"company_name": "Informatyk1",
|
||||
"domain": "informatyk1.pl",
|
||||
"url_scanned": "https://informatyk1.pl/about",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:32.687646"
|
||||
},
|
||||
{
|
||||
"company_id": 123,
|
||||
"company_name": "Iwona Spaleniak Coaching",
|
||||
"domain": "iwonaspaleniak.pl",
|
||||
"url_scanned": "https://iwonaspaleniak.pl/about",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:37.620806"
|
||||
},
|
||||
{
|
||||
"company_id": 114,
|
||||
"company_name": "Kancelaria Ostrowski i Wspólnicy",
|
||||
"domain": "ostrowski-legal.net",
|
||||
"url_scanned": "https://ostrowski-legal.net",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:48.733603"
|
||||
},
|
||||
{
|
||||
"company_id": 124,
|
||||
"company_name": "Kaszubia 2030",
|
||||
"domain": "kaszubia2030.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:51.434997"
|
||||
},
|
||||
{
|
||||
"company_id": 111,
|
||||
"company_name": "Nowatel",
|
||||
"domain": "nowatel.com",
|
||||
"url_scanned": "https://nowatel.com",
|
||||
"nip_found": "5932407062",
|
||||
"regon_found": null,
|
||||
"nips_all": [
|
||||
"5932407062"
|
||||
],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T06:59:52.617348"
|
||||
},
|
||||
{
|
||||
"company_id": 110,
|
||||
"company_name": "Omega Energy",
|
||||
"domain": "omega-energy.eu",
|
||||
"url_scanned": "https://www.omega-energy.eu",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:53.838239"
|
||||
},
|
||||
{
|
||||
"company_id": 96,
|
||||
"company_name": "Orlex Design",
|
||||
"domain": "orlexbeton.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T06:59:57.143298"
|
||||
},
|
||||
{
|
||||
"company_id": 113,
|
||||
"company_name": "Piotrex",
|
||||
"domain": "piotrex.info",
|
||||
"url_scanned": "https://piotrex.info/kontakt",
|
||||
"nip_found": "5881846715",
|
||||
"regon_found": null,
|
||||
"nips_all": [
|
||||
"5881846715"
|
||||
],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T06:59:58.758426"
|
||||
},
|
||||
{
|
||||
"company_id": 98,
|
||||
"company_name": "Podróże i My",
|
||||
"domain": "itakarumia.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:02.539004"
|
||||
},
|
||||
{
|
||||
"company_id": 100,
|
||||
"company_name": "PZU TFI",
|
||||
"domain": "pzu.pl",
|
||||
"url_scanned": "https://www.pzu.pl",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:04.298279"
|
||||
},
|
||||
{
|
||||
"company_id": 116,
|
||||
"company_name": "Renk Hurtownie",
|
||||
"domain": "renk.pl",
|
||||
"url_scanned": "https://renk.pl/kontakt",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:08.159123"
|
||||
},
|
||||
{
|
||||
"company_id": 101,
|
||||
"company_name": "Rozsądni Bracia",
|
||||
"domain": "rozsandnibracia.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:14.494471"
|
||||
},
|
||||
{
|
||||
"company_id": 102,
|
||||
"company_name": "TERMO",
|
||||
"domain": "termocenter.pl",
|
||||
"url_scanned": "https://termocenter.pl/about",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:15.685339"
|
||||
},
|
||||
{
|
||||
"company_id": 109,
|
||||
"company_name": "Unimot",
|
||||
"domain": "unimot-eig.pl",
|
||||
"url_scanned": "https://unimot-eig.pl",
|
||||
"nip_found": "9730421440",
|
||||
"regon_found": "970619205",
|
||||
"nips_all": [
|
||||
"9730421440"
|
||||
],
|
||||
"regons_all": [
|
||||
"970619205"
|
||||
],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T07:00:24.581291"
|
||||
},
|
||||
{
|
||||
"company_id": 118,
|
||||
"company_name": "Your Welcome",
|
||||
"domain": "yourewelcome.pl",
|
||||
"url_scanned": "https://yourewelcome.pl/o-nas",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:26.083523"
|
||||
}
|
||||
]
|
||||
331
data/nip_scan_results/scan_20260201_070155.json
Normal file
@ -0,0 +1,331 @@
|
||||
[
|
||||
{
|
||||
"company_id": 119,
|
||||
"company_name": "3W",
|
||||
"domain": "3wdb.pl",
|
||||
"url_scanned": "https://3wdb.pl/o-nas",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:40.822770"
|
||||
},
|
||||
{
|
||||
"company_id": 121,
|
||||
"company_name": "BIS Maszyny",
|
||||
"domain": "bis-bau.pl",
|
||||
"url_scanned": "https://bis-bau.pl/o-nas",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:44.927095"
|
||||
},
|
||||
{
|
||||
"company_id": 93,
|
||||
"company_name": "Dom Dziecka Pro-Sport",
|
||||
"domain": "prosport.wejher.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:52.609620"
|
||||
},
|
||||
{
|
||||
"company_id": 122,
|
||||
"company_name": "Elgreen EM",
|
||||
"domain": "elgreen.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:00:54.221059"
|
||||
},
|
||||
{
|
||||
"company_id": 117,
|
||||
"company_name": "Elzit",
|
||||
"domain": "elzit.pl",
|
||||
"url_scanned": "https://elzit.pl",
|
||||
"nip_found": "9581160890",
|
||||
"regon_found": "191427842",
|
||||
"nips_all": [
|
||||
"9581160890"
|
||||
],
|
||||
"regons_all": [
|
||||
"191427842"
|
||||
],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T07:00:55.749843"
|
||||
},
|
||||
{
|
||||
"company_id": 94,
|
||||
"company_name": "Event Investycje",
|
||||
"domain": "bombera.pl",
|
||||
"url_scanned": "https://bombera.pl",
|
||||
"nip_found": "5892024537",
|
||||
"regon_found": null,
|
||||
"nips_all": [
|
||||
"5892024537"
|
||||
],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T07:00:58.050212"
|
||||
},
|
||||
{
|
||||
"company_id": 112,
|
||||
"company_name": "Informatyk1",
|
||||
"domain": "informatyk1.pl",
|
||||
"url_scanned": "https://informatyk1.pl/about",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:00.371984"
|
||||
},
|
||||
{
|
||||
"company_id": 123,
|
||||
"company_name": "Iwona Spaleniak Coaching",
|
||||
"domain": "iwonaspaleniak.pl",
|
||||
"url_scanned": "https://iwonaspaleniak.pl/about",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:05.234668"
|
||||
},
|
||||
{
|
||||
"company_id": 114,
|
||||
"company_name": "Kancelaria Ostrowski i Wspólnicy",
|
||||
"domain": "ostrowski-legal.net",
|
||||
"url_scanned": "https://ostrowski-legal.net",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:16.190843"
|
||||
},
|
||||
{
|
||||
"company_id": 124,
|
||||
"company_name": "Kaszubia 2030",
|
||||
"domain": "kaszubia2030.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:18.672999"
|
||||
},
|
||||
{
|
||||
"company_id": 111,
|
||||
"company_name": "Nowatel",
|
||||
"domain": "nowatel.com",
|
||||
"url_scanned": "https://nowatel.com",
|
||||
"nip_found": "5932407062",
|
||||
"regon_found": null,
|
||||
"nips_all": [
|
||||
"5932407062"
|
||||
],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T07:01:19.699237"
|
||||
},
|
||||
{
|
||||
"company_id": 110,
|
||||
"company_name": "Omega Energy",
|
||||
"domain": "omega-energy.eu",
|
||||
"url_scanned": "https://www.omega-energy.eu",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:20.870985"
|
||||
},
|
||||
{
|
||||
"company_id": 96,
|
||||
"company_name": "Orlex Design",
|
||||
"domain": "orlexbeton.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:24.345116"
|
||||
},
|
||||
{
|
||||
"company_id": 113,
|
||||
"company_name": "Piotrex",
|
||||
"domain": "piotrex.info",
|
||||
"url_scanned": "https://piotrex.info/kontakt",
|
||||
"nip_found": "5881846715",
|
||||
"regon_found": null,
|
||||
"nips_all": [
|
||||
"5881846715"
|
||||
],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T07:01:25.806602"
|
||||
},
|
||||
{
|
||||
"company_id": 98,
|
||||
"company_name": "Podróże i My",
|
||||
"domain": "itakarumia.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:29.373428"
|
||||
},
|
||||
{
|
||||
"company_id": 100,
|
||||
"company_name": "PZU TFI",
|
||||
"domain": "pzu.pl",
|
||||
"url_scanned": "https://www.pzu.pl",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:30.817174"
|
||||
},
|
||||
{
|
||||
"company_id": 116,
|
||||
"company_name": "Renk Hurtownie",
|
||||
"domain": "renk.pl",
|
||||
"url_scanned": "https://renk.pl/kontakt",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:34.485235"
|
||||
},
|
||||
{
|
||||
"company_id": 101,
|
||||
"company_name": "Rozsądni Bracia",
|
||||
"domain": "rozsandnibracia.pl",
|
||||
"url_scanned": "",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:40.789330"
|
||||
},
|
||||
{
|
||||
"company_id": 102,
|
||||
"company_name": "TERMO",
|
||||
"domain": "termocenter.pl",
|
||||
"url_scanned": "https://termocenter.pl/about",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:41.822554"
|
||||
},
|
||||
{
|
||||
"company_id": 109,
|
||||
"company_name": "Unimot",
|
||||
"domain": "unimot-eig.pl",
|
||||
"url_scanned": "https://unimot-eig.pl",
|
||||
"nip_found": "9730421440",
|
||||
"regon_found": "970619205",
|
||||
"nips_all": [
|
||||
"9730421440"
|
||||
],
|
||||
"regons_all": [
|
||||
"970619205"
|
||||
],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "high",
|
||||
"error": null,
|
||||
"scanned_at": "2026-02-01T07:01:47.902680"
|
||||
},
|
||||
{
|
||||
"company_id": 118,
|
||||
"company_name": "Your Welcome",
|
||||
"domain": "yourewelcome.pl",
|
||||
"url_scanned": "https://yourewelcome.pl/o-nas",
|
||||
"nip_found": null,
|
||||
"regon_found": null,
|
||||
"nips_all": [],
|
||||
"regons_all": [],
|
||||
"phone_found": null,
|
||||
"address_found": null,
|
||||
"confidence": "low",
|
||||
"error": "NIP/REGON not found on website",
|
||||
"scanned_at": "2026-02-01T07:01:49.260663"
|
||||
}
|
||||
]
|
||||
@ -674,7 +674,7 @@ class Company(Base):
|
||||
# PKD (kod działalności gospodarczej) - z CEIDG
|
||||
pkd_code = Column(String(10)) # np. "6201Z" (główny PKD)
|
||||
pkd_description = Column(Text) # np. "Działalność związana z oprogramowaniem"
|
||||
pkd_codes = Column(PG_JSONB, default=[]) # Wszystkie PKD jako [{kod, nazwa}]
|
||||
ceidg_pkd_list = Column(PG_JSONB, default=[]) # Wszystkie PKD z CEIDG jako [{kod, nazwa}]
|
||||
|
||||
# Data rozpoczęcia działalności - z CEIDG
|
||||
business_start_date = Column(Date) # np. 2021-02-10
|
||||
|
||||
@ -14,8 +14,8 @@ ALTER TABLE companies ADD COLUMN IF NOT EXISTS correspondence_street VARCHAR(255
|
||||
ALTER TABLE companies ADD COLUMN IF NOT EXISTS correspondence_city VARCHAR(100);
|
||||
ALTER TABLE companies ADD COLUMN IF NOT EXISTS correspondence_postal VARCHAR(10);
|
||||
|
||||
-- PKD - wszystkie kody (JSONB array)
|
||||
ALTER TABLE companies ADD COLUMN IF NOT EXISTS pkd_codes JSONB DEFAULT '[]';
|
||||
-- PKD - wszystkie kody z CEIDG (JSONB array)
|
||||
ALTER TABLE companies ADD COLUMN IF NOT EXISTS ceidg_pkd_list JSONB DEFAULT '[]';
|
||||
|
||||
-- Obywatelstwa właściciela (JSONB array)
|
||||
ALTER TABLE companies ADD COLUMN IF NOT EXISTS owner_citizenships JSONB DEFAULT '[]';
|
||||
@ -32,7 +32,7 @@ CREATE INDEX IF NOT EXISTS idx_companies_ceidg_id ON companies(ceidg_id);
|
||||
-- Komentarze
|
||||
COMMENT ON COLUMN companies.ceidg_id IS 'GUID firmy w rejestrze CEIDG';
|
||||
COMMENT ON COLUMN companies.ceidg_status IS 'Status z CEIDG: AKTYWNY, ZAWIESZONY, WYKREŚLONY';
|
||||
COMMENT ON COLUMN companies.pkd_codes IS 'Wszystkie kody PKD jako JSON array [{kod, nazwa}]';
|
||||
COMMENT ON COLUMN companies.ceidg_pkd_list IS 'Wszystkie kody PKD z CEIDG jako JSON array [{kod, nazwa}]';
|
||||
COMMENT ON COLUMN companies.ceidg_raw_data IS 'Pełna odpowiedź z API CEIDG (JSON)';
|
||||
COMMENT ON COLUMN companies.ceidg_fetched_at IS 'Data ostatniego pobrania danych z CEIDG';
|
||||
|
||||
|
||||
1289
docs/UI_ANALYSIS_NORDA_BIZNES_INFO.md
Normal file
173
docs/UI_REDESIGN_CHANGELOG.md
Normal file
@ -0,0 +1,173 @@
|
||||
# NordaBiz UI Redesign Changelog
|
||||
|
||||
## Cel projektu
|
||||
Zmiana wyglądu nordabiznes.pl na zgodny z norda-biznes.info, zachowując wszystkie funkcjonalności.
|
||||
|
||||
---
|
||||
|
||||
## PRZED ZMIANAMI (Produkcja - 30.01.2026)
|
||||
|
||||
**Screenshot ID:** ss_7892h2ggn
|
||||
|
||||
### Obecny stan:
|
||||
- **Czcionka:** Inter
|
||||
- **Primary color:** #2563eb (jasny niebieski)
|
||||
- **Tło:** #f8fafc
|
||||
- **Event banner:** pomarańczowy (#f59e0b)
|
||||
- **NordaGPT banner:** fioletowy (#7c3aed)
|
||||
- **Karty firm:** cień (box-shadow), hover z translateY
|
||||
- **Przyciski:** border-radius 8px (symetryczny)
|
||||
|
||||
---
|
||||
|
||||
## SPRINT 1: Fundamenty (Commit: de46e12)
|
||||
|
||||
**Screenshot ID:** ss_3438lwagj
|
||||
|
||||
### Zmiany:
|
||||
1. **Czcionka:** Inter → **Poppins**
|
||||
2. **Primary color:** #2563eb → **#2E4872**
|
||||
3. **Primary dark:** #1e40af → **#1e3050**
|
||||
4. **Primary light:** #3b82f6 → **#4a6999**
|
||||
5. **Tło (background):** #f8fafc → **#EDF0F5**
|
||||
6. **Border color:** #e2e8f0 → **#e0e4eb**
|
||||
7. **Border-radius przycisków:** 0.5rem → **12px 4px 12px 4px** (asymetryczny)
|
||||
8. **Header:** usunięcie border-bottom, cień `0 2px 10px rgba(46, 72, 114, 0.08)`
|
||||
9. **Footer:** background #1e293b → **#2E4872**, padding 60px/30px
|
||||
|
||||
### Pliki zmienione:
|
||||
- `templates/base.html`
|
||||
|
||||
---
|
||||
|
||||
## SPRINT 2: Bannery i karty firm (Commit: 1da42f2)
|
||||
|
||||
**Screenshot ID:** ss_29596hr83
|
||||
|
||||
### Zmiany:
|
||||
1. **Event banner:** #f59e0b (pomarańczowy) → **#2E4872** (niebieski)
|
||||
2. **NordaGPT banner:** #7c3aed (fioletowy) → **#2E4872** (niebieski)
|
||||
3. **Karty firm:** usunięcie box-shadow, dodanie `border: 1px solid #e0e4eb`
|
||||
4. **Karty firm hover:** `border-color: var(--primary)` zamiast translateY
|
||||
5. **Tagi kategorii:**
|
||||
- background: primary (#2E4872)
|
||||
- color: white
|
||||
- font-size: 11px
|
||||
- text-transform: uppercase
|
||||
- letter-spacing: 0.5px
|
||||
6. **Przyciski w bannerach:** asymetryczny border-radius
|
||||
|
||||
### Pliki zmienione:
|
||||
- `templates/index.html`
|
||||
|
||||
---
|
||||
|
||||
## SPRINT 3: Strona chatu NordaGPT (Commit: b680e3f)
|
||||
|
||||
**Screenshot ID:** ss_6281tcv2v
|
||||
|
||||
### Zmiany:
|
||||
1. **Chat header:** #7c3aed/#5b21b6 → **#2E4872/#1e3050**
|
||||
2. **Sidebar "Nowa rozmowa" button:** fioletowy → niebieski
|
||||
3. **Message avatars (AI):** fioletowy gradient → niebieski gradient
|
||||
4. **Input focus:** border-color i box-shadow na niebieski
|
||||
5. **Send button:** fioletowy gradient → niebieski gradient
|
||||
6. **Typing indicator dots:** #7c3aed → #2E4872
|
||||
7. **Suggestion chips hover:** fioletowy → niebieski
|
||||
8. **Thinking toggle:** fioletowe akcenty → niebieskie
|
||||
9. **Fluent CSS:** wszystkie zmienne primary na NordaBiz blue
|
||||
|
||||
### Pliki zmienione:
|
||||
- `templates/chat.html`
|
||||
- `static/css/fluent-nordabiz.css`
|
||||
|
||||
---
|
||||
|
||||
## SPRINT 6: Karty firm i tagi (Commit: 64583b6)
|
||||
|
||||
**Screenshot ID:** ss_sprint6
|
||||
|
||||
### Zmiany:
|
||||
1. **Karty firm border-radius:** `8px` → `0` (ostre rogi jak na źródle)
|
||||
2. **Karty firm border:** `#e0e4eb` → `#E4E4E4`
|
||||
3. **Tagi kategorii background:** niebieski primary → `#EDF0F5` (szary)
|
||||
4. **Tagi kategorii color:** biały → `#464646` (ciemny)
|
||||
5. **Text primary:** `#1e293b` → `#303030`
|
||||
6. **Text secondary:** `#64748b` → `#464646`
|
||||
|
||||
### Pliki zmienione:
|
||||
- `templates/base.html`
|
||||
- `templates/index.html`
|
||||
|
||||
---
|
||||
|
||||
## SPRINT 5: Landing page (Commit: ede9d09)
|
||||
|
||||
**Screenshot ID:** ss_sprint5
|
||||
|
||||
### Zmiany:
|
||||
1. **Hero gradient:** `#1e40af/#2563eb/#3b82f6` → `#1e3050/#2E4872/#4a6999`
|
||||
2. **Accent color:** `#2563eb` → `#2E4872`
|
||||
3. **Hero section:** `data-animate="fadeIn"`
|
||||
4. **Stats section:** `data-animate="fadeInUp"`
|
||||
5. **CTA section:** `data-animate="fadeInUp"`
|
||||
|
||||
### Pliki zmienione:
|
||||
- `templates/landing.html`
|
||||
|
||||
---
|
||||
|
||||
## SPRINT 4: Animacje scroll (Commit: 6e1c46e)
|
||||
|
||||
**Screenshot ID:** ss_sprint4
|
||||
|
||||
### Zmiany:
|
||||
1. **Nowy plik:** `static/js/scroll-animations.js` z IntersectionObserver
|
||||
2. **CSS keyframes:** fadeIn, fadeInUp, fadeInLeft, fadeInRight, scaleIn
|
||||
3. **Event banner:** `data-animate="fadeIn"`
|
||||
4. **Chat banner:** `data-animate="fadeIn"`
|
||||
5. **Search section:** `data-animate="fadeIn"`
|
||||
6. **Karty firm:** `data-animate="fadeInUp"` z delay stagger (1-6)
|
||||
7. **Accessibility:** `prefers-reduced-motion` wsparcie
|
||||
|
||||
### Pliki zmienione:
|
||||
- `templates/base.html`
|
||||
- `templates/index.html`
|
||||
- `static/js/scroll-animations.js` (NOWY)
|
||||
|
||||
---
|
||||
|
||||
## PODSUMOWANIE ZMIAN
|
||||
|
||||
| Element | PRZED | PO |
|
||||
|---------|-------|-----|
|
||||
| Czcionka | Inter | **Poppins** |
|
||||
| Primary | #2563eb | **#2E4872** |
|
||||
| Tło | #f8fafc | **#EDF0F5** |
|
||||
| Border-radius btn | 8px | **12px 4px** |
|
||||
| Event banner | #f59e0b | **#2E4872** |
|
||||
| NordaGPT | #7c3aed | **#2E4872** |
|
||||
| Karty firm | box-shadow | **border** |
|
||||
| Tagi | szare, małe | **uppercase, primary** |
|
||||
| Footer | #1e293b | **#2E4872** |
|
||||
| Animacje scroll | brak | **fadeIn + IntersectionObserver** |
|
||||
| Landing hero | #1e40af/#2563eb | **#1e3050/#2E4872** |
|
||||
| Karty firm radius | 8px | **0 (ostre rogi)** |
|
||||
| Tagi kategorii | niebieski bg | **szary (#EDF0F5)** |
|
||||
| Tekst body | #1e293b | **#303030** |
|
||||
|
||||
---
|
||||
|
||||
## Screenshot IDs (do osadzenia w HTML)
|
||||
|
||||
1. `ss_7892h2ggn` - PRZED zmianami
|
||||
2. `ss_3438lwagj` - Po Sprint 1
|
||||
3. `ss_29596hr83` - Po Sprint 2
|
||||
4. `ss_6281tcv2v` - Po Sprint 3 (chat)
|
||||
5. `ss_sprint4` - Po Sprint 4 (animacje)
|
||||
6. `ss_sprint5` - Po Sprint 5 (landing page)
|
||||
7. `ss_sprint6` - Po Sprint 6 (karty firm, tagi)
|
||||
|
||||
---
|
||||
|
||||
Data dokumentacji: 2026-01-30
|
||||
BIN
docs/screenshots/screenshot-0-PRZED.png
Normal file
|
After Width: | Height: | Size: 561 KiB |
BIN
docs/screenshots/screenshot-1-sprint1.png
Normal file
|
After Width: | Height: | Size: 608 KiB |
BIN
docs/screenshots/screenshot-2-sprint2.png
Normal file
|
After Width: | Height: | Size: 608 KiB |
BIN
docs/screenshots/screenshot-3-sprint3.png
Normal file
|
After Width: | Height: | Size: 608 KiB |
BIN
docs/screenshots/screenshot-4-chat.png
Normal file
|
After Width: | Height: | Size: 146 KiB |
BIN
docs/screenshots/screenshot-4-sprint4.png
Normal file
|
After Width: | Height: | Size: 643 KiB |
BIN
docs/screenshots/screenshot-5-sprint5.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
docs/screenshots/screenshot-6-sprint6.png
Normal file
|
After Width: | Height: | Size: 610 KiB |
BIN
docs/screenshots/screenshot-before-sprint4.png
Normal file
|
After Width: | Height: | Size: 608 KiB |
BIN
docs/screenshots/screenshot-before-sprint5.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
docs/screenshots/screenshot-before-sprint6.png
Normal file
|
After Width: | Height: | Size: 629 KiB |
722
docs/ui-redesign-comparison.html
Normal file
@ -0,0 +1,722 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NordaBiz UI Redesign - Porównanie zmian</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--old-primary: #2563eb;
|
||||
--new-primary: #2E4872;
|
||||
--old-bg: #f8fafc;
|
||||
--new-bg: #EDF0F5;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background: #f5f5f5;
|
||||
color: #1e293b;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
header {
|
||||
background: linear-gradient(135deg, #1e3050 0%, #2E4872 100%);
|
||||
color: white;
|
||||
padding: 3rem 2rem;
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
header p {
|
||||
opacity: 0.9;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.sprint-section {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.sprint-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 2px solid #EDF0F5;
|
||||
}
|
||||
|
||||
.sprint-badge {
|
||||
background: linear-gradient(135deg, #1e3050 0%, #2E4872 100%);
|
||||
color: white;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 12px 4px 12px 4px;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.sprint-badge.before {
|
||||
background: linear-gradient(135deg, #64748b 0%, #475569 100%);
|
||||
}
|
||||
|
||||
.sprint-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.commit-hash {
|
||||
font-family: monospace;
|
||||
background: #EDF0F5;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.85rem;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.changes-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.change-card {
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
border-left: 4px solid var(--new-primary);
|
||||
}
|
||||
|
||||
.change-card h4 {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--new-primary);
|
||||
}
|
||||
|
||||
.change-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.old-value {
|
||||
color: #ef4444;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.new-value {
|
||||
color: #10b981;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.color-preview {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
vertical-align: middle;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.files-changed {
|
||||
background: #EDF0F5;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.files-changed h4 {
|
||||
font-size: 0.9rem;
|
||||
color: #64748b;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.files-changed code {
|
||||
display: block;
|
||||
font-family: monospace;
|
||||
font-size: 0.85rem;
|
||||
color: var(--new-primary);
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
|
||||
.screenshot-container {
|
||||
margin-top: 1.5rem;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e2e8f0;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.screenshot-container img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.screenshot-label {
|
||||
background: #EDF0F5;
|
||||
padding: 0.75rem 1rem;
|
||||
font-size: 0.85rem;
|
||||
color: #64748b;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.summary-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.summary-table th,
|
||||
.summary-table td {
|
||||
padding: 0.75rem 1rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.summary-table th {
|
||||
background: #EDF0F5;
|
||||
font-weight: 600;
|
||||
color: var(--new-primary);
|
||||
}
|
||||
|
||||
.summary-table tr:hover {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
color: #64748b;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
.changes-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>NordaBiz UI Redesign</h1>
|
||||
<p>Dokumentacja zmian graficznych: norda-biznes.info → nordabiznes.pl</p>
|
||||
<p style="margin-top: 0.5rem; font-size: 0.9rem; opacity: 0.7;">Data: 30 stycznia 2026</p>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<!-- PRZED ZMIANAMI -->
|
||||
<section class="sprint-section">
|
||||
<div class="sprint-header">
|
||||
<span class="sprint-badge before">PRZED</span>
|
||||
<h2 class="sprint-title">Stan wyjściowy (Produkcja)</h2>
|
||||
</div>
|
||||
|
||||
<div class="changes-grid">
|
||||
<div class="change-card">
|
||||
<h4>Czcionka</h4>
|
||||
<div class="change-value">Inter (Google Fonts)</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Kolor primary</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #2563eb;"></span>
|
||||
#2563eb (jasny niebieski)
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Tło strony</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #f8fafc;"></span>
|
||||
#f8fafc
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Event banner</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #f59e0b;"></span>
|
||||
#f59e0b (pomaranczowy)
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>NordaGPT banner</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #7c3aed;"></span>
|
||||
#7c3aed (fioletowy)
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Przyciski border-radius</h4>
|
||||
<div class="change-value">8px (symetryczny)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="screenshot-container">
|
||||
<img src="screenshots/screenshot-0-PRZED.png" alt="Screenshot przed zmianami">
|
||||
<div class="screenshot-label">Stan przed zmianami (commit d9f32b7)</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SPRINT 1 -->
|
||||
<section class="sprint-section">
|
||||
<div class="sprint-header">
|
||||
<span class="sprint-badge">SPRINT 1</span>
|
||||
<h2 class="sprint-title">Fundamenty</h2>
|
||||
<span class="commit-hash">de46e12</span>
|
||||
</div>
|
||||
|
||||
<div class="changes-grid">
|
||||
<div class="change-card">
|
||||
<h4>Czcionka</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">Inter</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">Poppins</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Kolor primary</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #2563eb;"></span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="color-preview" style="background: #2E4872;"></span>
|
||||
<span class="new-value">#2E4872</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Tło strony</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #f8fafc;"></span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="color-preview" style="background: #EDF0F5;"></span>
|
||||
<span class="new-value">#EDF0F5</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Border-radius przycisków</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">8px</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">12px 4px 12px 4px</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Header</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">border-bottom</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">subtelny cien</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Footer</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #1e293b;"></span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="color-preview" style="background: #2E4872;"></span>
|
||||
<span class="new-value">#2E4872</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="files-changed">
|
||||
<h4>Zmienione pliki:</h4>
|
||||
<code>templates/base.html</code>
|
||||
</div>
|
||||
|
||||
<div class="screenshot-container">
|
||||
<img src="screenshots/screenshot-1-sprint1.png" alt="Screenshot po Sprint 1">
|
||||
<div class="screenshot-label">Po Sprint 1 (commit de46e12)</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SPRINT 2 -->
|
||||
<section class="sprint-section">
|
||||
<div class="sprint-header">
|
||||
<span class="sprint-badge">SPRINT 2</span>
|
||||
<h2 class="sprint-title">Bannery i karty firm</h2>
|
||||
<span class="commit-hash">1da42f2</span>
|
||||
</div>
|
||||
|
||||
<div class="changes-grid">
|
||||
<div class="change-card">
|
||||
<h4>Event banner</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #f59e0b;"></span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="color-preview" style="background: #2E4872;"></span>
|
||||
<span class="new-value">#2E4872</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>NordaGPT banner</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #7c3aed;"></span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="color-preview" style="background: #2E4872;"></span>
|
||||
<span class="new-value">#2E4872</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Karty firm - styl</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">box-shadow</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">border 1px solid</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Karty firm - hover</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">translateY(-2px)</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">border-color: primary</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Tagi kategorii</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">szare, male litery</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">UPPERCASE, primary</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Przyciski w bannerach</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">asymetryczny border-radius</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="files-changed">
|
||||
<h4>Zmienione pliki:</h4>
|
||||
<code>templates/index.html</code>
|
||||
</div>
|
||||
|
||||
<div class="screenshot-container">
|
||||
<img src="screenshots/screenshot-2-sprint2.png" alt="Screenshot po Sprint 2">
|
||||
<div class="screenshot-label">Po Sprint 2 (commit 1da42f2)</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SPRINT 3 -->
|
||||
<section class="sprint-section">
|
||||
<div class="sprint-header">
|
||||
<span class="sprint-badge">SPRINT 3</span>
|
||||
<h2 class="sprint-title">Strona chatu NordaGPT</h2>
|
||||
<span class="commit-hash">b680e3f</span>
|
||||
</div>
|
||||
|
||||
<div class="changes-grid">
|
||||
<div class="change-card">
|
||||
<h4>Chat header</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #7c3aed;"></span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="color-preview" style="background: #2E4872;"></span>
|
||||
<span class="new-value">#2E4872</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Sidebar button</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">fioletowy</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">niebieski</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>AI Message avatar</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">fioletowy gradient</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">niebieski gradient</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Input focus</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">#7c3aed</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">#2E4872</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Send button</h4>
|
||||
<div class="change-value">
|
||||
<span class="old-value">fioletowy</span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="new-value">niebieski</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Fluent CSS</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">wszystkie zmienne primary</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="files-changed">
|
||||
<h4>Zmienione pliki:</h4>
|
||||
<code>templates/chat.html</code>
|
||||
<code>static/css/fluent-nordabiz.css</code>
|
||||
</div>
|
||||
|
||||
<div class="screenshot-container">
|
||||
<img src="screenshots/screenshot-3-sprint3.png" alt="Screenshot po Sprint 3 - strona główna">
|
||||
<div class="screenshot-label">Po Sprint 3 - strona glowna (commit b680e3f)</div>
|
||||
</div>
|
||||
<div class="screenshot-container" style="margin-top: 1rem;">
|
||||
<img src="screenshots/screenshot-4-chat.png" alt="Screenshot po Sprint 3 - strona chatu">
|
||||
<div class="screenshot-label">Po Sprint 3 - strona /chat (commit b680e3f)</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SPRINT 4 -->
|
||||
<section class="sprint-section">
|
||||
<div class="sprint-header">
|
||||
<span class="sprint-badge">SPRINT 4</span>
|
||||
<h2 class="sprint-title">Animacje scroll</h2>
|
||||
<span class="commit-hash">6e1c46e</span>
|
||||
</div>
|
||||
|
||||
<div class="changes-grid">
|
||||
<div class="change-card">
|
||||
<h4>IntersectionObserver</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">Nowy plik scroll-animations.js</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>CSS Keyframes</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">fadeIn, fadeInUp, fadeInLeft, fadeInRight, scaleIn</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Event banner</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">data-animate="fadeIn"</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Chat banner</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">data-animate="fadeIn"</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Karty firm</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">data-animate="fadeInUp" + delay stagger</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Reduced motion</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">prefers-reduced-motion wsparcie</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="files-changed">
|
||||
<h4>Zmienione pliki:</h4>
|
||||
<code>templates/base.html</code>
|
||||
<code>templates/index.html</code>
|
||||
<code>static/js/scroll-animations.js (NOWY)</code>
|
||||
</div>
|
||||
|
||||
<div class="screenshot-container">
|
||||
<img src="screenshots/screenshot-before-sprint4.png" alt="Screenshot przed Sprint 4">
|
||||
<div class="screenshot-label">Przed Sprint 4 (commit b680e3f)</div>
|
||||
</div>
|
||||
<div class="screenshot-container" style="margin-top: 1rem;">
|
||||
<img src="screenshots/screenshot-4-sprint4.png" alt="Screenshot po Sprint 4">
|
||||
<div class="screenshot-label">Po Sprint 4 (commit 6e1c46e)</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- SPRINT 5 -->
|
||||
<section class="sprint-section">
|
||||
<div class="sprint-header">
|
||||
<span class="sprint-badge">SPRINT 5</span>
|
||||
<h2 class="sprint-title">Landing page</h2>
|
||||
<span class="commit-hash">ede9d09</span>
|
||||
</div>
|
||||
|
||||
<div class="changes-grid">
|
||||
<div class="change-card">
|
||||
<h4>Hero gradient</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: linear-gradient(90deg, #1e40af, #2563eb);"></span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="color-preview" style="background: linear-gradient(90deg, #1e3050, #2E4872);"></span>
|
||||
<span class="new-value">NordaBiz blue</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Accent color</h4>
|
||||
<div class="change-value">
|
||||
<span class="color-preview" style="background: #2563eb;"></span>
|
||||
<span class="arrow">→</span>
|
||||
<span class="color-preview" style="background: #2E4872;"></span>
|
||||
<span class="new-value">#2E4872</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Hero section</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">data-animate="fadeIn"</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>Stats section</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">data-animate="fadeInUp"</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="change-card">
|
||||
<h4>CTA section</h4>
|
||||
<div class="change-value">
|
||||
<span class="new-value">data-animate="fadeInUp"</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="files-changed">
|
||||
<h4>Zmienione pliki:</h4>
|
||||
<code>templates/landing.html</code>
|
||||
</div>
|
||||
|
||||
<div class="screenshot-container">
|
||||
<img src="screenshots/screenshot-before-sprint5.png" alt="Screenshot przed Sprint 5">
|
||||
<div class="screenshot-label">Przed Sprint 5 - landing page (commit 6e1c46e)</div>
|
||||
</div>
|
||||
<div class="screenshot-container" style="margin-top: 1rem;">
|
||||
<img src="screenshots/screenshot-5-sprint5.png" alt="Screenshot po Sprint 5">
|
||||
<div class="screenshot-label">Po Sprint 5 - landing page (commit ede9d09)</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- PODSUMOWANIE -->
|
||||
<section class="sprint-section">
|
||||
<div class="sprint-header">
|
||||
<span class="sprint-badge">PODSUMOWANIE</span>
|
||||
<h2 class="sprint-title">Wszystkie zmiany</h2>
|
||||
</div>
|
||||
|
||||
<table class="summary-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Element</th>
|
||||
<th>PRZED</th>
|
||||
<th>PO</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Czcionka</td>
|
||||
<td>Inter</td>
|
||||
<td><strong>Poppins</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kolor primary</td>
|
||||
<td><span class="color-preview" style="background: #2563eb;"></span> #2563eb</td>
|
||||
<td><span class="color-preview" style="background: #2E4872;"></span> <strong>#2E4872</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tło strony</td>
|
||||
<td><span class="color-preview" style="background: #f8fafc;"></span> #f8fafc</td>
|
||||
<td><span class="color-preview" style="background: #EDF0F5;"></span> <strong>#EDF0F5</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Border-radius btn</td>
|
||||
<td>8px</td>
|
||||
<td><strong>12px 4px</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Event banner</td>
|
||||
<td><span class="color-preview" style="background: #f59e0b;"></span> #f59e0b</td>
|
||||
<td><span class="color-preview" style="background: #2E4872;"></span> <strong>#2E4872</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>NordaGPT</td>
|
||||
<td><span class="color-preview" style="background: #7c3aed;"></span> #7c3aed</td>
|
||||
<td><span class="color-preview" style="background: #2E4872;"></span> <strong>#2E4872</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Karty firm</td>
|
||||
<td>box-shadow</td>
|
||||
<td><strong>border</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tagi kategorii</td>
|
||||
<td>szare, male</td>
|
||||
<td><strong>UPPERCASE, primary</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Footer</td>
|
||||
<td><span class="color-preview" style="background: #1e293b;"></span> #1e293b</td>
|
||||
<td><span class="color-preview" style="background: #2E4872;"></span> <strong>#2E4872</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Animacje scroll</td>
|
||||
<td>brak</td>
|
||||
<td><strong>fadeIn + IntersectionObserver</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Landing hero</td>
|
||||
<td><span class="color-preview" style="background: linear-gradient(90deg, #1e40af, #2563eb);"></span> stary niebieski</td>
|
||||
<td><span class="color-preview" style="background: linear-gradient(90deg, #1e3050, #2E4872);"></span> <strong>NordaBiz blue</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>Dokumentacja wygenerowana automatycznie | NordaBiz UI Redesign | 30.01.2026</p>
|
||||
<p style="margin-top: 0.5rem;">
|
||||
<a href="https://nordabiznes.pl" target="_blank" style="color: #2E4872;">nordabiznes.pl</a> |
|
||||
<a href="https://norda-biznes.info" target="_blank" style="color: #2E4872;">norda-biznes.info</a>
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@ -464,9 +464,9 @@ def update_company_from_ceidg(company_id: int, ceidg_data: dict, db) -> bool:
|
||||
company.pkd_code = pkd_glowny.get("kod")
|
||||
company.pkd_description = pkd_glowny.get("nazwa")
|
||||
|
||||
# Wszystkie PKD
|
||||
# Wszystkie PKD z CEIDG
|
||||
if ceidg_data.get("pkd"):
|
||||
company.pkd_codes = ceidg_data.get("pkd")
|
||||
company.ceidg_pkd_list = ceidg_data.get("pkd")
|
||||
|
||||
# Data rozpoczęcia działalności
|
||||
if ceidg_data.get("dataRozpoczecia"):
|
||||
|
||||
493
scripts/search_ceidg_by_name.py
Normal file
@ -0,0 +1,493 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CEIDG Search by Name - wyszukuje firmy w CEIDG po nazwie
|
||||
|
||||
Dla firm bez NIP w bazie - szuka w portalu CEIDG po nazwie firmy
|
||||
i weryfikuje wyniki przez porównanie adresu/telefonu.
|
||||
|
||||
Portal CEIDG: https://aplikacja.ceidg.gov.pl/ceidg/ceidg.public.ui/search.aspx
|
||||
|
||||
Usage:
|
||||
python scripts/search_ceidg_by_name.py # Szukaj wszystkich
|
||||
python scripts/search_ceidg_by_name.py --id 119 # Szukaj konkretnej firmy
|
||||
python scripts/search_ceidg_by_name.py --apply # Zapisz znalezione NIP
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import argparse
|
||||
import time
|
||||
import json
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from dataclasses import dataclass, asdict, field
|
||||
from typing import Optional, List
|
||||
from difflib import SequenceMatcher
|
||||
|
||||
# Add parent directory to path for imports
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
try:
|
||||
from playwright.sync_api import sync_playwright, TimeoutError as PlaywrightTimeout
|
||||
except ImportError:
|
||||
print("Playwright nie jest zainstalowany. Uruchom: pip install playwright && playwright install chromium")
|
||||
sys.exit(1)
|
||||
|
||||
from database import SessionLocal, Company
|
||||
|
||||
# Output directory
|
||||
RESULTS_DIR = Path(__file__).parent.parent / "data" / "ceidg_search_results"
|
||||
RESULTS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Domains to skip (public email providers)
|
||||
SKIP_DOMAINS = {
|
||||
'gmail.com', 'wp.pl', 'onet.pl', 'op.pl', 'interia.pl',
|
||||
'o2.pl', 'poczta.fm', 'yahoo.com', 'hotmail.com', 'outlook.com'
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class CEIDGSearchResult:
|
||||
"""Wynik wyszukiwania w CEIDG"""
|
||||
company_id: int
|
||||
company_name: str
|
||||
search_query: str
|
||||
|
||||
# Znalezione dane
|
||||
found_nip: Optional[str] = None
|
||||
found_regon: Optional[str] = None
|
||||
found_name: Optional[str] = None
|
||||
found_owner: Optional[str] = None
|
||||
found_address: Optional[str] = None
|
||||
found_status: Optional[str] = None
|
||||
|
||||
# Weryfikacja
|
||||
matches: List[str] = field(default_factory=list) # Co się zgadza
|
||||
confidence: str = "low" # low, medium, high
|
||||
verified: bool = False
|
||||
|
||||
error: Optional[str] = None
|
||||
searched_at: str = ""
|
||||
|
||||
def __post_init__(self):
|
||||
if not self.searched_at:
|
||||
self.searched_at = datetime.now().isoformat()
|
||||
|
||||
def to_dict(self):
|
||||
return asdict(self)
|
||||
|
||||
|
||||
def normalize_phone(phone: str) -> str:
|
||||
"""Normalizuje numer telefonu do samych cyfr"""
|
||||
if not phone:
|
||||
return ""
|
||||
return re.sub(r'[^0-9]', '', phone)
|
||||
|
||||
|
||||
def normalize_address(address: str) -> str:
|
||||
"""Normalizuje adres do porównania"""
|
||||
if not address:
|
||||
return ""
|
||||
# Lowercase, usuń znaki specjalne
|
||||
addr = address.lower()
|
||||
addr = re.sub(r'[^\w\s]', ' ', addr)
|
||||
addr = re.sub(r'\s+', ' ', addr).strip()
|
||||
return addr
|
||||
|
||||
|
||||
def similarity(a: str, b: str) -> float:
|
||||
"""Oblicza podobieństwo dwóch stringów (0-1)"""
|
||||
if not a or not b:
|
||||
return 0.0
|
||||
return SequenceMatcher(None, a.lower(), b.lower()).ratio()
|
||||
|
||||
|
||||
def validate_nip(nip: str) -> bool:
|
||||
"""Waliduje NIP (checksum)"""
|
||||
nip = re.sub(r'[^0-9]', '', nip)
|
||||
if len(nip) != 10:
|
||||
return False
|
||||
|
||||
weights = [6, 5, 7, 2, 3, 4, 5, 6, 7]
|
||||
try:
|
||||
checksum = sum(int(nip[i]) * weights[i] for i in range(9)) % 11
|
||||
return checksum == int(nip[9])
|
||||
except (ValueError, IndexError):
|
||||
return False
|
||||
|
||||
|
||||
def extract_nip_from_text(text: str) -> Optional[str]:
|
||||
"""Wyciąga NIP z tekstu"""
|
||||
patterns = [
|
||||
r'NIP[:\s]*(\d{3}[-\s]?\d{3}[-\s]?\d{2}[-\s]?\d{2})',
|
||||
r'NIP[:\s]*(\d{10})',
|
||||
r'\b(\d{10})\b', # Standalone 10 digits
|
||||
]
|
||||
|
||||
for pattern in patterns:
|
||||
matches = re.findall(pattern, text, re.IGNORECASE)
|
||||
for match in matches:
|
||||
nip = re.sub(r'[^0-9]', '', match)
|
||||
if validate_nip(nip):
|
||||
return nip
|
||||
return None
|
||||
|
||||
|
||||
def extract_regon_from_text(text: str) -> Optional[str]:
|
||||
"""Wyciąga REGON z tekstu"""
|
||||
patterns = [
|
||||
r'REGON[:\s]*(\d{9,14})',
|
||||
]
|
||||
|
||||
for pattern in patterns:
|
||||
matches = re.findall(pattern, text, re.IGNORECASE)
|
||||
for match in matches:
|
||||
regon = re.sub(r'[^0-9]', '', match)
|
||||
if len(regon) in (9, 14):
|
||||
return regon
|
||||
return None
|
||||
|
||||
|
||||
def search_ceidg(company: Company) -> CEIDGSearchResult:
|
||||
"""
|
||||
Szuka firmy w CEIDG po nazwie.
|
||||
Portal CEIDG: https://aplikacja.ceidg.gov.pl/ceidg/ceidg.public.ui/search.aspx
|
||||
"""
|
||||
# Prepare search query
|
||||
search_name = company.name
|
||||
|
||||
# Remove common suffixes (CEIDG is for sole proprietorships, not companies)
|
||||
for suffix in [' sp. z o.o.', ' sp.z o.o.', ' s.c.', ' s.j.']:
|
||||
search_name = search_name.replace(suffix, '').replace(suffix.upper(), '')
|
||||
|
||||
search_name = search_name.strip()
|
||||
|
||||
result = CEIDGSearchResult(
|
||||
company_id=company.id,
|
||||
company_name=company.name,
|
||||
search_query=search_name
|
||||
)
|
||||
|
||||
print(f" Szukam w CEIDG: '{search_name}'")
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True)
|
||||
context = browser.new_context(
|
||||
user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||
)
|
||||
page = context.new_page()
|
||||
page.set_default_timeout(60000) # 60 seconds default timeout
|
||||
|
||||
try:
|
||||
# Go to CEIDG search page
|
||||
print(" → Ładuję stronę CEIDG...")
|
||||
page.goto("https://aplikacja.ceidg.gov.pl/ceidg/ceidg.public.ui/search.aspx", timeout=60000)
|
||||
time.sleep(3)
|
||||
|
||||
# Wait for page to be ready
|
||||
page.wait_for_load_state("domcontentloaded", timeout=30000)
|
||||
print(" → Strona załadowana")
|
||||
|
||||
# Try multiple selectors for company name field
|
||||
firma_input = None
|
||||
selectors = [
|
||||
"input[id*='txtFirma']",
|
||||
"input[id*='Firma']",
|
||||
"input[name*='Firma']",
|
||||
"#ctl00_MainContent_txtFirma",
|
||||
"input[placeholder*='Nazwa firmy']",
|
||||
]
|
||||
|
||||
for selector in selectors:
|
||||
try:
|
||||
elem = page.locator(selector).first
|
||||
if elem.is_visible(timeout=2000):
|
||||
firma_input = elem
|
||||
print(f" → Znaleziono pole wyszukiwania: {selector}")
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not firma_input:
|
||||
# Take screenshot for debugging
|
||||
screenshot_path = RESULTS_DIR / f"ceidg_debug_{company.id}.png"
|
||||
page.screenshot(path=str(screenshot_path))
|
||||
result.error = f"Nie znaleziono pola wyszukiwania. Screenshot: {screenshot_path}"
|
||||
return result
|
||||
|
||||
# Fill in company name
|
||||
firma_input.fill(search_name)
|
||||
print(f" → Wpisano: '{search_name}'")
|
||||
time.sleep(1)
|
||||
|
||||
# Add city if available
|
||||
if company.address_city:
|
||||
city_selectors = [
|
||||
"input[id*='txtMiasto']",
|
||||
"input[id*='Miasto']",
|
||||
"#ctl00_MainContent_txtMiasto",
|
||||
]
|
||||
for selector in city_selectors:
|
||||
try:
|
||||
city_input = page.locator(selector).first
|
||||
if city_input.is_visible(timeout=2000):
|
||||
city_input.fill(company.address_city)
|
||||
print(f" → Dodano miasto: '{company.address_city}'")
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
# Find and click search button
|
||||
search_selectors = [
|
||||
"input[id*='btnSearch']",
|
||||
"input[value='Szukaj']",
|
||||
"button:has-text('Szukaj')",
|
||||
"#ctl00_MainContent_btnSearch",
|
||||
]
|
||||
|
||||
search_clicked = False
|
||||
for selector in search_selectors:
|
||||
try:
|
||||
btn = page.locator(selector).first
|
||||
if btn.is_visible(timeout=2000):
|
||||
btn.click()
|
||||
search_clicked = True
|
||||
print(" → Kliknięto Szukaj")
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not search_clicked:
|
||||
page.keyboard.press("Enter")
|
||||
print(" → Wysłano Enter")
|
||||
|
||||
# Wait for results
|
||||
time.sleep(5)
|
||||
page.wait_for_load_state("networkidle", timeout=30000)
|
||||
print(" → Wyniki załadowane")
|
||||
|
||||
# Check for "no results" message
|
||||
page_text_check = page.inner_text("body")
|
||||
if "Brak wyników" in page_text_check or "nie znaleziono" in page_text_check.lower():
|
||||
result.error = "Nie znaleziono w CEIDG"
|
||||
return result
|
||||
|
||||
# Find details link
|
||||
details_selectors = [
|
||||
"a:has-text('Szczegóły')",
|
||||
"a[href*='SearchDetails']",
|
||||
"a[id*='Details']",
|
||||
"a.details-link",
|
||||
]
|
||||
|
||||
details_link = None
|
||||
for selector in details_selectors:
|
||||
try:
|
||||
link = page.locator(selector).first
|
||||
if link.is_visible(timeout=3000):
|
||||
details_link = link
|
||||
break
|
||||
except:
|
||||
continue
|
||||
|
||||
if not details_link:
|
||||
# Maybe direct results page?
|
||||
page_text = page.inner_text("body")
|
||||
nip = extract_nip_from_text(page_text)
|
||||
if nip:
|
||||
result.found_nip = nip
|
||||
result.found_regon = extract_regon_from_text(page_text)
|
||||
result = verify_result(result, company)
|
||||
return result
|
||||
|
||||
result.error = "Brak linku do szczegółów"
|
||||
screenshot_path = RESULTS_DIR / f"ceidg_results_{company.id}.png"
|
||||
page.screenshot(path=str(screenshot_path))
|
||||
return result
|
||||
|
||||
# Click details link
|
||||
details_link.click()
|
||||
print(" → Kliknięto Szczegóły")
|
||||
time.sleep(4)
|
||||
page.wait_for_load_state("networkidle", timeout=30000)
|
||||
|
||||
# Extract data from details page
|
||||
page_text = page.inner_text("body")
|
||||
|
||||
# Extract NIP
|
||||
result.found_nip = extract_nip_from_text(page_text)
|
||||
result.found_regon = extract_regon_from_text(page_text)
|
||||
|
||||
# Extract owner name
|
||||
owner_match = re.search(r'Imię i nazwisko[:\s]*([A-ZĄĆĘŁŃÓŚŹŻ][a-ząćęłńóśźż]+\s+[A-ZĄĆĘŁŃÓŚŹŻ][a-ząćęłńóśźż]+)', page_text)
|
||||
if owner_match:
|
||||
result.found_owner = owner_match.group(1).strip()
|
||||
|
||||
# Extract company name from CEIDG
|
||||
firma_match = re.search(r'Firma przedsiębiorcy[:\s]*(.+?)(?:\n|Adres|Status)', page_text, re.DOTALL)
|
||||
if firma_match:
|
||||
result.found_name = firma_match.group(1).strip()[:200]
|
||||
|
||||
# Extract address
|
||||
addr_match = re.search(r'Adres[:\s]*(.+?)(?:\n\n|Status|Data)', page_text, re.DOTALL)
|
||||
if addr_match:
|
||||
result.found_address = addr_match.group(1).strip()[:200]
|
||||
|
||||
# Extract status
|
||||
if 'AKTYWNY' in page_text.upper():
|
||||
result.found_status = 'AKTYWNY'
|
||||
elif 'ZAWIESZONY' in page_text.upper():
|
||||
result.found_status = 'ZAWIESZONY'
|
||||
elif 'WYKREŚLONY' in page_text.upper():
|
||||
result.found_status = 'WYKREŚLONY'
|
||||
|
||||
# Verify the result
|
||||
result = verify_result(result, company)
|
||||
|
||||
except PlaywrightTimeout:
|
||||
result.error = "Timeout"
|
||||
except Exception as e:
|
||||
result.error = str(e)[:200]
|
||||
finally:
|
||||
browser.close()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def verify_result(result: CEIDGSearchResult, company: Company) -> CEIDGSearchResult:
|
||||
"""
|
||||
Weryfikuje czy znaleziony wynik pasuje do naszej firmy.
|
||||
"""
|
||||
if not result.found_nip:
|
||||
result.error = "NIP nie znaleziony na stronie szczegółów"
|
||||
return result
|
||||
|
||||
matches = []
|
||||
|
||||
# 1. Sprawdź podobieństwo nazwy
|
||||
if result.found_name:
|
||||
name_sim = similarity(company.name, result.found_name)
|
||||
if name_sim > 0.7:
|
||||
matches.append(f"nazwa ({name_sim:.0%})")
|
||||
elif name_sim > 0.5:
|
||||
matches.append(f"nazwa częściowa ({name_sim:.0%})")
|
||||
|
||||
# 2. Sprawdź adres/miasto
|
||||
if result.found_address and company.address_city:
|
||||
if company.address_city.lower() in result.found_address.lower():
|
||||
matches.append("miasto")
|
||||
|
||||
if result.found_address and company.address_street:
|
||||
if company.address_street.lower()[:10] in result.found_address.lower():
|
||||
matches.append("ulica")
|
||||
|
||||
# 3. Sprawdź właściciela (jeśli mamy w nazwie)
|
||||
if result.found_owner:
|
||||
owner_parts = result.found_owner.lower().split()
|
||||
company_name_lower = company.name.lower()
|
||||
for part in owner_parts:
|
||||
if len(part) > 3 and part in company_name_lower:
|
||||
matches.append("właściciel w nazwie")
|
||||
break
|
||||
|
||||
# Determine confidence
|
||||
result.matches = matches
|
||||
|
||||
if len(matches) >= 2:
|
||||
result.confidence = "high"
|
||||
result.verified = True
|
||||
elif len(matches) == 1 and "nazwa" in matches[0]:
|
||||
result.confidence = "medium"
|
||||
result.verified = True
|
||||
elif len(matches) == 1:
|
||||
result.confidence = "low"
|
||||
result.verified = False
|
||||
else:
|
||||
result.confidence = "low"
|
||||
result.verified = False
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def get_companies_without_nip(db, company_id: int = None) -> List[Company]:
|
||||
"""Pobiera firmy bez NIP"""
|
||||
query = db.query(Company).filter(
|
||||
(Company.nip == None) | (Company.nip == '')
|
||||
)
|
||||
|
||||
if company_id:
|
||||
query = query.filter(Company.id == company_id)
|
||||
|
||||
return query.order_by(Company.name).all()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Search CEIDG by company name")
|
||||
parser.add_argument('--id', type=int, help="Search specific company ID")
|
||||
parser.add_argument('--apply', action='store_true', help="Apply found NIPs to database")
|
||||
parser.add_argument('--limit', type=int, default=50, help="Limit number of companies to search")
|
||||
parser.add_argument('--output', type=str, help="Output JSON file path")
|
||||
args = parser.parse_args()
|
||||
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
companies = get_companies_without_nip(db, args.id)
|
||||
|
||||
if not args.id:
|
||||
companies = companies[:args.limit]
|
||||
|
||||
print(f"\n=== Wyszukiwanie {len(companies)} firm w CEIDG ===\n")
|
||||
|
||||
results = []
|
||||
found_count = 0
|
||||
verified_count = 0
|
||||
|
||||
for i, company in enumerate(companies, 1):
|
||||
print(f"[{i}/{len(companies)}] {company.name}")
|
||||
|
||||
result = search_ceidg(company)
|
||||
results.append(result)
|
||||
|
||||
if result.found_nip:
|
||||
found_count += 1
|
||||
status = "✓" if result.verified else "?"
|
||||
print(f" {status} NIP: {result.found_nip} (confidence: {result.confidence})")
|
||||
print(f" Matches: {', '.join(result.matches) if result.matches else 'brak'}")
|
||||
|
||||
if result.verified:
|
||||
verified_count += 1
|
||||
|
||||
if args.apply:
|
||||
company.nip = result.found_nip
|
||||
if result.found_regon and not company.regon:
|
||||
company.regon = result.found_regon
|
||||
db.commit()
|
||||
print(f" → Zapisano do bazy")
|
||||
elif result.error:
|
||||
print(f" ✗ {result.error}")
|
||||
|
||||
# Rate limiting - CEIDG może blokować
|
||||
time.sleep(3)
|
||||
|
||||
# Save results to JSON
|
||||
output_file = args.output or (RESULTS_DIR / f"ceidg_search_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json")
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
json.dump([r.to_dict() for r in results], f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"\n=== Podsumowanie ===")
|
||||
print(f"Przeszukano: {len(companies)} firm")
|
||||
print(f"Znaleziono NIP: {found_count}")
|
||||
print(f"Zweryfikowano: {verified_count}")
|
||||
print(f"Wyniki zapisane: {output_file}")
|
||||
|
||||
if verified_count > 0 and not args.apply:
|
||||
print(f"\nUżyj --apply aby zapisać zweryfikowane NIP do bazy")
|
||||
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
353
static/img/icons-preview-v2.html
Normal file
@ -0,0 +1,353 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>NordaGPT - Propozycje ikon v2</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||||
min-height: 100vh;
|
||||
padding: 2rem;
|
||||
color: white;
|
||||
}
|
||||
h1 { text-align: center; margin-bottom: 0.5rem; font-weight: 300; }
|
||||
h2 { text-align: center; margin: 2rem 0 1rem; font-weight: 400; color: #22c55e; font-size: 1.3rem; }
|
||||
.subtitle { text-align: center; margin-bottom: 2rem; color: rgba(255,255,255,0.6); }
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 1.5rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.icon-card {
|
||||
background: rgba(255,255,255,0.05);
|
||||
border-radius: 16px;
|
||||
padding: 1.5rem;
|
||||
text-align: center;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
position: relative;
|
||||
}
|
||||
.icon-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 40px rgba(0,0,0,0.3);
|
||||
border-color: rgba(34, 197, 94, 0.5);
|
||||
}
|
||||
.icon-container {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 0 auto 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.icon-container svg { width: 100%; height: 100%; }
|
||||
.icon-name { font-size: 1rem; font-weight: 600; margin-bottom: 0.3rem; color: #22c55e; }
|
||||
.icon-desc { font-size: 0.8rem; color: rgba(255,255,255,0.6); line-height: 1.3; }
|
||||
.icon-number {
|
||||
position: absolute;
|
||||
top: 0.8rem;
|
||||
left: 0.8rem;
|
||||
background: #22c55e;
|
||||
color: #1a1a2e;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.section-divider {
|
||||
border: none;
|
||||
border-top: 1px solid rgba(255,255,255,0.1);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>NordaGPT - Propozycje ikon v2</h1>
|
||||
<p class="subtitle">5 wariantów robota + 5 wariantów litery N</p>
|
||||
|
||||
<h2>🤖 Warianty: Przyjazny Robot</h2>
|
||||
<div class="grid">
|
||||
|
||||
<!-- Robot 1: Okrągły, minimalistyczny -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">R1</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Antenna -->
|
||||
<line x1="50" y1="22" x2="50" y2="12" stroke="#22c55e" stroke-width="3" stroke-linecap="round"/>
|
||||
<circle cx="50" cy="10" r="4" fill="#fbbf24"/>
|
||||
<!-- Face circle -->
|
||||
<circle cx="50" cy="52" r="28" fill="#3b82f6"/>
|
||||
<circle cx="50" cy="52" r="24" fill="#60a5fa"/>
|
||||
<!-- Eyes - happy crescents -->
|
||||
<path d="M35 48 Q 40 42, 45 48" stroke="#233e6d" stroke-width="3" fill="none" stroke-linecap="round"/>
|
||||
<path d="M55 48 Q 60 42, 65 48" stroke="#233e6d" stroke-width="3" fill="none" stroke-linecap="round"/>
|
||||
<!-- Smile -->
|
||||
<path d="M38 58 Q 50 68, 62 58" stroke="#233e6d" stroke-width="3" fill="none" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Uśmiechnięty Krąg</div>
|
||||
<div class="icon-desc">Minimalistyczny, zamknięte oczy = szczęście</div>
|
||||
</div>
|
||||
|
||||
<!-- Robot 2: Z dużymi oczami -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">R2</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Antenna with glow -->
|
||||
<line x1="50" y1="20" x2="50" y2="8" stroke="#22c55e" stroke-width="2"/>
|
||||
<circle cx="50" cy="6" r="4" fill="#fbbf24"/>
|
||||
<circle cx="50" cy="6" r="6" fill="#fbbf24" opacity="0.3"/>
|
||||
<!-- Head -->
|
||||
<rect x="22" y="24" width="56" height="50" rx="12" fill="#22c55e"/>
|
||||
<rect x="26" y="28" width="48" height="42" rx="9" fill="#4ade80"/>
|
||||
<!-- Big cute eyes -->
|
||||
<ellipse cx="38" cy="48" rx="10" ry="12" fill="white"/>
|
||||
<ellipse cx="62" cy="48" rx="10" ry="12" fill="white"/>
|
||||
<circle cx="40" cy="48" r="6" fill="#233e6d"/>
|
||||
<circle cx="64" cy="48" r="6" fill="#233e6d"/>
|
||||
<circle cx="42" cy="46" r="2" fill="white"/>
|
||||
<circle cx="66" cy="46" r="2" fill="white"/>
|
||||
<!-- Small smile -->
|
||||
<path d="M44 62 Q 50 67, 56 62" stroke="#233e6d" stroke-width="2.5" fill="none" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Duże Oczy</div>
|
||||
<div class="icon-desc">Zielony robot z dużymi, uroczymi oczami</div>
|
||||
</div>
|
||||
|
||||
<!-- Robot 3: Pixel art style -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">R3</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Pixel antenna -->
|
||||
<rect x="47" y="12" width="6" height="10" fill="#22c55e"/>
|
||||
<rect x="44" y="8" width="12" height="6" fill="#fbbf24"/>
|
||||
<!-- Pixel head -->
|
||||
<rect x="24" y="26" width="52" height="48" rx="4" fill="#8b5cf6"/>
|
||||
<rect x="28" y="30" width="44" height="40" fill="#a78bfa"/>
|
||||
<!-- Pixel eyes -->
|
||||
<rect x="34" y="40" width="10" height="10" fill="white"/>
|
||||
<rect x="56" y="40" width="10" height="10" fill="white"/>
|
||||
<rect x="38" y="44" width="4" height="4" fill="#233e6d"/>
|
||||
<rect x="60" y="44" width="4" height="4" fill="#233e6d"/>
|
||||
<!-- Pixel smile -->
|
||||
<rect x="38" y="58" width="4" height="4" fill="#233e6d"/>
|
||||
<rect x="42" y="62" width="16" height="4" fill="#233e6d"/>
|
||||
<rect x="58" y="58" width="4" height="4" fill="#233e6d"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Pixel Robot</div>
|
||||
<div class="icon-desc">Styl retro/pixel art, fioletowy</div>
|
||||
</div>
|
||||
|
||||
<!-- Robot 4: Sleek modern -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">R4</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="robotGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#3b82f6"/>
|
||||
<stop offset="100%" style="stop-color:#8b5cf6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Sleek antenna -->
|
||||
<path d="M50 18 L50 8" stroke="url(#robotGrad)" stroke-width="3" stroke-linecap="round"/>
|
||||
<circle cx="50" cy="6" r="3" fill="#fbbf24"/>
|
||||
<!-- Modern rounded head -->
|
||||
<rect x="20" y="22" width="60" height="52" rx="16" fill="url(#robotGrad)"/>
|
||||
<!-- Visor style eye -->
|
||||
<rect x="28" y="38" width="44" height="14" rx="7" fill="#1a1a2e"/>
|
||||
<rect x="32" y="41" width="10" height="8" rx="4" fill="#22c55e"/>
|
||||
<rect x="58" y="41" width="10" height="8" rx="4" fill="#22c55e"/>
|
||||
<!-- Subtle mouth line -->
|
||||
<path d="M40 62 L60 62" stroke="#1a1a2e" stroke-width="3" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Nowoczesny</div>
|
||||
<div class="icon-desc">Sleek design z wizjerem</div>
|
||||
</div>
|
||||
|
||||
<!-- Robot 5: Okrągły z sercem -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">R5</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Antenna -->
|
||||
<line x1="50" y1="18" x2="50" y2="10" stroke="#f472b6" stroke-width="2"/>
|
||||
<circle cx="50" cy="8" r="4" fill="#fbbf24"/>
|
||||
<!-- Round head -->
|
||||
<circle cx="50" cy="50" r="32" fill="#ec4899"/>
|
||||
<circle cx="50" cy="50" r="28" fill="#f472b6"/>
|
||||
<!-- Happy eyes -->
|
||||
<circle cx="38" cy="45" r="6" fill="white"/>
|
||||
<circle cx="62" cy="45" r="6" fill="white"/>
|
||||
<circle cx="39" cy="45" r="3" fill="#233e6d"/>
|
||||
<circle cx="63" cy="45" r="3" fill="#233e6d"/>
|
||||
<!-- Heart mouth -->
|
||||
<path d="M45 58 L50 65 L55 58 Q 55 54, 50 58 Q 45 54, 45 58" fill="#233e6d"/>
|
||||
<!-- Blush -->
|
||||
<circle cx="30" cy="52" r="5" fill="#fb7185" opacity="0.5"/>
|
||||
<circle cx="70" cy="52" r="5" fill="#fb7185" opacity="0.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Różowy z Sercem</div>
|
||||
<div class="icon-desc">Przyjazny, ciepły, z rumieńcami</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
|
||||
<h2>🅽 Warianty: Litera N + GPT</h2>
|
||||
<div class="grid">
|
||||
|
||||
<!-- N1: Klasyczny z GPT -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">N1</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="nGrad1" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#22c55e"/>
|
||||
<stop offset="100%" style="stop-color:#14b8a6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<circle cx="50" cy="50" r="38" fill="none" stroke="url(#nGrad1)" stroke-width="2.5"/>
|
||||
<!-- Letter N -->
|
||||
<path d="M30 72 L30 28 L70 72 L70 28" stroke="url(#nGrad1)" stroke-width="7" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<!-- North indicator -->
|
||||
<circle cx="50" cy="8" r="4" fill="#fbbf24"/>
|
||||
<!-- GPT badge -->
|
||||
<rect x="58" y="68" width="28" height="16" rx="4" fill="#22c55e"/>
|
||||
<text x="72" y="80" text-anchor="middle" fill="white" font-size="9" font-weight="bold">GPT</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Klasyczne N</div>
|
||||
<div class="icon-desc">Oryginalna wersja z badge GPT</div>
|
||||
</div>
|
||||
|
||||
<!-- N2: Outline style -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">N2</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- N as outline -->
|
||||
<path d="M28 75 L28 25 L72 75 L72 25" stroke="#22c55e" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M28 75 L28 25 L72 75 L72 25" stroke="#4ade80" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="5,5"/>
|
||||
<!-- North star -->
|
||||
<polygon points="50,5 52,12 50,10 48,12" fill="#fbbf24"/>
|
||||
<circle cx="50" cy="5" r="3" fill="#fbbf24"/>
|
||||
<!-- GPT text below -->
|
||||
<text x="50" y="95" text-anchor="middle" fill="#22c55e" font-size="11" font-weight="bold">GPT</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">N Outline</div>
|
||||
<div class="icon-desc">Konturowe N z GPT na dole</div>
|
||||
</div>
|
||||
|
||||
<!-- N3: Bold chunky -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">N3</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="nGrad3" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#3b82f6"/>
|
||||
<stop offset="100%" style="stop-color:#8b5cf6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Bold N -->
|
||||
<path d="M25 78 L25 22 L75 78 L75 22" stroke="url(#nGrad3)" stroke-width="12" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<!-- Glow effect -->
|
||||
<path d="M25 78 L25 22 L75 78 L75 22" stroke="#3b82f6" stroke-width="16" fill="none" stroke-linecap="round" stroke-linejoin="round" opacity="0.2"/>
|
||||
<!-- GPT chip -->
|
||||
<rect x="60" y="60" width="30" height="20" rx="4" fill="#1a1a2e" stroke="#22c55e" stroke-width="1.5"/>
|
||||
<text x="75" y="74" text-anchor="middle" fill="#22c55e" font-size="10" font-weight="bold">GPT</text>
|
||||
<!-- North -->
|
||||
<circle cx="50" cy="6" r="4" fill="#fbbf24"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Bold N</div>
|
||||
<div class="icon-desc">Grube N z chipem GPT</div>
|
||||
</div>
|
||||
|
||||
<!-- N4: Geometric -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">N4</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Geometric N made of shapes -->
|
||||
<rect x="25" y="25" width="10" height="50" rx="2" fill="#22c55e"/>
|
||||
<rect x="65" y="25" width="10" height="50" rx="2" fill="#22c55e"/>
|
||||
<polygon points="25,25 35,25 75,75 65,75" fill="#22c55e"/>
|
||||
<!-- GPT in center -->
|
||||
<circle cx="50" cy="50" r="15" fill="#1a1a2e"/>
|
||||
<text x="50" y="54" text-anchor="middle" fill="#22c55e" font-size="9" font-weight="bold">GPT</text>
|
||||
<!-- North arrow -->
|
||||
<polygon points="50,5 54,12 50,9 46,12" fill="#fbbf24"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Geometryczne N</div>
|
||||
<div class="icon-desc">N z prostokątów z GPT w środku</div>
|
||||
</div>
|
||||
|
||||
<!-- N5: Neon style -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">N5</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<filter id="neon" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="2" result="blur"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="blur"/>
|
||||
<feMergeNode in="blur"/>
|
||||
<feMergeNode in="SourceGraphic"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#0f172a"/>
|
||||
<!-- Neon N -->
|
||||
<path d="M28 75 L28 25 L72 75 L72 25" stroke="#22c55e" stroke-width="5" fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#neon)"/>
|
||||
<!-- Neon circle -->
|
||||
<circle cx="50" cy="50" r="40" fill="none" stroke="#22c55e" stroke-width="1.5" opacity="0.5" filter="url(#neon)"/>
|
||||
<!-- GPT neon -->
|
||||
<text x="50" y="92" text-anchor="middle" fill="#f472b6" font-size="12" font-weight="bold" filter="url(#neon)">GPT</text>
|
||||
<!-- North glow -->
|
||||
<circle cx="50" cy="6" r="4" fill="#fbbf24" filter="url(#neon)"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Neonowe N</div>
|
||||
<div class="icon-desc">Efekt neonu, nocny vibe</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
<p style="text-align: center; color: rgba(255,255,255,0.4); margin-top: 1rem;">
|
||||
Wybierz numer ikony do wdrożenia
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
337
static/img/icons-preview-v3.html
Normal file
@ -0,0 +1,337 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>NordaGPT - Propozycje ikon v3</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #0a0a1a 0%, #1a1a2e 100%);
|
||||
min-height: 100vh;
|
||||
padding: 2rem;
|
||||
color: white;
|
||||
}
|
||||
h1 { text-align: center; margin-bottom: 0.5rem; font-weight: 300; }
|
||||
h2 { text-align: center; margin: 2rem 0 1rem; font-weight: 400; color: #22c55e; font-size: 1.3rem; }
|
||||
.subtitle { text-align: center; margin-bottom: 2rem; color: rgba(255,255,255,0.6); }
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 1.2rem;
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.icon-card {
|
||||
background: rgba(255,255,255,0.03);
|
||||
border-radius: 16px;
|
||||
padding: 1.2rem;
|
||||
text-align: center;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
position: relative;
|
||||
}
|
||||
.icon-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 40px rgba(0,0,0,0.4);
|
||||
border-color: rgba(34, 197, 94, 0.4);
|
||||
}
|
||||
.icon-container {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
margin: 0 auto 0.8rem;
|
||||
}
|
||||
.icon-container svg { width: 100%; height: 100%; }
|
||||
.icon-name { font-size: 0.95rem; font-weight: 600; margin-bottom: 0.2rem; color: #4ade80; }
|
||||
.icon-desc { font-size: 0.75rem; color: rgba(255,255,255,0.5); line-height: 1.3; }
|
||||
.icon-number {
|
||||
position: absolute;
|
||||
top: 0.6rem;
|
||||
left: 0.6rem;
|
||||
background: #22c55e;
|
||||
color: #0a0a1a;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
.section-divider {
|
||||
border: none;
|
||||
border-top: 1px solid rgba(255,255,255,0.08);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>NordaGPT - Propozycje ikon v3</h1>
|
||||
<p class="subtitle">Warianty R4 (Nowoczesny Robot) + N5 (Neonowe N)</p>
|
||||
|
||||
<h2>🤖 Warianty: Nowoczesny Robot z Wizjerem</h2>
|
||||
<div class="grid">
|
||||
|
||||
<!-- R4-A: Zielony wizjer -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">A</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="rA" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#22c55e"/>
|
||||
<stop offset="100%" style="stop-color:#14b8a6"/>
|
||||
</linearGradient>
|
||||
<filter id="glowA"><feGaussianBlur stdDeviation="2" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#1a1a2e"/>
|
||||
<path d="M50 18 L50 8" stroke="url(#rA)" stroke-width="3" stroke-linecap="round"/>
|
||||
<circle cx="50" cy="6" r="3" fill="#fbbf24" filter="url(#glowA)"/>
|
||||
<rect x="20" y="22" width="60" height="52" rx="14" fill="url(#rA)"/>
|
||||
<rect x="28" y="38" width="44" height="14" rx="7" fill="#0a0a1a"/>
|
||||
<rect x="32" y="41" width="12" height="8" rx="4" fill="#4ade80" filter="url(#glowA)"/>
|
||||
<rect x="56" y="41" width="12" height="8" rx="4" fill="#4ade80" filter="url(#glowA)"/>
|
||||
<rect x="38" y="60" width="24" height="4" rx="2" fill="#0a0a1a"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Zielony INPI</div>
|
||||
<div class="icon-desc">Kolory INPI, świecące oczy</div>
|
||||
</div>
|
||||
|
||||
<!-- R4-B: Niebieski gradient -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">B</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="rB" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#3b82f6"/>
|
||||
<stop offset="100%" style="stop-color:#6366f1"/>
|
||||
</linearGradient>
|
||||
<filter id="glowB"><feGaussianBlur stdDeviation="2" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#1a1a2e"/>
|
||||
<path d="M50 18 L50 8" stroke="url(#rB)" stroke-width="3" stroke-linecap="round"/>
|
||||
<circle cx="50" cy="6" r="3" fill="#fbbf24" filter="url(#glowB)"/>
|
||||
<rect x="20" y="22" width="60" height="52" rx="14" fill="url(#rB)"/>
|
||||
<rect x="26" y="36" width="48" height="16" rx="8" fill="#0a0a1a"/>
|
||||
<circle cx="38" cy="44" r="5" fill="#22c55e" filter="url(#glowB)"/>
|
||||
<circle cx="62" cy="44" r="5" fill="#22c55e" filter="url(#glowB)"/>
|
||||
<path d="M40 62 Q50 68, 60 62" stroke="#0a0a1a" stroke-width="3" fill="none" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Niebieski + Uśmiech</div>
|
||||
<div class="icon-desc">Okrągłe oczy, delikatny uśmiech</div>
|
||||
</div>
|
||||
|
||||
<!-- R4-C: Granat Norda -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">C</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="rC" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#233e6d"/>
|
||||
<stop offset="100%" style="stop-color:#1e3a5f"/>
|
||||
</linearGradient>
|
||||
<filter id="glowC"><feGaussianBlur stdDeviation="1.5" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#0f172a"/>
|
||||
<circle cx="50" cy="50" r="42" fill="none" stroke="#233e6d" stroke-width="1" opacity="0.5"/>
|
||||
<path d="M50 16 L50 6" stroke="#22c55e" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="50" cy="4" r="3" fill="#fbbf24" filter="url(#glowC)"/>
|
||||
<rect x="18" y="20" width="64" height="54" rx="12" fill="url(#rC)" stroke="#22c55e" stroke-width="1.5"/>
|
||||
<rect x="26" y="36" width="48" height="14" rx="7" fill="#0a0a1a"/>
|
||||
<rect x="30" y="39" width="14" height="8" rx="4" fill="#22c55e" filter="url(#glowC)"/>
|
||||
<rect x="56" y="39" width="14" height="8" rx="4" fill="#22c55e" filter="url(#glowC)"/>
|
||||
<rect x="36" y="58" width="28" height="6" rx="3" fill="#0a0a1a"/>
|
||||
<text x="50" y="64" text-anchor="middle" fill="#22c55e" font-size="6" font-weight="bold">GPT</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Norda Navy</div>
|
||||
<div class="icon-desc">Granat Norda + GPT w ustach</div>
|
||||
</div>
|
||||
|
||||
<!-- R4-D: Minimalistyczny -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">D</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#1a1a2e"/>
|
||||
<circle cx="50" cy="6" r="3" fill="#fbbf24"/>
|
||||
<line x1="50" y1="9" x2="50" y2="18" stroke="#22c55e" stroke-width="2"/>
|
||||
<rect x="22" y="22" width="56" height="48" rx="10" fill="none" stroke="#22c55e" stroke-width="2.5"/>
|
||||
<rect x="30" y="38" width="40" height="12" rx="6" fill="#22c55e" opacity="0.2"/>
|
||||
<circle cx="40" cy="44" r="4" fill="#22c55e"/>
|
||||
<circle cx="60" cy="44" r="4" fill="#22c55e"/>
|
||||
<line x1="40" y1="58" x2="60" y2="58" stroke="#22c55e" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Line Art</div>
|
||||
<div class="icon-desc">Minimalistyczny kontur</div>
|
||||
</div>
|
||||
|
||||
<!-- R4-E: Z badge GPT -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">E</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="rE" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#8b5cf6"/>
|
||||
<stop offset="100%" style="stop-color:#a855f7"/>
|
||||
</linearGradient>
|
||||
<filter id="glowE"><feGaussianBlur stdDeviation="2" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#1a1a2e"/>
|
||||
<path d="M50 18 L50 8" stroke="url(#rE)" stroke-width="3" stroke-linecap="round"/>
|
||||
<circle cx="50" cy="6" r="3" fill="#fbbf24" filter="url(#glowE)"/>
|
||||
<rect x="20" y="22" width="60" height="48" rx="14" fill="url(#rE)"/>
|
||||
<rect x="28" y="36" width="44" height="14" rx="7" fill="#0a0a1a"/>
|
||||
<rect x="32" y="39" width="10" height="8" rx="4" fill="#22c55e" filter="url(#glowE)"/>
|
||||
<rect x="58" y="39" width="10" height="8" rx="4" fill="#22c55e" filter="url(#glowE)"/>
|
||||
<line x1="40" y1="58" x2="60" y2="58" stroke="#0a0a1a" stroke-width="3" stroke-linecap="round"/>
|
||||
<!-- GPT Badge -->
|
||||
<circle cx="75" cy="70" r="14" fill="#22c55e"/>
|
||||
<text x="75" y="74" text-anchor="middle" fill="white" font-size="8" font-weight="bold">GPT</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Fiolet + Badge</div>
|
||||
<div class="icon-desc">Fioletowy z badge GPT</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
|
||||
<h2>✨ Warianty: Neonowe N</h2>
|
||||
<div class="grid">
|
||||
|
||||
<!-- N5-A: Zielony neon -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">A</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<filter id="neonA" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="2.5" result="blur"/>
|
||||
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#0a0a1a"/>
|
||||
<path d="M28 75 L28 25 L72 75 L72 25" stroke="#22c55e" stroke-width="6" fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#neonA)"/>
|
||||
<circle cx="50" cy="50" r="38" fill="none" stroke="#22c55e" stroke-width="1" opacity="0.3" filter="url(#neonA)"/>
|
||||
<text x="50" y="94" text-anchor="middle" fill="#22c55e" font-size="11" font-weight="bold" filter="url(#neonA)">GPT</text>
|
||||
<circle cx="50" cy="6" r="4" fill="#fbbf24" filter="url(#neonA)"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Zielony Neon</div>
|
||||
<div class="icon-desc">Klasyczny zielony, styl INPI</div>
|
||||
</div>
|
||||
|
||||
<!-- N5-B: Cyan neon -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">B</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<filter id="neonB" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="3" result="blur"/>
|
||||
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#0a0a1a"/>
|
||||
<path d="M28 75 L28 25 L72 75 L72 25" stroke="#06b6d4" stroke-width="5" fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#neonB)"/>
|
||||
<circle cx="50" cy="50" r="36" fill="none" stroke="#06b6d4" stroke-width="1.5" opacity="0.4" filter="url(#neonB)"/>
|
||||
<text x="50" y="94" text-anchor="middle" fill="#06b6d4" font-size="11" font-weight="bold" filter="url(#neonB)">GPT</text>
|
||||
<circle cx="50" cy="6" r="4" fill="#fbbf24" filter="url(#neonB)"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Cyan Neon</div>
|
||||
<div class="icon-desc">Turkusowy, futurystyczny</div>
|
||||
</div>
|
||||
|
||||
<!-- N5-C: Multi-color -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">C</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="neonGradC" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#22c55e"/>
|
||||
<stop offset="50%" style="stop-color:#06b6d4"/>
|
||||
<stop offset="100%" style="stop-color:#8b5cf6"/>
|
||||
</linearGradient>
|
||||
<filter id="neonC" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="2" result="blur"/>
|
||||
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#0a0a1a"/>
|
||||
<path d="M28 75 L28 25 L72 75 L72 25" stroke="url(#neonGradC)" stroke-width="6" fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#neonC)"/>
|
||||
<text x="50" y="94" text-anchor="middle" fill="url(#neonGradC)" font-size="11" font-weight="bold" filter="url(#neonC)">GPT</text>
|
||||
<circle cx="50" cy="6" r="4" fill="#fbbf24" filter="url(#neonC)"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Gradient Neon</div>
|
||||
<div class="icon-desc">Zielono-fioletowy gradient</div>
|
||||
</div>
|
||||
|
||||
<!-- N5-D: Pink neon -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">D</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<filter id="neonD" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="2.5" result="blur"/>
|
||||
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#0a0a1a"/>
|
||||
<path d="M28 75 L28 25 L72 75 L72 25" stroke="#ec4899" stroke-width="5" fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#neonD)"/>
|
||||
<circle cx="50" cy="50" r="36" fill="none" stroke="#ec4899" stroke-width="1" opacity="0.3" filter="url(#neonD)"/>
|
||||
<text x="50" y="94" text-anchor="middle" fill="#ec4899" font-size="11" font-weight="bold" filter="url(#neonD)">GPT</text>
|
||||
<circle cx="50" cy="6" r="4" fill="#fbbf24" filter="url(#neonD)"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Różowy Neon</div>
|
||||
<div class="icon-desc">Magenta, wyrazisty</div>
|
||||
</div>
|
||||
|
||||
<!-- N5-E: Double outline -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">E</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<filter id="neonE" x="-50%" y="-50%" width="200%" height="200%">
|
||||
<feGaussianBlur stdDeviation="2" result="blur"/>
|
||||
<feMerge><feMergeNode in="blur"/><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#0a0a1a"/>
|
||||
<!-- Outer N -->
|
||||
<path d="M25 78 L25 22 L75 78 L75 22" stroke="#22c55e" stroke-width="3" fill="none" stroke-linecap="round" stroke-linejoin="round" opacity="0.4" filter="url(#neonE)"/>
|
||||
<!-- Inner N -->
|
||||
<path d="M30 73 L30 27 L70 73 L70 27" stroke="#22c55e" stroke-width="5" fill="none" stroke-linecap="round" stroke-linejoin="round" filter="url(#neonE)"/>
|
||||
<!-- GPT badge -->
|
||||
<rect x="60" y="75" width="30" height="16" rx="4" fill="#22c55e" filter="url(#neonE)"/>
|
||||
<text x="75" y="87" text-anchor="middle" fill="#0a0a1a" font-size="9" font-weight="bold">GPT</text>
|
||||
<circle cx="50" cy="6" r="4" fill="#fbbf24" filter="url(#neonE)"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Podwójne N</div>
|
||||
<div class="icon-desc">Efekt głębi z badge</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="section-divider">
|
||||
<p style="text-align: center; color: rgba(255,255,255,0.4); margin-top: 1rem; font-size: 0.9rem;">
|
||||
Podaj kombinację np. "R4-C" lub "N5-A" do wdrożenia
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
317
static/img/icons-preview.html
Normal file
@ -0,0 +1,317 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>NordaGPT - Propozycje ikon</title>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
||||
min-height: 100vh;
|
||||
padding: 2rem;
|
||||
color: white;
|
||||
}
|
||||
h1 { text-align: center; margin-bottom: 2rem; font-weight: 300; }
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 2rem;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.icon-card {
|
||||
background: rgba(255,255,255,0.05);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
}
|
||||
.icon-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 40px rgba(0,0,0,0.3);
|
||||
border-color: rgba(34, 197, 94, 0.5);
|
||||
}
|
||||
.icon-container {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 0 auto 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.icon-container svg { width: 100%; height: 100%; }
|
||||
.icon-name { font-size: 1.1rem; font-weight: 600; margin-bottom: 0.5rem; color: #22c55e; }
|
||||
.icon-desc { font-size: 0.85rem; color: rgba(255,255,255,0.6); line-height: 1.4; }
|
||||
.icon-number {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
left: 1rem;
|
||||
background: #22c55e;
|
||||
color: #1a1a2e;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.icon-card { position: relative; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>NordaGPT - Propozycje ikon</h1>
|
||||
<div class="grid">
|
||||
|
||||
<!-- 1. Minimalist North Star -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">1</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#22c55e"/>
|
||||
<stop offset="100%" style="stop-color:#059669"/>
|
||||
</linearGradient>
|
||||
<filter id="glow1"><feGaussianBlur stdDeviation="3" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<path d="M50 10 L55 40 L85 50 L55 60 L50 90 L45 60 L15 50 L45 40 Z" fill="url(#g1)" filter="url(#glow1)"/>
|
||||
<circle cx="50" cy="50" r="12" fill="#233e6d"/>
|
||||
<circle cx="50" cy="50" r="8" fill="#22c55e" opacity="0.8"/>
|
||||
<circle cx="50" cy="15" r="4" fill="#fbbf24"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Gwiazda Polarna</div>
|
||||
<div class="icon-desc">Minimalistyczna 4-ramienna gwiazda z akcentem na północ</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. Friendly Chat Bubble -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">2</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="g2" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#3b82f6"/>
|
||||
<stop offset="100%" style="stop-color:#8b5cf6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="10" y="15" width="80" height="55" rx="12" fill="url(#g2)"/>
|
||||
<polygon points="25,70 40,70 30,85" fill="url(#g2)"/>
|
||||
<circle cx="35" cy="42" r="6" fill="white" opacity="0.9"/>
|
||||
<circle cx="50" cy="42" r="6" fill="white" opacity="0.9"/>
|
||||
<circle cx="65" cy="42" r="6" fill="white" opacity="0.9"/>
|
||||
<path d="M50 20 L52 28 L50 26 L48 28 Z" fill="#fbbf24"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Przyjazny Chat</div>
|
||||
<div class="icon-desc">Dymek czatu z animowanymi kropkami i wskaźnikiem północy</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Glowing Compass -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">3</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<radialGradient id="g3" cx="50%" cy="50%" r="50%">
|
||||
<stop offset="0%" style="stop-color:#22c55e;stop-opacity:0.3"/>
|
||||
<stop offset="100%" style="stop-color:#22c55e;stop-opacity:0"/>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="48" fill="#233e6d"/>
|
||||
<circle cx="50" cy="50" r="40" fill="url(#g3)"/>
|
||||
<circle cx="50" cy="50" r="35" fill="none" stroke="#22c55e" stroke-width="2" opacity="0.5"/>
|
||||
<circle cx="50" cy="50" r="25" fill="none" stroke="#22c55e" stroke-width="1.5" opacity="0.3"/>
|
||||
<!-- Compass needle -->
|
||||
<path d="M50 20 L55 50 L50 55 L45 50 Z" fill="#ef4444"/>
|
||||
<path d="M50 80 L55 50 L50 45 L45 50 Z" fill="white" opacity="0.8"/>
|
||||
<circle cx="50" cy="50" r="5" fill="#22c55e"/>
|
||||
<text x="50" y="15" text-anchor="middle" fill="#fbbf24" font-size="10" font-weight="bold">N</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Świecący Kompas</div>
|
||||
<div class="icon-desc">Klasyczny kompas z efektem świecenia i czerwoną igłą</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. Abstract Brain Wave -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">4</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<path d="M20 50 Q 30 30, 40 50 T 60 50 T 80 50" stroke="#22c55e" stroke-width="3" fill="none" opacity="0.6"/>
|
||||
<path d="M20 50 Q 30 70, 40 50 T 60 50 T 80 50" stroke="#3b82f6" stroke-width="3" fill="none" opacity="0.6"/>
|
||||
<path d="M25 50 Q 35 35, 45 50 T 65 50 T 85 50" stroke="#22c55e" stroke-width="2" fill="none"/>
|
||||
<circle cx="50" cy="50" r="15" fill="#1a2d4f" stroke="#22c55e" stroke-width="2"/>
|
||||
<text x="50" y="55" text-anchor="middle" fill="#22c55e" font-size="12" font-weight="bold">AI</text>
|
||||
<circle cx="50" cy="12" r="4" fill="#fbbf24"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Fala Neuronowa</div>
|
||||
<div class="icon-desc">Abstrakcyjne fale mózgowe symbolizujące AI</div>
|
||||
</div>
|
||||
|
||||
<!-- 5. Lighthouse -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">5</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Light rays -->
|
||||
<path d="M50 25 L30 10 M50 25 L50 5 M50 25 L70 10" stroke="#fbbf24" stroke-width="2" opacity="0.6"/>
|
||||
<path d="M50 25 L25 15 M50 25 L75 15" stroke="#fbbf24" stroke-width="1.5" opacity="0.4"/>
|
||||
<!-- Lighthouse -->
|
||||
<path d="M40 85 L45 40 L55 40 L60 85 Z" fill="white"/>
|
||||
<rect x="43" y="30" width="14" height="12" rx="2" fill="#22c55e"/>
|
||||
<rect x="46" y="33" width="8" height="6" fill="#fbbf24"/>
|
||||
<rect x="42" y="50" width="16" height="4" fill="#ef4444"/>
|
||||
<rect x="42" y="65" width="16" height="4" fill="#ef4444"/>
|
||||
<path d="M38 85 L62 85 L60 90 L40 90 Z" fill="#64748b"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Latarnia Morska</div>
|
||||
<div class="icon-desc">Symbolizuje przewodnictwo i wskazywanie drogi w biznesie</div>
|
||||
</div>
|
||||
|
||||
<!-- 6. Cute Robot -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">6</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Antenna -->
|
||||
<line x1="50" y1="25" x2="50" y2="15" stroke="#22c55e" stroke-width="3"/>
|
||||
<circle cx="50" cy="12" r="5" fill="#fbbf24"/>
|
||||
<!-- Head -->
|
||||
<rect x="25" y="28" width="50" height="45" rx="10" fill="#3b82f6"/>
|
||||
<rect x="28" y="31" width="44" height="39" rx="8" fill="#60a5fa"/>
|
||||
<!-- Eyes -->
|
||||
<circle cx="38" cy="48" r="8" fill="white"/>
|
||||
<circle cx="62" cy="48" r="8" fill="white"/>
|
||||
<circle cx="40" cy="48" r="4" fill="#233e6d"/>
|
||||
<circle cx="64" cy="48" r="4" fill="#233e6d"/>
|
||||
<circle cx="41" cy="47" r="1.5" fill="white"/>
|
||||
<circle cx="65" cy="47" r="1.5" fill="white"/>
|
||||
<!-- Smile -->
|
||||
<path d="M38 62 Q 50 72, 62 62" stroke="#233e6d" stroke-width="3" fill="none" stroke-linecap="round"/>
|
||||
<!-- Ears -->
|
||||
<rect x="18" y="40" width="8" height="15" rx="3" fill="#22c55e"/>
|
||||
<rect x="74" y="40" width="8" height="15" rx="3" fill="#22c55e"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Przyjazny Robot</div>
|
||||
<div class="icon-desc">Uroczy robot z uśmiechem i anteną wskazującą północ</div>
|
||||
</div>
|
||||
|
||||
<!-- 7. Magic Sparkle -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">7</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="g7" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#8b5cf6"/>
|
||||
<stop offset="100%" style="stop-color:#ec4899"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Main sparkle -->
|
||||
<path d="M50 15 L53 45 L83 50 L53 55 L50 85 L47 55 L17 50 L47 45 Z" fill="url(#g7)" opacity="0.8"/>
|
||||
<!-- Small sparkles -->
|
||||
<path d="M25 25 L27 32 L34 34 L27 36 L25 43 L23 36 L16 34 L23 32 Z" fill="#fbbf24"/>
|
||||
<path d="M75 70 L76 74 L80 75 L76 76 L75 80 L74 76 L70 75 L74 74 Z" fill="#22c55e"/>
|
||||
<path d="M78 25 L79 28 L82 29 L79 30 L78 33 L77 30 L74 29 L77 28 Z" fill="#fbbf24"/>
|
||||
<circle cx="50" cy="50" r="8" fill="white"/>
|
||||
<text x="50" y="54" text-anchor="middle" fill="#8b5cf6" font-size="10" font-weight="bold">AI</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Magiczna Iskra</div>
|
||||
<div class="icon-desc">Błyszcząca gwiazda symbolizująca magię AI</div>
|
||||
</div>
|
||||
|
||||
<!-- 8. Circle N -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">8</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="g8" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#22c55e"/>
|
||||
<stop offset="100%" style="stop-color:#14b8a6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<circle cx="50" cy="50" r="38" fill="none" stroke="url(#g8)" stroke-width="3"/>
|
||||
<!-- Letter N stylized -->
|
||||
<path d="M32 70 L32 30 L68 70 L68 30" stroke="url(#g8)" stroke-width="8" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<!-- North dot -->
|
||||
<circle cx="50" cy="8" r="5" fill="#fbbf24"/>
|
||||
<!-- Small AI badge -->
|
||||
<circle cx="75" cy="75" r="12" fill="#22c55e"/>
|
||||
<text x="75" y="79" text-anchor="middle" fill="white" font-size="9" font-weight="bold">AI</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Litera N</div>
|
||||
<div class="icon-desc">Stylizowana litera N (Norda) z badge AI</div>
|
||||
</div>
|
||||
|
||||
<!-- 9. Orbit -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">9</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Orbits -->
|
||||
<ellipse cx="50" cy="50" rx="35" ry="15" fill="none" stroke="#22c55e" stroke-width="1.5" opacity="0.5" transform="rotate(-30 50 50)"/>
|
||||
<ellipse cx="50" cy="50" rx="35" ry="15" fill="none" stroke="#3b82f6" stroke-width="1.5" opacity="0.5" transform="rotate(30 50 50)"/>
|
||||
<ellipse cx="50" cy="50" rx="35" ry="15" fill="none" stroke="#8b5cf6" stroke-width="1.5" opacity="0.5" transform="rotate(90 50 50)"/>
|
||||
<!-- Center -->
|
||||
<circle cx="50" cy="50" r="15" fill="#1a2d4f" stroke="#22c55e" stroke-width="2"/>
|
||||
<text x="50" y="54" text-anchor="middle" fill="#22c55e" font-size="11" font-weight="bold">AI</text>
|
||||
<!-- Orbit dots -->
|
||||
<circle cx="50" cy="15" r="5" fill="#fbbf24"/>
|
||||
<circle cx="80" cy="60" r="4" fill="#22c55e"/>
|
||||
<circle cx="25" cy="35" r="4" fill="#3b82f6"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Orbita</div>
|
||||
<div class="icon-desc">Orbity symbolizujące połączenia i sieć biznesową</div>
|
||||
</div>
|
||||
|
||||
<!-- 10. Gradient Compass Simple -->
|
||||
<div class="icon-card">
|
||||
<div class="icon-number">10</div>
|
||||
<div class="icon-container">
|
||||
<svg viewBox="0 0 100 100">
|
||||
<defs>
|
||||
<linearGradient id="g10" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#22c55e"/>
|
||||
<stop offset="50%" style="stop-color:#3b82f6"/>
|
||||
<stop offset="100%" style="stop-color:#8b5cf6"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="50" cy="50" r="45" fill="#233e6d"/>
|
||||
<!-- Simple compass with gradient -->
|
||||
<circle cx="50" cy="50" r="35" fill="none" stroke="url(#g10)" stroke-width="3"/>
|
||||
<line x1="50" y1="20" x2="50" y2="35" stroke="#fbbf24" stroke-width="4" stroke-linecap="round"/>
|
||||
<line x1="50" y1="65" x2="50" y2="80" stroke="url(#g10)" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="20" y1="50" x2="35" y2="50" stroke="url(#g10)" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="65" y1="50" x2="80" y2="50" stroke="url(#g10)" stroke-width="3" stroke-linecap="round"/>
|
||||
<!-- Center dot -->
|
||||
<circle cx="50" cy="50" r="12" fill="#1a2d4f"/>
|
||||
<circle cx="50" cy="50" r="8" fill="url(#g10)"/>
|
||||
<text x="50" y="10" text-anchor="middle" fill="#fbbf24" font-size="8" font-weight="bold">N</text>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="icon-name">Prosty Kompas</div>
|
||||
<div class="icon-desc">Elegancki, minimalistyczny kompas z gradientem</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||