diff --git a/src/app/app.routes.spec.ts b/src/app/app.routes.spec.ts
new file mode 100644
index 0000000..110d968
--- /dev/null
+++ b/src/app/app.routes.spec.ts
@@ -0,0 +1,44 @@
+import { TestBed } from '@angular/core/testing';
+import { provideRouter, Router } from '@angular/router';
+
+import { App } from './app';
+import { routes } from './app.routes';
+
+async function renderAppAt(url: string) {
+ TestBed.resetTestingModule();
+
+ await TestBed.configureTestingModule({
+ imports: [App],
+ providers: [provideRouter(routes)]
+ }).compileComponents();
+
+ const router = TestBed.inject(Router);
+ const fixture = TestBed.createComponent(App);
+
+ fixture.detectChanges();
+ await router.navigateByUrl(url);
+ await fixture.whenStable();
+ fixture.detectChanges();
+
+ return { fixture, router };
+}
+
+describe('app routes', () => {
+ it('loads the store layout at /store', async () => {
+ const { fixture, router } = await renderAppAt('/store');
+ const compiled = fixture.nativeElement as HTMLElement;
+
+ expect(router.url).toBe('/store');
+ expect(compiled.querySelector('.store-layout')).not.toBeNull();
+ expect(compiled.querySelector('.store-home')).not.toBeNull();
+ expect(compiled.textContent).toContain('Tienda en construccion');
+ });
+
+ it('keeps the root redirect under componentes-test', async () => {
+ const { fixture, router } = await renderAppAt('/');
+ const compiled = fixture.nativeElement as HTMLElement;
+
+ expect(router.url).toBe('/componentes-test/reutilizables');
+ expect(compiled.textContent).toContain('Componentes reutilizables');
+ });
+});
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index c1ff96f..4d3c5b6 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -6,6 +6,10 @@ export const routes: Routes = [
loadChildren: () =>
import('./features/componentes-test/componentes-test.routes').then((m) => m.routes)
},
+ {
+ path: 'store',
+ loadChildren: () => import('./features/store/store.routes').then((m) => m.routes)
+ },
{
path: '',
pathMatch: 'full',
diff --git a/src/app/core/layout/store-layout/store-layout.component.html b/src/app/core/layout/store-layout/store-layout.component.html
new file mode 100644
index 0000000..c17f63a
--- /dev/null
+++ b/src/app/core/layout/store-layout/store-layout.component.html
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/app/core/layout/store-layout/store-layout.component.scss b/src/app/core/layout/store-layout/store-layout.component.scss
new file mode 100644
index 0000000..2325374
--- /dev/null
+++ b/src/app/core/layout/store-layout/store-layout.component.scss
@@ -0,0 +1,288 @@
+:host {
+ display: flex;
+ min-height: 100dvh;
+ background-color: #f6f6f6;
+ color: #202020;
+}
+
+.store-layout {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.store-layout__container {
+ width: min(100% - 3rem, 75rem);
+ margin: 0 auto;
+}
+
+.store-layout__header {
+ background-color: #ffffff;
+ border-bottom: 1px solid #e9e9e9;
+}
+
+.store-layout__top-bar {
+ border-bottom: 1px solid #efefef;
+}
+
+.store-layout__top-content {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 1.5rem;
+ min-height: 5.5rem;
+ padding: 1rem 0;
+}
+
+.store-layout__brand-slot {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.75rem;
+ min-width: 10rem;
+}
+
+.store-layout__brand-mark {
+ display: grid;
+ place-items: center;
+ width: 2.75rem;
+ height: 2.75rem;
+ border: 1px dashed #bbbbbb;
+ border-radius: 999px;
+ font-size: 1.05rem;
+ font-weight: 700;
+ letter-spacing: 0.04em;
+ color: #373737;
+}
+
+.store-layout__brand-text {
+ font-size: 1.8rem;
+ font-weight: 700;
+ letter-spacing: -0.08em;
+}
+
+.store-layout__tools {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ margin-left: auto;
+}
+
+.store-layout__search {
+ display: flex;
+ align-items: center;
+ width: min(100%, 24rem);
+ min-width: 18rem;
+ border: 1px solid #313131;
+ border-radius: 0.35rem;
+ background-color: #ffffff;
+ overflow: hidden;
+}
+
+.store-layout__search-input {
+ flex: 1;
+ min-width: 0;
+ padding: 0.7rem 0.85rem;
+ border: 0;
+ font-size: 0.95rem;
+ background: transparent;
+
+ &:focus {
+ outline: none;
+ }
+}
+
+.store-layout__search-button,
+.store-layout__header-action,
+.store-layout__category-trigger {
+ border: 0;
+ background: transparent;
+}
+
+.store-layout__search-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 2.75rem;
+ height: 2.75rem;
+ color: #2c2c2c;
+}
+
+.store-layout__actions {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.store-layout__header-action {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 2.5rem;
+ height: 2.5rem;
+ font-size: 1rem;
+ color: #2c2c2c;
+}
+
+.store-layout__category-bar {
+ min-height: 2.35rem;
+}
+
+.store-layout__category-trigger {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.4rem;
+ min-height: 2.35rem;
+ padding: 0;
+ font-size: 0.8rem;
+ font-weight: 700;
+ letter-spacing: 0.02em;
+ text-transform: uppercase;
+ color: #202020;
+}
+
+.store-layout__main {
+ flex: 1;
+ display: block;
+}
+
+.store-layout__footer {
+ margin-top: auto;
+ background-color: #323232;
+ color: #f3f3f3;
+}
+
+.store-layout__footer-content {
+ display: grid;
+ grid-template-columns: minmax(16rem, 1.6fr) repeat(2, minmax(10rem, 1fr)) auto;
+ gap: 2rem;
+ padding: 2.5rem 0;
+}
+
+.store-layout__footer-brand-group,
+.store-layout__footer-section,
+.store-layout__social-group {
+ display: grid;
+ align-content: start;
+ gap: 0.9rem;
+}
+
+.store-layout__brand-slot--footer {
+ min-width: 0;
+}
+
+.store-layout__brand-mark--footer {
+ border-color: rgba(255, 255, 255, 0.35);
+ color: #ffffff;
+}
+
+.store-layout__brand-text--footer {
+ color: #ffffff;
+}
+
+.store-layout__contact-list {
+ display: grid;
+ gap: 0.45rem;
+}
+
+.store-layout__contact-item {
+ display: flex;
+ align-items: center;
+ gap: 0.6rem;
+ font-size: 0.95rem;
+ color: #ececec;
+}
+
+.store-layout__copyright {
+ margin: 0;
+ font-size: 0.85rem;
+ color: #d3d3d3;
+}
+
+.store-layout__footer-heading {
+ margin: 0;
+ font-size: 0.95rem;
+ font-weight: 500;
+ color: #f8f8f8;
+}
+
+.store-layout__footer-links {
+ display: grid;
+ gap: 0.55rem;
+}
+
+.store-layout__footer-link {
+ font-size: 0.95rem;
+ color: #ececec;
+}
+
+.store-layout__social-group {
+ justify-items: start;
+}
+
+.store-layout__social-links {
+ display: flex;
+ align-items: center;
+ gap: 0.85rem;
+ padding-top: 0.1rem;
+}
+
+.store-layout__social-link {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1.1rem;
+ color: #ffffff;
+}
+
+@media (max-width: 991.98px) {
+ .store-layout__top-content {
+ flex-wrap: wrap;
+ }
+
+ .store-layout__tools {
+ flex: 1 1 100%;
+ justify-content: space-between;
+ }
+
+ .store-layout__search {
+ flex: 1 1 auto;
+ width: auto;
+ }
+
+ .store-layout__footer-content {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
+}
+
+@media (max-width: 767.98px) {
+ .store-layout__container {
+ width: min(100% - 1.5rem, 75rem);
+ }
+
+ .store-layout__brand-slot {
+ min-width: 0;
+ }
+
+ .store-layout__brand-text {
+ font-size: 1.45rem;
+ }
+
+ .store-layout__tools {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .store-layout__search {
+ min-width: 0;
+ }
+
+ .store-layout__actions {
+ justify-content: flex-end;
+ }
+
+ .store-layout__footer-content {
+ grid-template-columns: minmax(0, 1fr);
+ gap: 1.5rem;
+ padding: 2rem 0;
+ }
+}
diff --git a/src/app/core/layout/store-layout/store-layout.component.spec.ts b/src/app/core/layout/store-layout/store-layout.component.spec.ts
new file mode 100644
index 0000000..842364c
--- /dev/null
+++ b/src/app/core/layout/store-layout/store-layout.component.spec.ts
@@ -0,0 +1,41 @@
+import { TestBed } from '@angular/core/testing';
+import { provideRouter } from '@angular/router';
+
+import { StoreLayoutComponent } from './store-layout.component';
+
+describe('StoreLayoutComponent', () => {
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [StoreLayoutComponent],
+ providers: [provideRouter([])]
+ }).compileComponents();
+ });
+
+ it('renders the main layout sections', () => {
+ const fixture = TestBed.createComponent(StoreLayoutComponent);
+ fixture.detectChanges();
+
+ const compiled = fixture.nativeElement as HTMLElement;
+
+ expect(compiled.querySelector('.store-layout__header')).not.toBeNull();
+ expect(compiled.querySelector('.store-layout__category-trigger')).not.toBeNull();
+ expect(compiled.querySelector('router-outlet')).not.toBeNull();
+ expect(compiled.querySelector('.store-layout__footer')).not.toBeNull();
+ });
+
+ it('renders the placeholder branding and action icons', () => {
+ const fixture = TestBed.createComponent(StoreLayoutComponent);
+ fixture.detectChanges();
+
+ const compiled = fixture.nativeElement as HTMLElement;
+
+ expect(compiled.querySelector('[data-testid="store-header-brand-slot"]')).not.toBeNull();
+ expect(compiled.querySelector('[data-testid="store-footer-brand-slot"]')).not.toBeNull();
+ expect(compiled.querySelector('.fa-cart-shopping')).not.toBeNull();
+ expect(compiled.querySelector('.fa-circle-user')).not.toBeNull();
+ expect(compiled.querySelector('.fa-instagram')).not.toBeNull();
+ expect(compiled.querySelector('.fa-whatsapp')).not.toBeNull();
+ expect(compiled.querySelector('.fa-facebook')).not.toBeNull();
+ expect(compiled.querySelector('.fa-linkedin-in')).not.toBeNull();
+ });
+});
diff --git a/src/app/core/layout/store-layout/store-layout.component.ts b/src/app/core/layout/store-layout/store-layout.component.ts
new file mode 100644
index 0000000..b71f3d4
--- /dev/null
+++ b/src/app/core/layout/store-layout/store-layout.component.ts
@@ -0,0 +1,68 @@
+import { Component } from '@angular/core';
+import { RouterOutlet } from '@angular/router';
+
+type StoreHeaderAction = {
+ label: string;
+ iconClass: string;
+};
+
+type StoreFooterSection = {
+ heading: string;
+ links: string[];
+};
+
+type StoreSocialLink = {
+ label: string;
+ iconClass: string;
+};
+
+@Component({
+ selector: 'app-store-layout',
+ imports: [RouterOutlet],
+ templateUrl: './store-layout.component.html',
+ styleUrl: './store-layout.component.scss'
+})
+export class StoreLayoutComponent {
+ protected readonly currentYear = new Date().getFullYear();
+
+ protected readonly headerActions: StoreHeaderAction[] = [
+ {
+ label: 'Carrito',
+ iconClass: 'fa-solid fa-cart-shopping'
+ },
+ {
+ label: 'Mi cuenta',
+ iconClass: 'fa-solid fa-circle-user'
+ }
+ ];
+
+ protected readonly footerSections: StoreFooterSection[] = [
+ {
+ heading: 'Cuenta',
+ links: ['Mi cuenta', 'Mis compras', 'Cerrar sesion']
+ },
+ {
+ heading: 'Ayuda',
+ links: ['Contacto', 'Ayuda', 'Preguntas frecuentes']
+ }
+ ];
+
+ protected readonly socialLinks: StoreSocialLink[] = [
+ {
+ label: 'Instagram',
+ iconClass: 'fa-brands fa-instagram'
+ },
+ {
+ label: 'WhatsApp',
+ iconClass: 'fa-brands fa-whatsapp'
+ },
+ {
+ label: 'Facebook',
+ iconClass: 'fa-brands fa-facebook'
+ },
+ {
+ label: 'LinkedIn',
+ iconClass: 'fa-brands fa-linkedin-in'
+ }
+ ];
+}
diff --git a/src/app/features/store/pages/store-home-page/store-home-page.component.html b/src/app/features/store/pages/store-home-page/store-home-page.component.html
new file mode 100644
index 0000000..759ca67
--- /dev/null
+++ b/src/app/features/store/pages/store-home-page/store-home-page.component.html
@@ -0,0 +1,21 @@
+
+
+
+
Store Layout
+
Tienda en construccion
+
+ Esta pagina placeholder deja visible el shell del store mientras se conectan categorias,
+ catalogo y acciones reales.
+
+
+
+
+ @for (highlight of highlights; track highlight) {
+
+ 0{{ $index + 1 }}
+ {{ highlight }}
+
+ }
+
+
+
diff --git a/src/app/features/store/pages/store-home-page/store-home-page.component.scss b/src/app/features/store/pages/store-home-page/store-home-page.component.scss
new file mode 100644
index 0000000..8953f81
--- /dev/null
+++ b/src/app/features/store/pages/store-home-page/store-home-page.component.scss
@@ -0,0 +1,96 @@
+:host {
+ display: block;
+}
+
+.store-home {
+ padding: 3rem 0 4rem;
+}
+
+.store-home__inner {
+ width: min(100% - 3rem, 75rem);
+ margin: 0 auto;
+ display: grid;
+ gap: 1.5rem;
+}
+
+.store-home__hero {
+ padding: clamp(2rem, 4vw, 3rem);
+ border: 1px solid #e4e4e4;
+ border-radius: 1.5rem;
+ background: linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%);
+ box-shadow: 0 1.2rem 2.2rem rgba(17, 17, 17, 0.06);
+}
+
+.store-home__eyebrow {
+ display: inline-block;
+ margin-bottom: 0.75rem;
+ font-size: 0.78rem;
+ font-weight: 700;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: #666666;
+}
+
+h1 {
+ margin-bottom: 0.75rem;
+ font-size: clamp(2rem, 4vw, 3.25rem);
+ font-weight: 700;
+ letter-spacing: -0.05em;
+}
+
+.store-home__lead {
+ max-width: 42rem;
+ margin: 0;
+ font-size: 1rem;
+ line-height: 1.6;
+ color: #4a4a4a;
+}
+
+.store-home__highlights {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 1rem;
+}
+
+.store-home__card {
+ display: grid;
+ gap: 0.9rem;
+ padding: 1.5rem;
+ border: 1px solid #e4e4e4;
+ border-radius: 1.25rem;
+ background-color: #ffffff;
+ box-shadow: 0 0.75rem 1.5rem rgba(17, 17, 17, 0.04);
+}
+
+.store-home__card-index {
+ font-size: 0.85rem;
+ font-weight: 700;
+ letter-spacing: 0.08em;
+ color: #707070;
+}
+
+.store-home__card p {
+ margin: 0;
+ line-height: 1.6;
+ color: #333333;
+}
+
+@media (max-width: 991.98px) {
+ .store-home__highlights {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
+}
+
+@media (max-width: 767.98px) {
+ .store-home {
+ padding: 2rem 0 3rem;
+ }
+
+ .store-home__inner {
+ width: min(100% - 1.5rem, 75rem);
+ }
+
+ .store-home__highlights {
+ grid-template-columns: minmax(0, 1fr);
+ }
+}
diff --git a/src/app/features/store/pages/store-home-page/store-home-page.component.ts b/src/app/features/store/pages/store-home-page/store-home-page.component.ts
new file mode 100644
index 0000000..b708858
--- /dev/null
+++ b/src/app/features/store/pages/store-home-page/store-home-page.component.ts
@@ -0,0 +1,14 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-store-home-page',
+ templateUrl: './store-home-page.component.html',
+ styleUrl: './store-home-page.component.scss'
+})
+export class StoreHomePageComponent {
+ protected readonly highlights = [
+ 'Header y footer listos para conectar con datos reales.',
+ 'Barra de categorias reservada para sumar dropdown despues.',
+ 'Placeholder inicial para validar layout, espaciados y responsive.'
+ ];
+}
diff --git a/src/app/features/store/store.routes.ts b/src/app/features/store/store.routes.ts
new file mode 100644
index 0000000..01a0110
--- /dev/null
+++ b/src/app/features/store/store.routes.ts
@@ -0,0 +1,17 @@
+import { Routes } from '@angular/router';
+
+import { StoreLayoutComponent } from '../../core/layout/store-layout/store-layout.component';
+import { StoreHomePageComponent } from './pages/store-home-page/store-home-page.component';
+
+export const routes: Routes = [
+ {
+ path: '',
+ component: StoreLayoutComponent,
+ children: [
+ {
+ path: '',
+ component: StoreHomePageComponent
+ }
+ ]
+ }
+];
diff --git a/src/environments/environment.local.ts b/src/environments/environment.local.ts
new file mode 100644
index 0000000..8c83d8c
--- /dev/null
+++ b/src/environments/environment.local.ts
@@ -0,0 +1,6 @@
+export const environment = {
+ production: false,
+ nombre:"Desarrollo - activo",
+ url:"http://localhost:8000/api/",
+ urlDescarga:"url/"
+};
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
new file mode 100644
index 0000000..9bb711c
--- /dev/null
+++ b/src/environments/environment.ts
@@ -0,0 +1,6 @@
+export const environment = {
+ production: false,
+ nombre:"Desarrollo - activo",
+ url:"url/api/",
+ urlDescarga:"url/"
+};