create-jilatax 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/AGENTS.md +79 -0
- package/template/CLAUDE.md +1 -0
- package/template/public/fonts/jilatax.ttf +0 -0
- package/template/src/app/App.tsx +2 -1
- package/template/src/app/navigation.ts +1 -1
- package/template/src/components/navigation/BottomBar.css +78 -0
- package/template/src/components/navigation/BottomBar.tsx +2 -0
- package/template/src/components/ui/Logo.tsx +44 -0
- package/template/src/screens/AboutScreen.tsx +3 -31
- package/template/src/screens/HomeScreen.tsx +11 -38
- package/template/src/screens/SettingScreen.tsx +9 -0
- package/template/src/styles/global.css +28 -374
- package/template/public/fonts/JilataX.otf +0 -0
- package/template/src/components/ui/Brand.tsx +0 -19
- /package/template/{public/assets/jilatax-icon.png → src/assets/images/logo.png} +0 -0
package/package.json
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project
|
|
4
|
+
|
|
5
|
+
- Android-first Lynx application generated with Jilatax.
|
|
6
|
+
- Stack: TypeScript, Lynx, React, Rspeedy, and the Jilatax CLI.
|
|
7
|
+
- This project is self-contained. Its `package.json`, `bun.lock`, `app.json`, source tree, and Android project belong to this app only.
|
|
8
|
+
- If the parent directory contains other generated apps, treat them as independent projects. Do not edit or run commands in sibling apps unless explicitly requested.
|
|
9
|
+
|
|
10
|
+
## Requirements
|
|
11
|
+
|
|
12
|
+
- Node.js `>=22.18.0`.
|
|
13
|
+
- Bun `1.3.4`, as pinned in `package.json`.
|
|
14
|
+
- Android SDK, Java, and ADB are required only for Android commands.
|
|
15
|
+
|
|
16
|
+
## Package manager
|
|
17
|
+
|
|
18
|
+
- Use Bun exclusively.
|
|
19
|
+
- Run commands from this project root, where `package.json` and `app.json` live.
|
|
20
|
+
- Run `bun install` after cloning or whenever dependencies are missing.
|
|
21
|
+
- Keep `bun.lock` committed and never commit `node_modules/`.
|
|
22
|
+
|
|
23
|
+
## Commands
|
|
24
|
+
|
|
25
|
+
| Action | Command | Notes |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| Install dependencies | `bun install` | Run from this project root |
|
|
28
|
+
| Development server | `bun run dev` | Starts Rspeedy and prints the Lynx QR code |
|
|
29
|
+
| Production bundle | `bun run build` | Builds the Lynx bundle into `dist/` |
|
|
30
|
+
| Typecheck | `bun run typecheck` | Runs `tsc -b` |
|
|
31
|
+
| Run on Android | `bun run run:android` | Builds, installs, configures ADB reverse, and launches the debug app |
|
|
32
|
+
| Production AAB | `bun run create:aab` | Requires Android signing configuration |
|
|
33
|
+
|
|
34
|
+
- No lint, test, or format scripts are configured. Do not invent substitute commands and report these checks as passed.
|
|
35
|
+
|
|
36
|
+
## Architecture
|
|
37
|
+
|
|
38
|
+
- `src/index.tsx` is the runtime entry point and renders `src/app/App.tsx`.
|
|
39
|
+
- `src/app/App.tsx` owns the active-tab state and screen composition.
|
|
40
|
+
- `src/app/navigation.ts` defines the valid app tabs.
|
|
41
|
+
- `src/screens/` contains screen-level components: Home, About, and Setting.
|
|
42
|
+
- `src/components/` contains reusable UI and navigation components.
|
|
43
|
+
- `src/components/navigation/BottomBar.css` is colocated with the bottom navigation; shared app styles live in `src/styles/global.css`.
|
|
44
|
+
- `src/assets/` contains assets imported by application source, such as the interactive logo image.
|
|
45
|
+
- `public/assets/` contains launcher and splash artwork referenced by `app.json`.
|
|
46
|
+
- `public/fonts/` contains fonts loaded by CSS.
|
|
47
|
+
- `lynx.config.ts` configures Rspeedy, React Lynx, QR development, bundle naming, and the required `asset:///` prefix.
|
|
48
|
+
- `app.json` is the source of truth for Jilatax application and Android metadata.
|
|
49
|
+
- `android/` contains the committed native project and Gradle wrapper. Jilatax synchronizes configuration and resources before Android builds.
|
|
50
|
+
|
|
51
|
+
## Implementation conventions
|
|
52
|
+
|
|
53
|
+
- Prefer the existing `app`, `screens`, and `components` boundaries before introducing new abstractions.
|
|
54
|
+
- Keep screen orchestration in `App.tsx`, tab types in `navigation.ts`, and reusable presentation in `components/`.
|
|
55
|
+
- Follow the existing `.js` suffix convention for relative TypeScript imports.
|
|
56
|
+
- Use Lynx elements and events such as `<view>`, `<text>`, `<image>`, and `bindtap`; do not assume browser DOM APIs or React DOM event names.
|
|
57
|
+
- Keep component-specific styles colocated when they are not shared. Put only cross-app styles and theme variables in `src/styles/global.css`.
|
|
58
|
+
- Import source assets from `src/assets/`. Keep launcher and splash paths stable unless `app.json` is updated at the same time.
|
|
59
|
+
- Preserve `output.assetPrefix: 'asset:///'` in `lynx.config.ts`; Android bundle loading depends on it.
|
|
60
|
+
|
|
61
|
+
## Generated and sensitive files
|
|
62
|
+
|
|
63
|
+
- Treat `dist/`, `.jilatax/`, `android/**/build/`, `android/.gradle/`, and `*.tsbuildinfo` as generated output, not source of truth.
|
|
64
|
+
- Do not hand-edit generated resources under `.jilatax/`; change `app.json` or the referenced public assets and let Jilatax regenerate them.
|
|
65
|
+
- Never commit `android/keystore.properties`, `*.jks`, `*.keystore`, `android/local.properties`, environment files, or credentials.
|
|
66
|
+
- Use `android/keystore.properties.example` as the signing configuration reference.
|
|
67
|
+
|
|
68
|
+
## Validation
|
|
69
|
+
|
|
70
|
+
- Run `bun run typecheck` after TypeScript or configuration changes.
|
|
71
|
+
- Run `bun run build` after source, style, asset, or Rspeedy configuration changes.
|
|
72
|
+
- Run Android commands only when the task affects native behavior or explicitly requires device/build verification.
|
|
73
|
+
- Report unavailable checks clearly; do not claim lint or tests passed because neither is configured.
|
|
74
|
+
|
|
75
|
+
## Comment style
|
|
76
|
+
|
|
77
|
+
- Never place comments on the first two lines of a source file; start with imports or declarations.
|
|
78
|
+
- Prefer concise section headings such as `// ── Constants ──` or a three-line banner for major sections.
|
|
79
|
+
- Use JSDoc only when an API, intent, edge case, or constraint needs explanation; do not restate the code.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
Binary file
|
package/template/src/app/App.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { useState } from '@lynx-js/react';
|
|
|
3
3
|
import { BottomBar } from '../components/navigation/BottomBar.js';
|
|
4
4
|
import { AboutScreen } from '../screens/AboutScreen.js';
|
|
5
5
|
import { HomeScreen } from '../screens/HomeScreen.js';
|
|
6
|
+
import { SettingScreen } from '../screens/SettingScreen.js';
|
|
6
7
|
import '../styles/global.css';
|
|
7
8
|
import type { AppTab } from './navigation.js';
|
|
8
9
|
|
|
@@ -11,7 +12,7 @@ export function App() {
|
|
|
11
12
|
|
|
12
13
|
return (
|
|
13
14
|
<view className="app-shell">
|
|
14
|
-
{activeTab === 'home' ? <HomeScreen /> : <AboutScreen />}
|
|
15
|
+
{activeTab === 'home' ? <HomeScreen /> : activeTab === 'about' ? <AboutScreen /> : <SettingScreen />}
|
|
15
16
|
<BottomBar activeTab={activeTab} onSelect={setActiveTab} />
|
|
16
17
|
</view>
|
|
17
18
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type AppTab = 'home' | 'about';
|
|
1
|
+
export type AppTab = 'home' | 'about' | 'setting';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
.bottom-bar-wrap {
|
|
2
|
+
bottom: 11px;
|
|
3
|
+
left: 0;
|
|
4
|
+
padding: 0 22px;
|
|
5
|
+
position: absolute;
|
|
6
|
+
width: 100%;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.bottom-bar {
|
|
10
|
+
background-color: #ffffff;
|
|
11
|
+
border-color: #dfe9e5;
|
|
12
|
+
border-radius: 999px;
|
|
13
|
+
border-style: solid;
|
|
14
|
+
border-width: 1px;
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: row;
|
|
17
|
+
padding: 7px;
|
|
18
|
+
width: 100%;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.bottom-bar__button {
|
|
22
|
+
align-items: center;
|
|
23
|
+
border-radius: 999px;
|
|
24
|
+
display: flex;
|
|
25
|
+
flex: 1;
|
|
26
|
+
flex-direction: row;
|
|
27
|
+
height: 54px;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.bottom-bar__button--active {
|
|
32
|
+
background-color: #e8f7ef;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.bottom-bar__mark {
|
|
36
|
+
border-color: #879990;
|
|
37
|
+
border-radius: 999px;
|
|
38
|
+
border-style: solid;
|
|
39
|
+
border-width: 2px;
|
|
40
|
+
height: 10px;
|
|
41
|
+
margin-right: 8px;
|
|
42
|
+
width: 10px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.bottom-bar__mark--active {
|
|
46
|
+
background-color: #00aa6b;
|
|
47
|
+
border-color: #00aa6b;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.bottom-bar__label {
|
|
51
|
+
color: #72847c;
|
|
52
|
+
font-size: 13px;
|
|
53
|
+
font-weight: 650;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.bottom-bar__label--active {
|
|
57
|
+
color: #08774f;
|
|
58
|
+
font-weight: 800;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@media (prefers-color-scheme: dark) {
|
|
62
|
+
.bottom-bar {
|
|
63
|
+
background-color: #0d2119;
|
|
64
|
+
border-color: #1b382d;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.bottom-bar__button--active {
|
|
68
|
+
background-color: #15392b;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.bottom-bar__label {
|
|
72
|
+
color: #82978e;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.bottom-bar__label--active {
|
|
76
|
+
color: #79efb5;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AppTab } from '../../app/navigation.js';
|
|
2
|
+
import './BottomBar.css';
|
|
2
3
|
|
|
3
4
|
interface BottomBarProps {
|
|
4
5
|
activeTab: AppTab;
|
|
@@ -8,6 +9,7 @@ interface BottomBarProps {
|
|
|
8
9
|
const tabs: ReadonlyArray<{ id: AppTab; label: string }> = [
|
|
9
10
|
{ id: 'home', label: 'Home' },
|
|
10
11
|
{ id: 'about', label: 'About' },
|
|
12
|
+
{ id: 'setting', label: 'Setting' },
|
|
11
13
|
];
|
|
12
14
|
|
|
13
15
|
export function BottomBar({ activeTab, onSelect }: BottomBarProps) {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import logo from '../../assets/images/logo.png';
|
|
2
|
+
|
|
3
|
+
const containerStyle = {
|
|
4
|
+
display: 'flex',
|
|
5
|
+
flexDirection: 'row',
|
|
6
|
+
alignItems: 'center',
|
|
7
|
+
justifyContent: 'center',
|
|
8
|
+
margin: 'auto',
|
|
9
|
+
} as const;
|
|
10
|
+
|
|
11
|
+
const iconWrapperStyle = {
|
|
12
|
+
width: '32px',
|
|
13
|
+
height: '32px',
|
|
14
|
+
display: 'flex',
|
|
15
|
+
justifyContent: 'center',
|
|
16
|
+
alignItems: 'center',
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
const textStyle = { margin: 0 };
|
|
20
|
+
const textWithPaddingStyle = { margin: 0, paddingRight: '8px' };
|
|
21
|
+
const imageStyle = { width: '32px', height: '32px' };
|
|
22
|
+
|
|
23
|
+
interface LogoProps {
|
|
24
|
+
showImage?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function Logo({ showImage }: LogoProps) {
|
|
28
|
+
return (
|
|
29
|
+
<view style={containerStyle}>
|
|
30
|
+
<text className="centered-message" style={textWithPaddingStyle}>
|
|
31
|
+
Welcome
|
|
32
|
+
</text>
|
|
33
|
+
<view style={iconWrapperStyle}>
|
|
34
|
+
{showImage ? (
|
|
35
|
+
<image src={logo} style={imageStyle} />
|
|
36
|
+
) : (
|
|
37
|
+
<text className="centered-message" style={textStyle}>
|
|
38
|
+
🎉
|
|
39
|
+
</text>
|
|
40
|
+
)}
|
|
41
|
+
</view>
|
|
42
|
+
</view>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -1,37 +1,9 @@
|
|
|
1
|
-
import { Brand } from '../components/ui/Brand.js';
|
|
2
|
-
|
|
3
|
-
const principles = [
|
|
4
|
-
{ number: '01', title: 'Simple by default', detail: 'A small structure that stays easy to evolve.' },
|
|
5
|
-
{ number: '02', title: 'Native in the end', detail: 'A direct path from Lynx UI to Android.' },
|
|
6
|
-
{ number: '03', title: 'Built with intent', detail: 'Clear hierarchy, spacing, and interaction.' },
|
|
7
|
-
] as const;
|
|
8
|
-
|
|
9
1
|
export function AboutScreen() {
|
|
10
2
|
return (
|
|
11
|
-
<
|
|
3
|
+
<view className="screen">
|
|
12
4
|
<view className="screen__content">
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
<view className="about-heading">
|
|
16
|
-
<text className="about-heading__label">THE FOUNDATION</text>
|
|
17
|
-
<text className="about-heading__title">Small core.{`\n`}Native result.</text>
|
|
18
|
-
<text className="about-heading__description">
|
|
19
|
-
JILATAX keeps the route from idea to Android direct and understandable.
|
|
20
|
-
</text>
|
|
21
|
-
</view>
|
|
22
|
-
|
|
23
|
-
<view className="principles">
|
|
24
|
-
{principles.map((principle) => (
|
|
25
|
-
<view className="principle" key={principle.number}>
|
|
26
|
-
<text className="principle__number">{principle.number}</text>
|
|
27
|
-
<view className="principle__copy">
|
|
28
|
-
<text className="principle__title">{principle.title}</text>
|
|
29
|
-
<text className="principle__detail">{principle.detail}</text>
|
|
30
|
-
</view>
|
|
31
|
-
</view>
|
|
32
|
-
))}
|
|
33
|
-
</view>
|
|
5
|
+
<text className="centered-message">About</text>
|
|
34
6
|
</view>
|
|
35
|
-
</
|
|
7
|
+
</view>
|
|
36
8
|
);
|
|
37
9
|
}
|
|
@@ -1,45 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useState } from '@lynx-js/react';
|
|
2
|
+
import { Logo } from '../components/ui/Logo.js';
|
|
2
3
|
|
|
3
4
|
export function HomeScreen() {
|
|
4
|
-
|
|
5
|
-
<scroll-view className="screen" scroll-orientation="vertical">
|
|
6
|
-
<view className="screen__content">
|
|
7
|
-
<Brand />
|
|
5
|
+
const [showImage, setShowImage] = useState(false);
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
<text className="eyebrow__text">ANDROID READY</text>
|
|
13
|
-
</view>
|
|
14
|
-
<text className="hero__title">Build clean.{`\n`}Ship native.</text>
|
|
15
|
-
<text className="hero__description">
|
|
16
|
-
A focused foundation for fast Lynx experiences on Android.
|
|
17
|
-
</text>
|
|
18
|
-
</view>
|
|
7
|
+
const handleScreenTap = () => {
|
|
8
|
+
setShowImage((prev) => !prev);
|
|
9
|
+
};
|
|
19
10
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
<view className="workspace-card__status">
|
|
25
|
-
<view className="workspace-card__status-dot" />
|
|
26
|
-
<text className="workspace-card__status-text">LIVE</text>
|
|
27
|
-
</view>
|
|
28
|
-
</view>
|
|
29
|
-
<text className="workspace-card__title">Ready for what comes next.</text>
|
|
30
|
-
<text className="workspace-card__description">
|
|
31
|
-
One clear interface, powered by Lynx and prepared for Android.
|
|
32
|
-
</text>
|
|
33
|
-
<view className="workspace-card__footer">
|
|
34
|
-
<view className="tech-pill">
|
|
35
|
-
<text className="tech-pill__text">LYNX</text>
|
|
36
|
-
</view>
|
|
37
|
-
<view className="tech-pill tech-pill--accent">
|
|
38
|
-
<text className="tech-pill__text tech-pill__text--accent">JILATAX</text>
|
|
39
|
-
</view>
|
|
40
|
-
</view>
|
|
41
|
-
</view>
|
|
11
|
+
return (
|
|
12
|
+
<view className="screen" bindtap={handleScreenTap}>
|
|
13
|
+
<view className="screen__content">
|
|
14
|
+
<Logo showImage={showImage} />
|
|
42
15
|
</view>
|
|
43
|
-
</
|
|
16
|
+
</view>
|
|
44
17
|
);
|
|
45
18
|
}
|
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
@font-face {
|
|
2
|
-
font-family:
|
|
3
|
-
src: url('../../public/fonts/
|
|
2
|
+
font-family: jilatax;
|
|
3
|
+
src: url('../../public/fonts/jilatax.ttf');
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
:root {
|
|
7
|
-
|
|
8
|
-
color: #10241d;
|
|
7
|
+
--bg-color: #f3f7f5;
|
|
8
|
+
--text-color: #10241d;
|
|
9
|
+
background-color: var(--bg-color);
|
|
10
|
+
color: var(--text-color);
|
|
9
11
|
font-family: system-ui, sans-serif;
|
|
10
12
|
}
|
|
11
13
|
|
|
14
|
+
@media (prefers-color-scheme: dark) {
|
|
15
|
+
:root {
|
|
16
|
+
--bg-color: #071510;
|
|
17
|
+
--text-color: #f3fff8;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* ------------------------------------------------
|
|
23
|
+
* ⚡ APP SHELL
|
|
24
|
+
* ------------------------------------------------
|
|
25
|
+
*/
|
|
26
|
+
|
|
12
27
|
.app-shell {
|
|
13
|
-
background-color:
|
|
28
|
+
background-color: var(--bg-color);
|
|
14
29
|
height: 100vh;
|
|
15
30
|
overflow: hidden;
|
|
16
31
|
position: relative;
|
|
@@ -20,381 +35,20 @@
|
|
|
20
35
|
.screen {
|
|
21
36
|
height: 100%;
|
|
22
37
|
width: 100%;
|
|
38
|
+
background-color: var(--bg-color);
|
|
23
39
|
}
|
|
24
40
|
|
|
25
41
|
.screen__content {
|
|
26
42
|
display: flex;
|
|
27
43
|
flex-direction: column;
|
|
28
44
|
padding: 48px 22px 124px;
|
|
45
|
+
height: 100%;
|
|
29
46
|
}
|
|
30
47
|
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
.brand--compact {
|
|
38
|
-
margin-bottom: 38px;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.brand__icon-wrap {
|
|
42
|
-
align-items: center;
|
|
43
|
-
background-color: #e3eee9;
|
|
44
|
-
border-radius: 15px;
|
|
45
|
-
display: flex;
|
|
46
|
-
height: 48px;
|
|
47
|
-
justify-content: center;
|
|
48
|
-
overflow: hidden;
|
|
49
|
-
width: 48px;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.brand__icon {
|
|
53
|
-
height: 82%;
|
|
54
|
-
width: 82%;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.brand__copy {
|
|
58
|
-
display: flex;
|
|
59
|
-
flex-direction: column;
|
|
60
|
-
margin-left: 13px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.brand__name {
|
|
64
|
-
color: #10241d;
|
|
65
|
-
font-size: 18px;
|
|
66
|
-
font-weight: 800;
|
|
67
|
-
letter-spacing: 2px;
|
|
68
|
-
line-height: 22px;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.brand__caption {
|
|
72
|
-
color: #688078;
|
|
73
|
-
font-family: JilataX;
|
|
74
|
-
font-size: 9px;
|
|
75
|
-
letter-spacing: 1.5px;
|
|
76
|
-
line-height: 14px;
|
|
77
|
-
margin-top: 2px;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.hero {
|
|
81
|
-
display: flex;
|
|
82
|
-
flex-direction: column;
|
|
83
|
-
margin-top: 50px;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.eyebrow {
|
|
87
|
-
align-items: center;
|
|
88
|
-
display: flex;
|
|
89
|
-
flex-direction: row;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.eyebrow__dot {
|
|
93
|
-
background-color: #0abf78;
|
|
94
|
-
border-radius: 999px;
|
|
95
|
-
height: 7px;
|
|
96
|
-
margin-right: 8px;
|
|
97
|
-
width: 7px;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.eyebrow__text,
|
|
101
|
-
.about-heading__label {
|
|
102
|
-
color: #008f5a;
|
|
103
|
-
font-size: 11px;
|
|
104
|
-
font-weight: 800;
|
|
105
|
-
letter-spacing: 1.8px;
|
|
106
|
-
line-height: 16px;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.hero__title,
|
|
110
|
-
.about-heading__title {
|
|
111
|
-
color: #10241d;
|
|
112
|
-
font-size: 42px;
|
|
113
|
-
font-weight: 800;
|
|
114
|
-
letter-spacing: -1.5px;
|
|
115
|
-
line-height: 46px;
|
|
116
|
-
margin-top: 14px;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
.hero__description,
|
|
120
|
-
.about-heading__description {
|
|
121
|
-
color: #5c726a;
|
|
122
|
-
font-size: 16px;
|
|
123
|
-
line-height: 24px;
|
|
124
|
-
margin-top: 16px;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.workspace-card {
|
|
128
|
-
background-color: #10241d;
|
|
129
|
-
border-radius: 26px;
|
|
130
|
-
display: flex;
|
|
131
|
-
flex-direction: column;
|
|
132
|
-
margin-top: 38px;
|
|
133
|
-
overflow: hidden;
|
|
134
|
-
padding: 24px;
|
|
135
|
-
position: relative;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.workspace-card__glow {
|
|
139
|
-
background: linear-gradient(135deg, #c7ff36, #00b879);
|
|
140
|
-
border-radius: 999px;
|
|
141
|
-
height: 150px;
|
|
142
|
-
opacity: 0.14;
|
|
143
|
-
position: absolute;
|
|
144
|
-
right: -64px;
|
|
145
|
-
top: -76px;
|
|
146
|
-
width: 150px;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
.workspace-card__top {
|
|
150
|
-
align-items: center;
|
|
151
|
-
display: flex;
|
|
152
|
-
flex-direction: row;
|
|
153
|
-
justify-content: space-between;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.workspace-card__label {
|
|
157
|
-
color: #a8bbb4;
|
|
158
|
-
font-size: 10px;
|
|
159
|
-
font-weight: 800;
|
|
160
|
-
letter-spacing: 1.6px;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
.workspace-card__status {
|
|
164
|
-
align-items: center;
|
|
165
|
-
background-color: #1b382e;
|
|
166
|
-
border-radius: 999px;
|
|
167
|
-
display: flex;
|
|
168
|
-
flex-direction: row;
|
|
169
|
-
padding: 6px 10px;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.workspace-card__status-dot {
|
|
173
|
-
background-color: #b7ff33;
|
|
174
|
-
border-radius: 999px;
|
|
175
|
-
height: 6px;
|
|
176
|
-
margin-right: 6px;
|
|
177
|
-
width: 6px;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.workspace-card__status-text {
|
|
181
|
-
color: #d9ff9c;
|
|
182
|
-
font-size: 9px;
|
|
183
|
-
font-weight: 800;
|
|
184
|
-
letter-spacing: 1px;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
.workspace-card__title {
|
|
188
|
-
color: #f5fff9;
|
|
189
|
-
font-size: 24px;
|
|
190
|
-
font-weight: 750;
|
|
191
|
-
line-height: 30px;
|
|
192
|
-
margin-top: 28px;
|
|
193
|
-
max-width: 250px;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
.workspace-card__description {
|
|
197
|
-
color: #a8bbb4;
|
|
198
|
-
font-size: 14px;
|
|
199
|
-
line-height: 21px;
|
|
200
|
-
margin-top: 10px;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.workspace-card__footer {
|
|
204
|
-
display: flex;
|
|
205
|
-
flex-direction: row;
|
|
206
|
-
margin-top: 24px;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
.tech-pill {
|
|
210
|
-
border-color: #395248;
|
|
211
|
-
border-radius: 999px;
|
|
212
|
-
border-style: solid;
|
|
213
|
-
border-width: 1px;
|
|
214
|
-
padding: 7px 11px;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.tech-pill--accent {
|
|
218
|
-
border-color: #377b5f;
|
|
219
|
-
margin-left: 8px;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
.tech-pill__text {
|
|
223
|
-
color: #9eb1aa;
|
|
224
|
-
font-size: 9px;
|
|
225
|
-
font-weight: 800;
|
|
226
|
-
letter-spacing: 1.1px;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
.tech-pill__text--accent {
|
|
230
|
-
color: #8ee3b7;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
.about-heading {
|
|
234
|
-
display: flex;
|
|
235
|
-
flex-direction: column;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
.principles {
|
|
239
|
-
display: flex;
|
|
240
|
-
flex-direction: column;
|
|
241
|
-
margin-top: 34px;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
.principle {
|
|
245
|
-
align-items: flex-start;
|
|
246
|
-
background-color: #ffffff;
|
|
247
|
-
border-color: #dfe9e5;
|
|
248
|
-
border-radius: 20px;
|
|
249
|
-
border-style: solid;
|
|
250
|
-
border-width: 1px;
|
|
251
|
-
display: flex;
|
|
252
|
-
flex-direction: row;
|
|
253
|
-
margin-bottom: 12px;
|
|
254
|
-
padding: 18px;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
.principle__number {
|
|
258
|
-
color: #00a969;
|
|
259
|
-
font-size: 11px;
|
|
260
|
-
font-weight: 800;
|
|
261
|
-
letter-spacing: 1px;
|
|
262
|
-
line-height: 18px;
|
|
263
|
-
width: 36px;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
.principle__copy {
|
|
267
|
-
display: flex;
|
|
268
|
-
flex: 1;
|
|
269
|
-
flex-direction: column;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
.principle__title {
|
|
273
|
-
color: #10241d;
|
|
274
|
-
font-size: 15px;
|
|
275
|
-
font-weight: 750;
|
|
276
|
-
line-height: 20px;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.principle__detail {
|
|
280
|
-
color: #647970;
|
|
281
|
-
font-size: 13px;
|
|
282
|
-
line-height: 19px;
|
|
283
|
-
margin-top: 4px;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
.bottom-bar-wrap {
|
|
287
|
-
bottom: 22px;
|
|
288
|
-
left: 0;
|
|
289
|
-
padding: 0 22px;
|
|
290
|
-
position: absolute;
|
|
291
|
-
width: 100%;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
.bottom-bar {
|
|
295
|
-
background-color: #ffffff;
|
|
296
|
-
border-color: #dfe9e5;
|
|
297
|
-
border-radius: 22px;
|
|
298
|
-
border-style: solid;
|
|
299
|
-
border-width: 1px;
|
|
300
|
-
display: flex;
|
|
301
|
-
flex-direction: row;
|
|
302
|
-
padding: 7px;
|
|
303
|
-
width: 100%;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.bottom-bar__button {
|
|
307
|
-
align-items: center;
|
|
308
|
-
border-radius: 16px;
|
|
309
|
-
display: flex;
|
|
310
|
-
flex: 1;
|
|
311
|
-
flex-direction: row;
|
|
312
|
-
height: 54px;
|
|
313
|
-
justify-content: center;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
.bottom-bar__button--active {
|
|
317
|
-
background-color: #e8f7ef;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
.bottom-bar__mark {
|
|
321
|
-
border-color: #879990;
|
|
322
|
-
border-radius: 999px;
|
|
323
|
-
border-style: solid;
|
|
324
|
-
border-width: 2px;
|
|
325
|
-
height: 10px;
|
|
326
|
-
margin-right: 8px;
|
|
327
|
-
width: 10px;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
.bottom-bar__mark--active {
|
|
331
|
-
background-color: #00aa6b;
|
|
332
|
-
border-color: #00aa6b;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
.bottom-bar__label {
|
|
336
|
-
color: #72847c;
|
|
337
|
-
font-size: 13px;
|
|
338
|
-
font-weight: 650;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
.bottom-bar__label--active {
|
|
342
|
-
color: #08774f;
|
|
343
|
-
font-weight: 800;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
@media (prefers-color-scheme: dark) {
|
|
347
|
-
:root,
|
|
348
|
-
.app-shell {
|
|
349
|
-
background-color: #071510;
|
|
350
|
-
color: #f3fff8;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
.brand__icon-wrap {
|
|
354
|
-
background-color: #102b21;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
.brand__name,
|
|
358
|
-
.hero__title,
|
|
359
|
-
.about-heading__title,
|
|
360
|
-
.principle__title {
|
|
361
|
-
color: #f3fff8;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.brand__caption,
|
|
365
|
-
.hero__description,
|
|
366
|
-
.about-heading__description,
|
|
367
|
-
.principle__detail {
|
|
368
|
-
color: #8ca198;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
.eyebrow__text,
|
|
372
|
-
.about-heading__label {
|
|
373
|
-
color: #5ce7a6;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
.workspace-card {
|
|
377
|
-
background-color: #0e251c;
|
|
378
|
-
border-color: #1a392d;
|
|
379
|
-
border-style: solid;
|
|
380
|
-
border-width: 1px;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
.principle,
|
|
384
|
-
.bottom-bar {
|
|
385
|
-
background-color: #0d2119;
|
|
386
|
-
border-color: #1b382d;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
.bottom-bar__button--active {
|
|
390
|
-
background-color: #15392b;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
.bottom-bar__label {
|
|
394
|
-
color: #82978e;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
.bottom-bar__label--active {
|
|
398
|
-
color: #79efb5;
|
|
399
|
-
}
|
|
48
|
+
.centered-message {
|
|
49
|
+
font-family: jilatax;
|
|
50
|
+
font-size: 32px;
|
|
51
|
+
text-align: center;
|
|
52
|
+
margin: auto;
|
|
53
|
+
color: var(--text-color);
|
|
400
54
|
}
|
|
Binary file
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import jilataxIcon from '../../../public/assets/jilatax-icon.png';
|
|
2
|
-
|
|
3
|
-
interface BrandProps {
|
|
4
|
-
compact?: boolean;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function Brand({ compact = false }: BrandProps) {
|
|
8
|
-
return (
|
|
9
|
-
<view className={`brand${compact ? ' brand--compact' : ''}`}>
|
|
10
|
-
<view className="brand__icon-wrap">
|
|
11
|
-
<image className="brand__icon" mode="aspectFit" src={jilataxIcon} />
|
|
12
|
-
</view>
|
|
13
|
-
<view className="brand__copy">
|
|
14
|
-
<text className="brand__name">JILATAX</text>
|
|
15
|
-
<text className="brand__caption">LYNX TO ANDROID</text>
|
|
16
|
-
</view>
|
|
17
|
-
</view>
|
|
18
|
-
);
|
|
19
|
-
}
|
|
File without changes
|