update for final push
update for final push
No files matched your search
@@ -16,8 +16,8 @@ const { generateSalt, hashPassword } = require('./utils/hash');
|
||||
// ---- Default admin credentials (change after first login) ----
|
||||
const ADMIN = {
|
||||
username: 'admin',
|
||||
email: process.env.SEED_ADMIN_EMAIL || 'admin@ai-solutions.com',
|
||||
password: process.env.SEED_ADMIN_PASSWORD || 'Admin@2026!',
|
||||
email: process.env.SEED_ADMIN_EMAIL || 'kit24h.ismt.edu.np',
|
||||
password: process.env.SEED_ADMIN_PASSWORD || 'Admin@234',
|
||||
};
|
||||
|
||||
const solutions = [
|
||||
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 7.4 KiB |
@@ -2,6 +2,8 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon-32.png" />
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="%PUBLIC_URL%/favicon-64.png" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#1f1813" />
|
||||
|
||||
|
After Width: | Height: | Size: 149 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 233 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"short_name": "AI-Solutions",
|
||||
"name": "AI-Solutions — Digital Employee Experience",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
@@ -20,6 +20,6 @@
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
"theme_color": "#e8590c",
|
||||
"background_color": "#f7f3ee"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// One-off: crop the brain-network icon out of public/logo.png (a wide
|
||||
// lockup) into square app icons / favicons. Run: node scripts/make-icons.js
|
||||
const path = require('path');
|
||||
const Jimp = require('jimp');
|
||||
|
||||
const SRC = path.resolve(__dirname, '../public/logo.png');
|
||||
const OUT = path.resolve(__dirname, '../public');
|
||||
|
||||
(async () => {
|
||||
const img = await Jimp.read(SRC);
|
||||
const W = img.bitmap.width;
|
||||
const H = img.bitmap.height;
|
||||
|
||||
// The icon sits on the left of the lockup. Crop a square around it.
|
||||
const side = Math.round(H * 0.60);
|
||||
const cx = Math.round(W * 0.285);
|
||||
const cy = Math.round(H * 0.52);
|
||||
let x = Math.max(0, Math.round(cx - side / 2));
|
||||
let y = Math.max(0, Math.round(cy - side / 2));
|
||||
if (x + side > W) x = W - side;
|
||||
if (y + side > H) y = H - side;
|
||||
|
||||
const icon = img.clone().crop(x, y, side, side);
|
||||
|
||||
await icon.clone().resize(512, 512).writeAsync(path.join(OUT, 'logo512.png'));
|
||||
await icon.clone().resize(192, 192).writeAsync(path.join(OUT, 'logo192.png'));
|
||||
await icon.clone().resize(64, 64).writeAsync(path.join(OUT, 'favicon-64.png'));
|
||||
await icon.clone().resize(32, 32).writeAsync(path.join(OUT, 'favicon-32.png'));
|
||||
|
||||
// Tight horizontal lockup for the navbar/footer — trim the uniform
|
||||
// cream border so the logo isn't tiny when scaled to nav height.
|
||||
const lockup = img.clone().autocrop(0.02);
|
||||
await lockup.writeAsync(path.join(OUT, 'logo-lockup.png'));
|
||||
|
||||
console.log(`source ${W}x${H} — icon square ${side}px at (${x}, ${y})`);
|
||||
console.log(`lockup ${lockup.bitmap.width}x${lockup.bitmap.height}`);
|
||||
console.log('wrote logo512, logo192, favicon-64, favicon-32, logo-lockup');
|
||||
})().catch((e) => { console.error(e); process.exit(1); });
|
||||
@@ -1,19 +1,22 @@
|
||||
// Brand mark — mono wordmark + dark rounded "AI" square (DESIGN.md §Brand).
|
||||
// Brand mark — the AI-Solutions logo lockup (public/logo-lockup.png).
|
||||
// On dark surfaces it sits on a light rounded plate so it stays legible.
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
function Brand({ to = '/', onDark = false }) {
|
||||
const inner = (
|
||||
<span className="brand">
|
||||
<span className="brand__mark">AI</span>
|
||||
<span className="brand__word" style={onDark ? { color: 'var(--dark-fg)' } : undefined}>
|
||||
ai-<b>solutions</b>
|
||||
</span>
|
||||
</span>
|
||||
const img = (
|
||||
<img
|
||||
src={`${process.env.PUBLIC_URL}/logo-lockup.png`}
|
||||
alt="AI-Solutions"
|
||||
className={`brand__logo${onDark ? ' brand__logo--plate' : ''}`}
|
||||
width="128"
|
||||
height="45"
|
||||
/>
|
||||
);
|
||||
if (!to) return inner;
|
||||
|
||||
if (!to) return img;
|
||||
return (
|
||||
<Link to={to} aria-label="AI-Solutions home" style={{ textDecoration: 'none' }}>
|
||||
{inner}
|
||||
<Link to={to} className="brand" aria-label="AI-Solutions home">
|
||||
{img}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,10 @@ button { font-family: inherit; }
|
||||
.grid--4 { grid-template-columns: repeat(4, 1fr); }
|
||||
|
||||
/* ---- Brand ---- */
|
||||
.brand { display: inline-flex; align-items: center; gap: 11px; flex: none; }
|
||||
.brand { display: inline-flex; align-items: center; flex: none; }
|
||||
.brand__logo { height: 44px; width: auto; display: block; }
|
||||
/* On dark surfaces (footer/admin) sit the logo on a cream rounded plate */
|
||||
.brand__logo--plate { height: 38px; background: #f6f1e6; padding: 8px 14px; border-radius: 12px; box-sizing: content-box; }
|
||||
.brand__mark {
|
||||
width: 34px; height: 34px; border-radius: 11px; background: var(--grad-accent);
|
||||
color: #fff; display: grid; place-items: center; font-weight: 800; font-size: 14px;
|
||||
@@ -188,8 +191,10 @@ button { font-family: inherit; }
|
||||
.hero__actions { display: flex; flex-wrap: wrap; gap: 14px; }
|
||||
.hero__proof { display: flex; align-items: center; gap: 14px; margin-top: 30px; color: var(--ink-dim); font-size: 14px; }
|
||||
.hero__avatars { display: flex; }
|
||||
.hero__avatars span { width: 34px; height: 34px; border-radius: 999px; border: 2px solid var(--bg); background: var(--grad-accent); color: #fff; display: grid; place-items: center; font-size: 12px; font-weight: 700; margin-left: -10px; }
|
||||
.hero__avatars span:first-child { margin-left: 0; }
|
||||
.hero__avatars span, .hero__avatars img { width: 36px; height: 36px; border-radius: 999px; border: 2px solid var(--bg); margin-left: -10px; }
|
||||
.hero__avatars span { background: var(--grad-accent); color: #fff; display: grid; place-items: center; font-size: 12px; font-weight: 700; }
|
||||
.hero__avatars img { object-fit: cover; background: var(--bg-soft); box-shadow: var(--shadow-xs); }
|
||||
.hero__avatars span:first-child, .hero__avatars img:first-child { margin-left: 0; }
|
||||
|
||||
.hero__media { position: relative; }
|
||||
.hero__media img { width: 100%; border-radius: var(--r-panel); box-shadow: var(--shadow-lg); aspect-ratio: 5/5.4; object-fit: cover; }
|
||||
|
||||
@@ -53,7 +53,10 @@ function Home() {
|
||||
</div>
|
||||
<div className="hero__proof">
|
||||
<div className="hero__avatars" aria-hidden="true">
|
||||
<span>NL</span><span>TM</span><span>WC</span><span>BR</span>
|
||||
<img src="https://randomuser.me/api/portraits/women/68.jpg" alt="" loading="lazy" />
|
||||
<img src="https://randomuser.me/api/portraits/men/32.jpg" alt="" loading="lazy" />
|
||||
<img src="https://randomuser.me/api/portraits/women/44.jpg" alt="" loading="lazy" />
|
||||
<img src="https://randomuser.me/api/portraits/men/75.jpg" alt="" loading="lazy" />
|
||||
</div>
|
||||
<span>Trusted by teams in logistics, manufacturing, healthcare & more</span>
|
||||
</div>
|
||||
|
||||