[verified] Replace site branding and icons with approved logo kit

This commit is contained in:
2026-10-20 15:37:07 +03:00
parent 0f075626d1
commit 31842ba2e3
43 changed files with 178 additions and 13 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><rect width="256" height="256" rx="57.6" fill="#131519"/><path d="M128.00 70.34 L109.50 102.39 L146.50 102.39Z M104.24 111.50 L85.74 143.54 L122.74 143.54Z M109.50 108.46 L146.50 108.46 L128.00 140.50Z M151.76 111.50 L133.26 143.54 L170.26 143.54Z M80.48 152.65 L61.98 184.69 L98.98 184.69Z M85.74 149.61 L122.74 149.61 L104.24 181.66Z M133.26 149.61 L170.26 149.61 L151.76 181.66Z M175.52 152.65 L157.02 184.69 L194.02 184.69Z" fill="#f2f1ee"/><path d="M157.02 108.46 L194.02 108.46 L175.52 140.50Z" fill="#d4b47c"/></svg>

After

Width:  |  Height:  |  Size: 662 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><rect width="256" height="256" rx="44" fill="#131519"/><path d="M128.00 52.18 L214.40 201.82 L41.60 201.82Z M156.80 201.82 L99.20 201.82 L128.00 151.94Z" fill="#f2f1ee" fill-rule="evenodd"/><path d="M169.27 109.26 L201.93 109.26 L185.60 137.54Z" fill="#d4b47c"/></svg>

After

Width:  |  Height:  |  Size: 407 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><path d="M128.00 40.97 L98.93 91.32 L157.07 91.32Z M92.00 103.32 L62.93 153.68 L121.07 153.68Z M98.93 99.32 L157.07 99.32 L128.00 149.68Z M164.00 103.32 L134.93 153.68 L193.07 153.68Z M56.00 165.68 L26.93 216.03 L85.07 216.03Z M62.93 161.68 L121.07 161.68 L92.00 212.03Z M134.93 161.68 L193.07 161.68 L164.00 212.03Z M200.00 165.68 L170.93 216.03 L229.07 216.03Z" fill="#000000"/><path d="M170.93 99.32 L229.07 99.32 L200.00 149.68Z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 595 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><path d="M128.00 42.17 L99.97 90.72 L156.03 90.72Z M92.00 104.52 L63.97 153.08 L120.03 153.08Z M99.97 99.92 L156.03 99.92 L128.00 148.48Z M164.00 104.52 L135.97 153.08 L192.03 153.08Z M56.00 166.88 L27.97 215.43 L84.03 215.43Z M63.97 162.28 L120.03 162.28 L92.00 210.83Z M135.97 162.28 L192.03 162.28 L164.00 210.83Z M200.00 166.88 L171.97 215.43 L228.03 215.43Z" fill="#f2f1ee"/><path d="M171.97 99.92 L228.03 99.92 L200.00 148.48Z" fill="#d4b47c"/></svg>

After

Width:  |  Height:  |  Size: 595 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><path d="M128.00 40.97 L98.93 91.32 L157.07 91.32Z M92.00 103.32 L62.93 153.68 L121.07 153.68Z M98.93 99.32 L157.07 99.32 L128.00 149.68Z M164.00 103.32 L134.93 153.68 L193.07 153.68Z M56.00 165.68 L26.93 216.03 L85.07 216.03Z M62.93 161.68 L121.07 161.68 L92.00 212.03Z M134.93 161.68 L193.07 161.68 L164.00 212.03Z M200.00 165.68 L170.93 216.03 L229.07 216.03Z" fill="#131519"/><path d="M170.93 99.32 L229.07 99.32 L200.00 149.68Z" fill="#b08a45"/></svg>

After

Width:  |  Height:  |  Size: 595 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><path d="M128.00 27.86 L242.48 226.14 L13.52 226.14Z M166.16 226.14 L89.84 226.14 L128.00 160.05Z" fill="#f2f1ee" fill-rule="evenodd"/><path d="M182.68 103.49 L225.96 103.49 L204.32 140.97Z" fill="#d4b47c"/></svg>

After

Width:  |  Height:  |  Size: 352 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><path d="M128.00 27.86 L242.48 226.14 L13.52 226.14Z M166.16 226.14 L89.84 226.14 L128.00 160.05Z" fill="#131519" fill-rule="evenodd"/><path d="M182.68 103.49 L225.96 103.49 L204.32 140.97Z" fill="#b08a45"/></svg>

After

Width:  |  Height:  |  Size: 352 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><path d="M128.00 42.17 L99.97 90.72 L156.03 90.72Z M92.00 104.52 L63.97 153.08 L120.03 153.08Z M99.97 99.92 L156.03 99.92 L128.00 148.48Z M164.00 104.52 L135.97 153.08 L192.03 153.08Z M56.00 166.88 L27.97 215.43 L84.03 215.43Z M63.97 162.28 L120.03 162.28 L92.00 210.83Z M135.97 162.28 L192.03 162.28 L164.00 210.83Z M200.00 166.88 L171.97 215.43 L228.03 215.43Z" fill="#ffffff"/><path d="M171.97 99.92 L228.03 99.92 L200.00 148.48Z" fill="#ffffff"/></svg>

After

Width:  |  Height:  |  Size: 595 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.8 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><style>.i{fill:#131519}.g{fill:#b08a45}@media (prefers-color-scheme:dark){.i{fill:#f2f1ee}.g{fill:#d4b47c}}</style><path d="M128.00 27.86 L242.48 226.14 L13.52 226.14Z M166.16 226.14 L89.84 226.14 L128.00 160.05Z" class="i" fill-rule="evenodd"/><path d="M182.68 103.49 L225.96 103.49 L204.32 140.97Z" class="g"/></svg>

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 595 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256.00 256.00" role="img" aria-label="أنور پآي"><title>أنور پآي</title><style>.i{fill:#131519}.g{fill:#b08a45}@media (prefers-color-scheme:dark){.i{fill:#f2f1ee}.g{fill:#d4b47c}}</style><path d="M128.00 27.86 L242.48 226.14 L13.52 226.14Z M166.16 226.14 L89.84 226.14 L128.00 160.05Z" class="i" fill-rule="evenodd"/><path d="M182.68 103.49 L225.96 103.49 L204.32 140.97Z" class="g"/></svg>

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 37 KiB

+1
View File
@@ -0,0 +1 @@
{"name":"أنور پآي","short_name":"أنور پآي","lang":"ar","dir":"rtl","icons":[{"src":"/icon-192.png","sizes":"192x192","type":"image/png"},{"src":"/icon-512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#131519","background_color":"#0c0d0f","display":"standalone"}
+21
View File
@@ -0,0 +1,21 @@
/* Official light lockup for the site's light-only surfaces. Its SVG contains
the approved RTL composition and outlined IBM Plex Sans Arabic wordmark. */
#site img.logo-lockup {
display: block;
width: 152px;
height: 60px;
max-width: none;
object-fit: contain;
flex: none;
transform: none;
filter: none;
background: none;
border-radius: 0;
}
@media (max-width: 640px) {
#site .site-header img.logo-lockup,
#site .menu-head img.logo-lockup {
width: 132px;
height: 52px;
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

+12 -1
View File
@@ -4,6 +4,7 @@ import './globals.css'
import './polish.css'
import './design.css'
import './color-trial.css'
import './brand.css'
/* Bundle Readex Pro's Arabic/Latin variable font so builds never fetch Google Fonts. */
const sans = localFont({
@@ -13,13 +14,23 @@ const sans = localFont({
})
/* The design is light-only: stop browsers' forced dark modes from repainting it. */
export const viewport: Viewport = { colorScheme: 'only light', themeColor: '#ffffff' }
export const viewport: Viewport = { colorScheme: 'only light', themeColor: '#131519' }
export const metadata: Metadata = {
metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? 'https://anwarpi.ai'),
title: { default: 'أنور پآي — محتوى الذكاء الاصطناعي العملي بالعربية', template: '%s — أنور پآي' },
description: 'محتوى عربي عملي عن الذكاء الاصطناعي: تشغيل النماذج محليًا، وبناء الوكلاء، والأتمتة وRAG. استكشف تجارب أنور پآي وشروحات الأدوات بخطوات قابلة للتطبيق.',
alternates: { canonical: './' },
manifest: '/site.webmanifest',
icons: {
icon: [
{ url: '/favicon.ico', sizes: '48x48' },
{ url: '/favicon.svg', type: 'image/svg+xml' },
{ url: '/favicon-32.png', sizes: '32x32', type: 'image/png' },
{ url: '/favicon-16.png', sizes: '16x16', type: 'image/png' },
],
apple: [{ url: '/apple-touch-icon.png', sizes: '180x180' }],
},
openGraph: {
type: 'website',
siteName: 'أنور پآي',
+13
View File
@@ -0,0 +1,13 @@
/* The approved wordmark is outlined in the supplied SVG; never retype it. */
export default function BrandLogo() {
return (
// eslint-disable-next-line @next/next/no-img-element
<img
className="logo-lockup"
src="/brand/anwarpy-horizontal-light.svg"
alt="أنور پآي"
width={152}
height={60}
/>
)
}
+2 -3
View File
@@ -1,4 +1,5 @@
import Link from 'next/link'
import BrandLogo from './brand-logo'
/* Footer — brand column + three link columns. */
export default function Footer() {
@@ -8,9 +9,7 @@ export default function Footer() {
<div className="footer-grid">
<div>
<Link className="logo" href="/">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img className="logo-mark" src="/brand/mark-light.svg" alt="" width={36} height={32} />
أنور پآي
<BrandLogo />
</Link>
<p>محتوى عربي عملي لتعلّم الذكاء الاصطناعي والوكلاء.</p>
</div>
+2 -3
View File
@@ -2,6 +2,7 @@
import { useEffect } from 'react'
import Link from 'next/link'
import BrandLogo from './brand-logo'
import { usePathname } from 'next/navigation'
import { SITE_LINKS } from './site-links'
import AccountLink from './account-link'
@@ -71,9 +72,7 @@ export default function SiteMenu({
<div className="menu-drawer" role="dialog" aria-modal="true" aria-label="قائمة أنور پآي">
<div className="menu-head">
<Link className="logo" href="/">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img className="logo-mark" src="/brand/mark-light.svg" alt="" width={36} height={32} />
أنور پآي
<BrandLogo />
</Link>
<button className="icon-btn" type="button" aria-label="إغلاق القائمة" data-menu-close>×</button>
</div>
+2 -3
View File
@@ -1,4 +1,5 @@
import Link from 'next/link'
import BrandLogo from './brand-logo'
import NavLinks from './nav-links'
import SiteMenu from './site-menu'
import AccountLink from './account-link'
@@ -12,9 +13,7 @@ export default function Topnav({ viewer }: { viewer?: { email: string } | null }
<header className="topnav site-header" data-od-id="topnav">
<div className="container nav-inner">
<Link className="logo" href="/" data-od-id="brand">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img className="logo-mark" src="/brand/mark-light.svg" alt="" width={36} height={32} />
أنور پآي
<BrandLogo />
</Link>
<NavLinks links={SITE_LINKS} />
<div className="nav-tools">
+52
View File
@@ -0,0 +1,52 @@
const test = require('node:test')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const crypto = require('node:crypto')
const root = path.resolve(__dirname, '..')
const read = p => fs.readFileSync(path.join(root, p), 'utf8')
const hash = p => crypto.createHash('sha256').update(fs.readFileSync(path.join(root, p))).digest('hex')
test('all navigation lockups use the approved outlined wordmark component', () => {
for (const file of ['topnav.tsx', 'site-menu.tsx', 'footer.tsx']) {
const source = read(`src/components/${file}`)
assert.match(source, /import BrandLogo from '\.\/brand-logo'/)
assert.match(source, /<BrandLogo \/>/)
assert.doesNotMatch(source, /className="logo-mark"/)
}
const logo = read('src/components/brand-logo.tsx')
assert.match(logo, /alt="أنور پآي"/)
assert.match(logo, /src="\/brand\/anwarpy-horizontal-light\.svg"/)
assert.match(logo, /width=\{152\}/)
})
test('SVG logo masters contain outlined artwork, not scripts or external fonts', () => {
for (const name of ['anwarpy-horizontal-light.svg', 'anwarpy-horizontal-dark.svg']) {
const svg = read(`public/brand/${name}`)
assert.match(svg, /<path/)
assert.doesNotMatch(svg, /<script|<foreignObject|<text\b|https?:\/\/[^" ]+\.(?:js|css|woff)/i)
}
assert.match(read('public/brand/anwarpy-horizontal-light.svg'), /#b08a45/)
assert.match(read('public/brand/anwarpy-horizontal-dark.svg'), /#d4b47c/)
})
test('manifest and all raster icon sizes are internally consistent', () => {
const manifest = JSON.parse(read('public/site.webmanifest'))
assert.equal(manifest.name, 'أنور پآي')
assert.equal(manifest.dir, 'rtl')
for (const [name, size] of [['favicon-16.png',16],['favicon-32.png',32],['favicon-48.png',48],['apple-touch-icon.png',180],['icon-192.png',192],['icon-512.png',512]]) {
const bytes = fs.readFileSync(path.join(root,'public',name))
assert.equal(bytes.readUInt32BE(16), size, name)
assert.equal(bytes.readUInt32BE(20), size, name)
}
for (const icon of manifest.icons) assert.ok(fs.existsSync(path.join(root,'public',icon.src)))
assert.equal(hash('src/app/icon.png'), hash('public/icon-512.png'))
})
test('browser metadata includes the supplied favicon, touch icon and manifest', () => {
const source = read('src/app/layout.tsx')
for (const url of ['/favicon.ico','/favicon.svg','/favicon-32.png','/favicon-16.png','/apple-touch-icon.png','/site.webmanifest']) assert.ok(source.includes(url), url)
assert.match(source, /themeColor: '#131519'/)
assert.match(read('public/favicon.svg'), /prefers-color-scheme:dark/)
assert.match(read('src/app/brand.css'), /width: 132px/)
})