diff --git a/homepage/src/app/[locale]/page.module.css b/apps/homepage/src/app/[locale]/page.module.css similarity index 100% rename from homepage/src/app/[locale]/page.module.css rename to apps/homepage/src/app/[locale]/page.module.css diff --git a/apps/homepage/src/components/app-shell/SiteFooter.tsx b/apps/homepage/src/components/app-shell/SiteFooter.tsx index 0a9df54..3397a37 100644 --- a/apps/homepage/src/components/app-shell/SiteFooter.tsx +++ b/apps/homepage/src/components/app-shell/SiteFooter.tsx @@ -2,6 +2,7 @@ import { StatusBadge } from '@/components/foundation/StatusBadge'; import { accountCreateUrl } from '@/lib/account-urls'; import { localizedPath, type Locale } from '@/lib/localization/config'; import type { ShellMessages } from '@/lib/localization/messages'; +import Image from 'next/image'; import styles from './SiteFooter.module.css'; function signInUrl(locale: Locale): string { @@ -54,9 +55,14 @@ export function SiteFooter({ locale, messages }: SiteFooterProps) {
- + RentalDriveGo RentalDriveGo

{footer.tagline}

diff --git a/homepage/eslint.config.mjs b/homepage/eslint.config.mjs deleted file mode 100644 index da90fbc..0000000 --- a/homepage/eslint.config.mjs +++ /dev/null @@ -1,40 +0,0 @@ -import { defineConfig, globalIgnores } from 'eslint/config'; -import nextVitals from 'eslint-config-next/core-web-vitals'; -import nextTypeScript from 'eslint-config-next/typescript'; -import prettier from 'eslint-config-prettier'; - -export default defineConfig([ - ...nextVitals, - ...nextTypeScript, - prettier, - { - rules: { - 'no-console': ['error', { allow: ['log', 'warn', 'error'] }], - }, - }, - { - files: ['**/*.{ts,tsx}'], - languageOptions: { - parserOptions: { - projectService: true, - tsconfigRootDir: import.meta.dirname, - }, - }, - rules: { - '@typescript-eslint/consistent-type-imports': [ - 'error', - { prefer: 'type-imports', fixStyle: 'inline-type-imports' }, - ], - '@typescript-eslint/no-floating-promises': 'error', - '@typescript-eslint/switch-exhaustiveness-check': 'error', - }, - }, - globalIgnores([ - '.next/**', - 'coverage/**', - 'playwright-report/**', - 'test-results/**', - 'contracts/**', - 'next-env.d.ts', - ]), -]); diff --git a/homepage/next-env.d.ts b/homepage/next-env.d.ts deleted file mode 100644 index c4b7818..0000000 --- a/homepage/next-env.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/// -/// -import "./.next/dev/types/routes.d.ts"; - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/homepage/next.config.ts b/homepage/next.config.ts deleted file mode 100644 index df98054..0000000 --- a/homepage/next.config.ts +++ /dev/null @@ -1,79 +0,0 @@ -import type { NextConfig } from 'next'; - -const securityHeaders = [ - { key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' }, - { key: 'X-Content-Type-Options', value: 'nosniff' }, - { key: 'X-Frame-Options', value: 'DENY' }, - { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' }, - { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' }, -]; - -const nextConfig: NextConfig = { - allowedDevOrigins: ['192.168.3.3'], - compress: true, - poweredByHeader: false, - reactStrictMode: true, - - transpilePackages: ['@rentaldrivego/types'], - - images: { - remotePatterns: [ - { - protocol: 'https', - hostname: 'res.cloudinary.com', - }, - ], - }, - - async headers() { - return [ - { - source: '/:path*', - headers: securityHeaders, - }, - ]; - }, - - async redirects() { - return [ - { - source: '/dashboard/dashboard', - destination: '/dashboard', - permanent: false, - }, - { - source: '/dashboard/dashboard/:path*', - destination: '/dashboard/:path*', - permanent: false, - }, - ]; - }, - - async rewrites() { - const dashboardOrigin = - process.env.DASHBOARD_INTERNAL_URL ?? 'http://dashboard:3001'; - const adminOrigin = - process.env.ADMIN_INTERNAL_URL ?? 'http://admin:3002'; - - return [ - { - source: '/dashboard', - destination: `${dashboardOrigin}/dashboard`, - }, - { - source: '/dashboard/:path*', - destination: `${dashboardOrigin}/dashboard/:path*`, - }, - { - source: '/admin', - destination: `${adminOrigin}/admin`, - }, - { - source: '/admin/:path*', - destination: `${adminOrigin}/admin/:path*`, - }, - ]; - }, -}; - -export default nextConfig; diff --git a/homepage/package.json b/homepage/package.json deleted file mode 100644 index e8e059b..0000000 --- a/homepage/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "@rentaldrivego/homepage", - "version": "1.0.0", - "private": true, - "scripts": { - "predev": "npm run build --workspace @rentaldrivego/types", - "dev": "next dev -H 0.0.0.0 -p 3000", - "prebuild": "npm run build --workspace @rentaldrivego/types", - "build": "next build", - "prestart": "npm run build --workspace @rentaldrivego/types", - "pretype-check": "npm run build --workspace @rentaldrivego/types", - "start": "next start -H 0.0.0.0 -p 3000", - "type-check": "tsc --noEmit", - "test": "vitest run", - "test:watch": "vitest", - "lint": "eslint . --max-warnings=0", - "format": "prettier --write .", - "format:check": "prettier --check ." - }, - "dependencies": { - "@fontsource-variable/inter": "^5.2.8", - "@fontsource-variable/noto-sans-arabic": "^5.2.10", - "@rentaldrivego/types": "*", - "next": "^16.2.7", - "react": "^19.2.0", - "react-dom": "^19.2.0", - "zod": "^4.4.0" - }, - "devDependencies": { - "@eslint/js": "^9.0.0", - "@playwright/test": "^1.61.0", - "@testing-library/jest-dom": "^6.9.0", - "@testing-library/react": "^16.3.0", - "@testing-library/user-event": "^14.6.0", - "@types/node": "^20.12.0", - "@types/react": "^19.2.0", - "@types/react-dom": "^19.2.0", - "@vitest/coverage-v8": "^4.1.0", - "eslint": "^9.0.0", - "eslint-config-next": "^16.2.0", - "eslint-config-prettier": "^10.1.0", - "globals": "^17.0.0", - "jsdom": "^29.0.0", - "prettier": "^3.8.0", - "typescript": "^5.4.0", - "typescript-eslint": "^8.0.0", - "vitest": "^4.1.0" - } -} diff --git a/homepage/playwright.config.ts b/homepage/playwright.config.ts deleted file mode 100644 index 39ab4a6..0000000 --- a/homepage/playwright.config.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { defineConfig, devices } from '@playwright/test'; - -const baseURL = process.env.PLAYWRIGHT_BASE_URL ?? 'http://127.0.0.1:3000'; -const executablePath = process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH; -const serverCommand = process.env.PLAYWRIGHT_SERVER_COMMAND ?? 'pnpm start'; - -export default defineConfig({ - testDir: './tests', - testMatch: ['browser/**/*.spec.ts', 'a11y/**/*.spec.ts', 'visual/**/*.spec.ts'], - fullyParallel: true, - forbidOnly: Boolean(process.env.CI), - retries: process.env.CI ? 2 : 0, - ...(process.env.CI ? { workers: 2 } : {}), - reporter: process.env.CI ? [['html', { open: 'never' }], ['github']] : 'list', - expect: { - timeout: 5_000, - toHaveScreenshot: { - animations: 'disabled', - caret: 'hide', - maxDiffPixelRatio: 0.005, - }, - }, - use: { - baseURL, - locale: 'en-US', - timezoneId: 'UTC', - trace: 'retain-on-failure', - screenshot: 'only-on-failure', - video: - process.env.PLAYWRIGHT_VIDEO === 'off' ? 'off' : process.env.CI ? 'retain-on-failure' : 'off', - }, - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - ...(executablePath ? { launchOptions: { executablePath } } : {}), - }, - }, - { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, - { name: 'webkit', use: { ...devices['Desktop Safari'] } }, - { name: 'mobile-chrome', use: { ...devices['Pixel 7'] } }, - { name: 'mobile-safari', use: { ...devices['iPhone 15'] } }, - ], - webServer: { - command: serverCommand, - url: baseURL, - reuseExistingServer: !process.env.CI, - timeout: 120_000, - env: { - SITE_ORIGIN: baseURL, - PUBLIC_RELEASE_APPROVED: 'false', - COMPONENT_FIXTURES_ENABLED: 'true', - NEXT_PUBLIC_DEMO_ENABLED: 'true', - DEMO_SUBMISSION_MODE: 'local', - DEMO_LOCAL_TEST_MODE: 'true', - DEMO_TEST_SCENARIOS_ENABLED: 'true', - NEXT_PUBLIC_ANALYTICS_MODE: 'disabled', - HOSTNAME: '127.0.0.1', - PORT: '3000', - }, - }, -}); diff --git a/homepage/prettier.config.mjs b/homepage/prettier.config.mjs deleted file mode 100644 index b1f4351..0000000 --- a/homepage/prettier.config.mjs +++ /dev/null @@ -1,9 +0,0 @@ -/** @type {import("prettier").Config} */ -const config = { - printWidth: 100, - singleQuote: true, - trailingComma: 'all', - plugins: [], -}; - -export default config; diff --git a/homepage/public/.gitkeep b/homepage/public/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/homepage/public/benefit1_AR.png b/homepage/public/benefit1_AR.png deleted file mode 100644 index bc7f5b0..0000000 Binary files a/homepage/public/benefit1_AR.png and /dev/null differ diff --git a/homepage/public/benefit1_EN.png b/homepage/public/benefit1_EN.png deleted file mode 100644 index 5cd3d5d..0000000 Binary files a/homepage/public/benefit1_EN.png and /dev/null differ diff --git a/homepage/public/benefit1_FR.png b/homepage/public/benefit1_FR.png deleted file mode 100644 index 0288fa7..0000000 Binary files a/homepage/public/benefit1_FR.png and /dev/null differ diff --git a/homepage/public/dashboard1_AR.png b/homepage/public/dashboard1_AR.png deleted file mode 100644 index 5b1fd4c..0000000 Binary files a/homepage/public/dashboard1_AR.png and /dev/null differ diff --git a/homepage/public/dashboard1_EN.png b/homepage/public/dashboard1_EN.png deleted file mode 100644 index d48c2c6..0000000 Binary files a/homepage/public/dashboard1_EN.png and /dev/null differ diff --git a/homepage/public/dashboard1_FR.png b/homepage/public/dashboard1_FR.png deleted file mode 100644 index c6f0e28..0000000 Binary files a/homepage/public/dashboard1_FR.png and /dev/null differ diff --git a/homepage/public/dashboard2_AR.png b/homepage/public/dashboard2_AR.png deleted file mode 100644 index 7ce0783..0000000 Binary files a/homepage/public/dashboard2_AR.png and /dev/null differ diff --git a/homepage/public/dashboard2_EN.png b/homepage/public/dashboard2_EN.png deleted file mode 100644 index 2ece4ea..0000000 Binary files a/homepage/public/dashboard2_EN.png and /dev/null differ diff --git a/homepage/public/dashboard2_FR.png b/homepage/public/dashboard2_FR.png deleted file mode 100644 index 1dac45f..0000000 Binary files a/homepage/public/dashboard2_FR.png and /dev/null differ diff --git a/homepage/public/dashboard3_EN.png b/homepage/public/dashboard3_EN.png deleted file mode 100644 index f24b917..0000000 Binary files a/homepage/public/dashboard3_EN.png and /dev/null differ diff --git a/homepage/public/dashboard4_EN.png b/homepage/public/dashboard4_EN.png deleted file mode 100644 index e78c73c..0000000 Binary files a/homepage/public/dashboard4_EN.png and /dev/null differ diff --git a/homepage/public/dashboard5_AR.png b/homepage/public/dashboard5_AR.png deleted file mode 100644 index 3fb688e..0000000 Binary files a/homepage/public/dashboard5_AR.png and /dev/null differ diff --git a/homepage/public/dashboard5_EN.png b/homepage/public/dashboard5_EN.png deleted file mode 100644 index 76bc626..0000000 Binary files a/homepage/public/dashboard5_EN.png and /dev/null differ diff --git a/homepage/public/dashboard5_FR.png b/homepage/public/dashboard5_FR.png deleted file mode 100644 index 178eaad..0000000 Binary files a/homepage/public/dashboard5_FR.png and /dev/null differ diff --git a/homepage/public/oilchange1_AR.png b/homepage/public/oilchange1_AR.png deleted file mode 100644 index c8020b5..0000000 Binary files a/homepage/public/oilchange1_AR.png and /dev/null differ diff --git a/homepage/public/oilchange1_EN.png b/homepage/public/oilchange1_EN.png deleted file mode 100644 index 92d4bd3..0000000 Binary files a/homepage/public/oilchange1_EN.png and /dev/null differ diff --git a/homepage/public/oilchange1_FR.png b/homepage/public/oilchange1_FR.png deleted file mode 100644 index 47d3d72..0000000 Binary files a/homepage/public/oilchange1_FR.png and /dev/null differ diff --git a/homepage/public/rentaldrivego.png b/homepage/public/rentaldrivego.png deleted file mode 100644 index 24f50ea..0000000 Binary files a/homepage/public/rentaldrivego.png and /dev/null differ diff --git a/homepage/public/workflow1_AR.png b/homepage/public/workflow1_AR.png deleted file mode 100644 index 28a9b66..0000000 Binary files a/homepage/public/workflow1_AR.png and /dev/null differ diff --git a/homepage/public/workflow1_EN.png b/homepage/public/workflow1_EN.png deleted file mode 100644 index dc0ee4a..0000000 Binary files a/homepage/public/workflow1_EN.png and /dev/null differ diff --git a/homepage/public/workflow1_FR.png b/homepage/public/workflow1_FR.png deleted file mode 100644 index 328b9ff..0000000 Binary files a/homepage/public/workflow1_FR.png and /dev/null differ diff --git a/homepage/src/app/[locale]/[slug]/page.tsx b/homepage/src/app/[locale]/[slug]/page.tsx deleted file mode 100644 index ad928cd..0000000 --- a/homepage/src/app/[locale]/[slug]/page.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { StateAction, StateActions, StateShell } from '@/components/app-shell/StateShell'; -import { SignInForm } from '@/components/auth/SignInForm'; -import { ForgotPasswordForm } from '@/components/auth/ForgotPasswordForm'; -import { ResetPasswordForm } from '@/components/auth/ResetPasswordForm'; -import { - isLocale, - localizedPath, - routeIdFromSlug, - type Locale, - type RouteId, -} from '@/lib/localization/config'; -import { getMessages, type ShellMessages } from '@/lib/localization/messages'; -import { buildLocalizedMetadata } from '@/lib/metadata/build-metadata'; -import type { Metadata } from 'next'; -import { notFound } from 'next/navigation'; - -interface PendingRouteProps { - params: Promise<{ locale: string; slug: string }>; -} - -function routeLabel(messages: ShellMessages, routeId: RouteId): string { - const labels = messages.footer.links; - switch (routeId) { - case 'sign-in': - return labels.login; - case 'forgot-password': - return 'Forgot password'; - case 'reset-password': - return 'Reset password'; - case 'privacy': - return labels.privacy; - case 'terms': - return labels.terms; - case 'accessibility': - return labels.accessibility; - case 'home': - return 'RentalDriveGo'; - } -} - -async function resolveParams(params: PendingRouteProps['params']) { - const { locale: localeValue, slug } = await params; - if (!isLocale(localeValue)) notFound(); - const routeId = routeIdFromSlug(localeValue, slug); - if (!routeId || routeId === 'home') notFound(); - return { locale: localeValue as Locale, routeId }; -} - -export async function generateMetadata({ params }: PendingRouteProps): Promise { - const { locale, routeId } = await resolveParams(params); - const messages = getMessages(locale).shell; - const label = routeLabel(messages, routeId); - return buildLocalizedMetadata({ - locale, - routeId, - title: `${label} | ${messages.metadata.pendingTitle}`, - description: messages.metadata.pendingDescription, - indexable: false, - }); -} - -export default async function PendingRoute({ params }: PendingRouteProps) { - const { locale, routeId } = await resolveParams(params); - const messages = getMessages(locale).shell; - const label = routeLabel(messages, routeId); - - if (routeId === 'sign-in') { - return ; - } - - if (routeId === 'forgot-password') { - return ; - } - - if (routeId === 'reset-password') { - return ; - } - - return ( - - - {messages.states.backHome} - - - ); -} diff --git a/homepage/src/app/[locale]/component-lab/ComponentLabInteractive.tsx b/homepage/src/app/[locale]/component-lab/ComponentLabInteractive.tsx deleted file mode 100644 index 1cba5e1..0000000 --- a/homepage/src/app/[locale]/component-lab/ComponentLabInteractive.tsx +++ /dev/null @@ -1,96 +0,0 @@ -'use client'; - -import { Button } from '@/components/actions/Button'; -import { Accordion } from '@/components/controls/Accordion'; -import { SegmentedControl } from '@/components/controls/SegmentedControl'; -import { Tabs } from '@/components/controls/Tabs'; -import { Alert } from '@/components/feedback/Alert'; -import { Checkbox, Switch } from '@/components/forms/ChoiceControls'; -import { FormField } from '@/components/forms/FormField'; -import { TextInput } from '@/components/forms/TextInput'; -import { DropdownMenu } from '@/components/overlays/DropdownMenu'; -import { Dialog } from '@/components/overlays/Dialog'; -import type { ComponentLabCopy } from '@/content/development/component-lab'; -import { useRef, useState } from 'react'; -import styles from './page.module.css'; - -export function ComponentLabInteractive({ copy }: { copy: ComponentLabCopy }) { - const [dialogOpen, setDialogOpen] = useState(false); - const [segment, setSegment] = useState('comfortable'); - const triggerRef = useRef(null); - return ( -
-
-

Actions

-
- - - - - - undefined }, - { - id: 'archive', - label: copy.menu.second, - onSelect: () => undefined, - destructive: true, - }, - ]} - /> -
-
-
-

Form controls

- - - - - - -
-
-

Selection and disclosure

- - -
- - {copy.alert.body} - - -

{copy.dialog.content}

-
-
- ); -} diff --git a/homepage/src/app/[locale]/component-lab/page.module.css b/homepage/src/app/[locale]/component-lab/page.module.css deleted file mode 100644 index 52517f5..0000000 --- a/homepage/src/app/[locale]/component-lab/page.module.css +++ /dev/null @@ -1,32 +0,0 @@ -.main { - min-block-size: 100dvh; -} -.interactiveGrid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: var(--space-6); -} -.group { - display: grid; - align-content: start; - gap: var(--space-4); - min-inline-size: 0; - padding: var(--space-6); - border: 1px solid var(--border-standard); - border-radius: var(--radius-md); - background: var(--surface-elevated); -} -.group h2 { - margin: 0; - font-size: var(--type-heading-3-size); -} -.cluster { - display: flex; - flex-wrap: wrap; - gap: var(--space-3); -} -@media (max-width: 767px) { - .interactiveGrid { - grid-template-columns: 1fr; - } -} diff --git a/homepage/src/app/[locale]/component-lab/page.tsx b/homepage/src/app/[locale]/component-lab/page.tsx deleted file mode 100644 index 120134c..0000000 --- a/homepage/src/app/[locale]/component-lab/page.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { Container, Section, Stack } from '@/components/layout/LayoutPrimitives'; -import { Comparison } from '@/components/marketing/Comparison'; -import { CTA } from '@/components/marketing/CTA'; -import { Metric } from '@/components/marketing/Evidence'; -import { ProductPreview } from '@/components/marketing/ProductPreview'; -import { SectionHeader } from '@/components/marketing/SectionHeader'; -import { Workflow } from '@/components/marketing/Workflow'; -import { getComponentLabCopy } from '@/content/development/component-lab'; -import { isLocale, type Locale } from '@/lib/localization/config'; -import { notFound } from 'next/navigation'; -import { ComponentLabInteractive } from './ComponentLabInteractive'; -import styles from './page.module.css'; - -export const metadata = { robots: { index: false, follow: false } }; - -export default async function ComponentLabPage({ - params, -}: { - params: Promise<{ locale: string }>; -}) { - if (process.env.COMPONENT_FIXTURES_ENABLED !== 'true') notFound(); - const { locale } = await params; - if (!isLocale(locale)) notFound(); - const resolvedLocale: Locale = locale; - const copy = getComponentLabCopy(resolvedLocale); - return ( -
-
- - - - - - - ({ - ...row, - statusTone: index === 0 ? 'success' : 'warning', - }))} - /> - - - - -
-
- ); -} diff --git a/homepage/src/app/[locale]/error.tsx b/homepage/src/app/[locale]/error.tsx deleted file mode 100644 index d516598..0000000 --- a/homepage/src/app/[locale]/error.tsx +++ /dev/null @@ -1,23 +0,0 @@ -'use client'; - -import { StateButton, StateActions, StateShell } from '@/components/app-shell/StateShell'; -import { getClientShellMessages } from '@/lib/localization/client-messages'; -import { useParams } from 'next/navigation'; - -export default function ErrorPage({ - reset, -}: { - error: Error & { digest?: string }; - reset: () => void; -}) { - const params = useParams<{ locale?: string }>(); - const messages = getClientShellMessages(params?.locale); - - return ( - - - {messages.states.retry} - - - ); -} diff --git a/homepage/src/app/[locale]/layout.tsx b/homepage/src/app/[locale]/layout.tsx deleted file mode 100644 index d094193..0000000 --- a/homepage/src/app/[locale]/layout.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import '@fontsource-variable/inter/index.css'; -import '@fontsource-variable/noto-sans-arabic/index.css'; -import '@/styles/tokens.css'; -import '@/styles/component-tokens.css'; -import '@/styles/globals.css'; - -import { SiteFooter } from '@/components/app-shell/SiteFooter'; -import { DemoDialogHost } from '@/components/integrations/DemoDialogHost'; -import { SiteHeader } from '@/components/app-shell/SiteHeader'; -import { ThemeController } from '@/components/app-shell/ThemeController'; -import { getPublicIntegrationConfig } from '@/lib/integrations/environment'; -import { getDirection, isLocale, type Locale } from '@/lib/localization/config'; -import { getMessages } from '@/lib/localization/messages'; -import { themeBootstrapScript } from '@/lib/theme/bootstrap-script'; -import { - isThemePreference, - serverResolvedTheme, - themeCookie, - type ThemePreference, -} from '@/lib/theme/config'; -import { cookies, headers } from 'next/headers'; -import { notFound } from 'next/navigation'; -import type { Metadata } from 'next'; -import type { ReactNode } from 'react'; - -export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }): Promise { - const { locale } = await params; - return { - icons: { - icon: '/rentaldrivego.png', - apple: '/rentaldrivego.png', - }, - }; -} - -export const dynamic = 'force-dynamic'; - -interface LocaleLayoutProps { - children: ReactNode; - params: Promise<{ locale: string }>; -} - -export default async function LocaleLayout({ children, params }: LocaleLayoutProps) { - const { locale: localeValue } = await params; - if (!isLocale(localeValue)) notFound(); - const locale: Locale = localeValue; - const messages = getMessages(locale); - const integrationConfig = getPublicIntegrationConfig(); - const requestHeaders = await headers(); - const nonce = requestHeaders.get('x-nonce') ?? undefined; - const cookieStore = await cookies(); - const cookiePreference = cookieStore.get(themeCookie)?.value; - const preference: ThemePreference = isThemePreference(cookiePreference) - ? cookiePreference - : 'system'; - const resolvedTheme = serverResolvedTheme(preference); - - return ( - - -