[verified] Replace site branding and icons with approved logo kit
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 5.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><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 |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
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 |
@@ -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 |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.8 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><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 |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 457 B |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 595 B |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 595 B |
|
After Width: | Height: | Size: 451 B |
|
After Width: | Height: | Size: 914 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.6 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><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 |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 37 KiB |
@@ -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"}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
@@ -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: 'أنور پآي',
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -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,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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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/)
|
||||
})
|
||||