From 3957987b0753f8d4c54bad6bde14e48cd5e515ae Mon Sep 17 00:00:00 2001 From: bisco Date: Tue, 5 May 2026 10:26:03 +0200 Subject: [PATCH] feat: refresh frontend visual design --- frontend/src/app/app.component.ts | 198 ++++++++++--- .../booking-placeholder-page.component.ts | 86 ++++-- .../check-in-placeholder-page.component.ts | 89 ++++-- frontend/src/app/pages/home-page.component.ts | 278 +++++++++++++++--- .../reservation-confirm-page.component.ts | 71 +++-- .../show-detail-placeholder-page.component.ts | 84 +++--- .../src/app/pages/show-list-page.component.ts | 84 ++++-- frontend/src/styles.css | 117 ++++++-- 8 files changed, 760 insertions(+), 247 deletions(-) diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts index 9355b39..19be632 100644 --- a/frontend/src/app/app.component.ts +++ b/frontend/src/app/app.component.ts @@ -1,8 +1,6 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router'; import { MatButtonModule } from '@angular/material/button'; -import { MatIconModule } from '@angular/material/icon'; -import { MatToolbarModule } from '@angular/material/toolbar'; @Component({ selector: 'app-root', @@ -11,56 +9,108 @@ import { MatToolbarModule } from '@angular/material/toolbar'; RouterOutlet, RouterLink, RouterLinkActive, - MatToolbarModule, MatButtonModule, - MatIconModule, ], template: `
- - - A - - AzioneLab - Theatre and reservations - - +
+
+ Rome-based theatre company + Reservations, confirmation, and entrance check-in +
+
- -
+
+ +
+ +
`, styles: [` .app-shell { min-height: 100vh; + display: flex; + flex-direction: column; } - .app-toolbar { - position: sticky; - top: 0; - z-index: 10; + .topline { + background: var(--azionelab-surface-dark); + color: rgba(255, 247, 239, 0.84); + font-size: 0.85rem; + } + + .topline-inner, + .header-inner, + .footer-inner { + width: min(100%, var(--azionelab-shell-width)); + margin: 0 auto; + } + + .topline-inner { display: flex; justify-content: space-between; gap: 16px; - min-height: 72px; - padding: 0 24px; - background: rgba(251, 247, 242, 0.88); - backdrop-filter: blur(18px); + padding: 10px 20px; + flex-wrap: wrap; + } + + .site-header { + position: sticky; + top: 0; + z-index: 20; + backdrop-filter: blur(16px); + background: rgba(250, 245, 238, 0.9); border-bottom: 1px solid var(--azionelab-border); } + .header-inner { + display: grid; + grid-template-columns: auto 1fr auto; + align-items: center; + gap: 18px; + min-height: 82px; + padding: 0 20px; + } + .brand { display: inline-flex; align-items: center; - gap: 12px; + gap: 14px; color: inherit; text-decoration: none; } @@ -68,49 +118,117 @@ import { MatToolbarModule } from '@angular/material/toolbar'; .brand-mark { display: inline-grid; place-items: center; - width: 42px; - height: 42px; - border-radius: 10px; - background: linear-gradient(135deg, var(--azionelab-accent), #ca6d3b); - color: white; + width: 48px; + height: 48px; + border-radius: 14px; + background: linear-gradient(145deg, var(--azionelab-accent), var(--azionelab-accent-soft)); + color: #fff8f2; font-weight: 700; + box-shadow: 0 14px 30px rgba(111, 40, 33, 0.18); } .brand-text { display: flex; flex-direction: column; - line-height: 1.1; + line-height: 1.05; + } + + .brand-text strong { + font-family: var(--azionelab-serif); + font-size: 1.4rem; + font-weight: 700; } .brand-text small { color: var(--azionelab-muted); - font-size: 0.74rem; + font-size: 0.78rem; } .main-nav { display: flex; align-items: center; - gap: 4px; + justify-content: center; + gap: 6px; flex-wrap: wrap; } .main-nav .active { - background: rgba(159, 47, 40, 0.08); + background: rgba(143, 51, 45, 0.1); + } + + .header-actions { + display: flex; + justify-content: flex-end; } .page-shell { - padding: 32px 20px 56px; + flex: 1; + padding: 40px 20px 72px; + } + + .site-footer { + border-top: 1px solid var(--azionelab-border); + background: + linear-gradient(180deg, rgba(255, 251, 246, 0.86), rgba(244, 235, 223, 0.92)); + } + + .footer-inner { + display: grid; + grid-template-columns: minmax(0, 1.5fr) auto; + gap: 24px; + align-items: start; + padding: 28px 20px 34px; + } + + .footer-title { + margin: 0 0 8px; + font-family: var(--azionelab-serif); + font-size: 1.15rem; + font-weight: 700; + color: var(--azionelab-ink); + } + + .footer-copy { + margin: 0; + max-width: 52ch; + color: var(--azionelab-muted); + line-height: 1.6; + } + + .footer-nav { + display: flex; + flex-wrap: wrap; + gap: 14px; + } + + .footer-nav a { + color: var(--azionelab-ink-soft); + text-decoration: none; } @media (max-width: 800px) { - .app-toolbar { + .header-inner { + grid-template-columns: 1fr; align-items: flex-start; - flex-direction: column; - padding: 16px 16px 14px; + padding: 16px; } .main-nav { width: 100%; + justify-content: flex-start; + } + + .header-actions { + width: 100%; + } + + .footer-inner { + grid-template-columns: 1fr; + padding: 24px 16px 28px; + } + + .page-shell { + padding: 28px 16px 52px; } } `], diff --git a/frontend/src/app/pages/booking-placeholder-page.component.ts b/frontend/src/app/pages/booking-placeholder-page.component.ts index 763bbfa..ac99a7b 100644 --- a/frontend/src/app/pages/booking-placeholder-page.component.ts +++ b/frontend/src/app/pages/booking-placeholder-page.component.ts @@ -36,8 +36,21 @@ type ApiValidationErrors = Record;

- - +
+ + +

Before you submit

+

Reservations are activated only after email confirmation.

+
    +
  • Your confirmation link arrives at the email address you provide.
  • +
  • Seat availability is checked on the server before confirmation.
  • +
  • The QR code is generated only after the reservation becomes confirmed.
  • +
+
+
+ + + @if (isSuccess()) {
@@ -131,52 +144,69 @@ type ApiValidationErrors = Record;
} - - + + +
`, styles: [` - .page { - max-width: 760px; - margin: 0 auto; - } - .page-header { - margin-bottom: 24px; - } - - .eyebrow { - margin: 0 0 10px; - color: var(--azionelab-accent); - text-transform: uppercase; - font-size: 0.78rem; - font-weight: 700; - } - - h1 { - margin: 0; - font-size: clamp(2rem, 4vw, 3rem); + margin-bottom: 26px; } .supporting { - color: var(--azionelab-muted); - line-height: 1.6; max-width: 56ch; margin: 14px 0 0; } + .booking-grid { + display: grid; + grid-template-columns: minmax(0, 320px) minmax(0, 1fr); + gap: 20px; + align-items: start; + } + + .summary-card, .content-card { - border-radius: 20px; + border-radius: var(--azionelab-radius-lg); border: 1px solid var(--azionelab-border); background: var(--azionelab-surface-strong); box-shadow: var(--azionelab-shadow); overflow: hidden; } + .summary-card { + background: + linear-gradient(180deg, rgba(255, 252, 248, 0.98), rgba(247, 238, 227, 0.94)); + } + mat-card-content { padding: 28px !important; } + .summary-label { + margin: 0 0 10px; + font-size: 0.78rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--azionelab-accent); + } + + .summary-card h2 { + margin: 0; + max-width: 14ch; + } + + .summary-list { + display: grid; + gap: 12px; + margin: 18px 0 0; + padding-left: 18px; + color: var(--azionelab-ink-soft); + line-height: 1.6; + } + .intro-note { display: flex; align-items: flex-start; @@ -317,6 +347,10 @@ type ApiValidationErrors = Record; } @media (max-width: 640px) { + .booking-grid { + grid-template-columns: 1fr; + } + mat-card-content { padding: 22px !important; } diff --git a/frontend/src/app/pages/check-in-placeholder-page.component.ts b/frontend/src/app/pages/check-in-placeholder-page.component.ts index af5e587..b608896 100644 --- a/frontend/src/app/pages/check-in-placeholder-page.component.ts +++ b/frontend/src/app/pages/check-in-placeholder-page.component.ts @@ -68,8 +68,21 @@ type BarcodeDetectorConstructor = new (options?: { formats?: string[] }) => Barc

Enter a token manually or scan a QR code to preview admission data and confirm entrance.

- - +
+ + +

Front of house

+

Designed for quick, low-friction arrivals.

+
    +
  • Scan a QR code when a device camera is available.
  • +
  • Enter the token manually if scanning is not possible.
  • +
  • Confirm admission only after the preview data matches the guest.
  • +
+
+
+ + +

Camera scan

@@ -175,46 +188,62 @@ type BarcodeDetectorConstructor = new (options?: { formats?: string[] }) => Barc @if (state() === 'error') {

Something went wrong. Please try again.

} - - + + +
`, styles: [` - .page { - max-width: 760px; - margin: 0 auto; - } - .page-header { - margin-bottom: 22px; - } - - .eyebrow { - margin: 0 0 10px; - color: var(--azionelab-accent); - text-transform: uppercase; - font-size: 0.78rem; - font-weight: 700; - } - - h1 { - margin: 0; - font-size: clamp(2rem, 4vw, 3rem); + margin-bottom: 24px; } .supporting { - color: var(--azionelab-muted); - line-height: 1.6; max-width: 50ch; } + .checkin-grid { + display: grid; + grid-template-columns: minmax(0, 300px) minmax(0, 1fr); + gap: 20px; + align-items: start; + } + + .side-card, .content-card { - border-radius: 8px; + border-radius: var(--azionelab-radius-lg); border: 1px solid var(--azionelab-border); - background: var(--azionelab-surface); + background: var(--azionelab-surface-strong); box-shadow: var(--azionelab-shadow); } + .side-card { + background: + linear-gradient(180deg, rgba(255, 252, 248, 0.98), rgba(247, 238, 227, 0.94)); + } + + .side-label { + margin: 0 0 10px; + font-size: 0.78rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--azionelab-accent); + } + + .side-card h2 { + margin: 0; + } + + .side-list { + display: grid; + gap: 12px; + margin: 18px 0 0; + padding-left: 18px; + color: var(--azionelab-ink-soft); + line-height: 1.6; + } + .scanner-panel { display: grid; gap: 14px; @@ -320,6 +349,12 @@ type BarcodeDetectorConstructor = new (options?: { formats?: string[] }) => Barc color: #b3261e; font-weight: 500; } + + @media (max-width: 760px) { + .checkin-grid { + grid-template-columns: 1fr; + } + } `], changeDetection: ChangeDetectionStrategy.OnPush, }) diff --git a/frontend/src/app/pages/home-page.component.ts b/frontend/src/app/pages/home-page.component.ts index 3911ddd..65610cd 100644 --- a/frontend/src/app/pages/home-page.component.ts +++ b/frontend/src/app/pages/home-page.component.ts @@ -9,66 +9,103 @@ import { API_BASE_URL } from '../services/api-config.token'; standalone: true, imports: [RouterLink, MatButtonModule, MatCardModule], template: ` -
+

AzioneLab Theatre Company

-

Public website and booking UI foundations.

+

Small-stage evenings, thoughtful performances, simple reservations.

- This Angular shell is wired for the existing Django APIs and ready for the next booking-focused iterations. + AzioneLab brings contemporary theatre into intimate venues. This public frontend is shaped around clear show discovery, lightweight booking, and a calm arrival experience at the door.

-
- - Frontend wiring + +
+ +
+
+
+

At a glance

+

Built for a small company, not a sprawling ticketing empire

+
+

The public experience stays simple: browse a show, reserve seats, confirm by email, arrive with a QR code.

+
+ +
+ + Find the right performance -

API base URL

- {{ apiBaseUrl }} -

Placeholders are in place for public content, booking, and staff check-in flows.

+

Show listings and detail pages keep venue, schedule, and availability visible without noise.

+
+
+ + Confirm by email + +

Reservations stay pending until the audience member confirms, which keeps capacity trustworthy and easy to manage.

+
+
+ + Check in quickly + +

Front-of-house staff can preview a token, validate it server-side, and record entry in one compact flow.

+ +
+
+

Audience journey

+

From interest to entrance in a few quiet steps

+
    +
  1. Browse the public programme and open a show page.
  2. +
  3. Reserve seats for a performance and confirm by email.
  4. +
  5. Keep the QR code ready on your phone or on paper for entry.
  6. +
+
+ + + Runtime wiring + +

API base URL

+ {{ apiBaseUrl }} +

The frontend remains aligned with the existing Django API surface without changing backend contracts.

+
+
+
`, styles: [` .hero { display: grid; - grid-template-columns: minmax(0, 1.4fr) minmax(280px, 0.9fr); + grid-template-columns: minmax(0, 1.3fr) minmax(280px, 0.9fr); gap: 28px; align-items: stretch; - max-width: 1180px; - margin: 0 auto; + padding: 12px 0 24px; } .hero-copy { - padding: 36px 0; - } - - .eyebrow { - margin: 0 0 12px; - color: var(--azionelab-accent); - text-transform: uppercase; - font-size: 0.78rem; - font-weight: 700; + padding: 34px 0 20px; } h1 { margin: 0; - max-width: 10ch; - font-size: clamp(2.5rem, 5vw, 4.75rem); - line-height: 0.95; + max-width: 11ch; + font-size: 3.85rem; } .supporting { - max-width: 52ch; - color: var(--azionelab-muted); - font-size: 1.08rem; - line-height: 1.65; margin: 20px 0 0; + font-size: 1.06rem; } .hero-actions { @@ -78,32 +115,189 @@ import { API_BASE_URL } from '../services/api-config.token'; margin-top: 28px; } - .hero-panel mat-card { - height: 100%; - border-radius: 8px; + .hero-stage { + position: relative; + overflow: hidden; + min-height: 420px; + border-radius: var(--azionelab-radius-lg); + border: 1px solid rgba(255, 250, 245, 0.16); + background: + linear-gradient(180deg, rgba(31, 18, 18, 0.1), rgba(27, 18, 14, 0.62)), + linear-gradient(135deg, #b04b40 0%, #7f251f 24%, #43261f 56%, #211b1a 100%); + box-shadow: var(--azionelab-shadow-strong); + } + + .curtain { + position: absolute; + inset: 0; + background: + linear-gradient(90deg, rgba(255, 255, 255, 0.08) 0, rgba(255, 255, 255, 0) 22%, rgba(255, 255, 255, 0.08) 48%, rgba(255, 255, 255, 0) 74%, rgba(255, 255, 255, 0.08) 100%), + repeating-linear-gradient(90deg, rgba(75, 18, 14, 0.2) 0 18px, rgba(160, 60, 52, 0.08) 18px 36px); + opacity: 0.9; + } + + .stage-glow { + position: absolute; + left: 50%; + bottom: -80px; + width: 340px; + height: 340px; + transform: translateX(-50%); + border-radius: 50%; + background: radial-gradient(circle, rgba(245, 214, 150, 0.9) 0, rgba(245, 214, 150, 0.22) 44%, rgba(245, 214, 150, 0) 72%); + } + + .stage-copy { + position: absolute; + left: 24px; + right: 24px; + bottom: 24px; + display: grid; + gap: 8px; + padding: 18px 20px; + border-radius: 18px; + background: rgba(24, 17, 15, 0.52); + backdrop-filter: blur(8px); + color: rgba(255, 247, 239, 0.94); + border: 1px solid rgba(255, 247, 239, 0.12); + } + + .stage-copy span { + text-transform: uppercase; + font-size: 0.76rem; + letter-spacing: 0.08em; + color: rgba(255, 227, 192, 0.84); + } + + .stage-copy strong { + font-family: var(--azionelab-serif); + font-size: 1.4rem; + font-weight: 700; + line-height: 1.15; + } + + .overview, + .journey-grid { + margin-top: 34px; + } + + .section-heading { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(260px, 420px); + gap: 24px; + align-items: end; + margin-bottom: 20px; + } + + .section-heading h2, + .journey-copy h2 { + margin: 0; + max-width: 18ch; + } + + .feature-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 18px; + } + + .feature-card, + .meta-card { + border-radius: var(--azionelab-radius-md); border: 1px solid var(--azionelab-border); - background: var(--azionelab-surface); + background: linear-gradient(180deg, rgba(255, 253, 250, 0.98), rgba(251, 245, 236, 0.94)); box-shadow: var(--azionelab-shadow); } + .feature-card { + min-height: 210px; + } + + .feature-card mat-card-title, + .meta-card mat-card-title { + margin-bottom: 12px; + font-family: var(--azionelab-serif); + font-size: 1.18rem; + font-weight: 700; + } + + .feature-card p, + .meta-card p { + margin: 0; + color: var(--azionelab-muted); + line-height: 1.6; + } + + .journey-grid { + display: grid; + grid-template-columns: minmax(0, 1.2fr) minmax(280px, 0.9fr); + gap: 24px; + align-items: start; + } + + .journey-copy { + padding: 10px 0; + } + + ol { + display: grid; + gap: 12px; + margin: 20px 0 0; + padding-left: 22px; + color: var(--azionelab-ink-soft); + line-height: 1.65; + } + + .meta-label { + margin: 0 0 10px; + font-size: 0.8rem; + font-weight: 700; + text-transform: uppercase; + color: var(--azionelab-muted); + letter-spacing: 0.08em; + } + code { display: inline-block; - margin-top: 8px; padding: 10px 12px; - border-radius: 8px; - background: rgba(30, 27, 24, 0.06); + border-radius: 12px; + background: rgba(34, 28, 24, 0.06); + color: var(--azionelab-ink-soft); + word-break: break-word; } - .panel-note { - margin-top: 20px; - color: var(--azionelab-muted); - line-height: 1.5; + .meta-note { + margin: 18px 0 0; } @media (max-width: 900px) { - .hero { + .hero, + .section-heading, + .journey-grid, + .feature-grid { grid-template-columns: 1fr; } + + h1 { + font-size: 2.9rem; + } + } + + @media (max-width: 640px) { + h1 { + font-size: 2.25rem; + } + + .hero-stage { + min-height: 320px; + } + + .stage-copy { + left: 16px; + right: 16px; + bottom: 16px; + padding: 16px; + } } `], changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/frontend/src/app/pages/reservation-confirm-page.component.ts b/frontend/src/app/pages/reservation-confirm-page.component.ts index cdd26c0..110d195 100644 --- a/frontend/src/app/pages/reservation-confirm-page.component.ts +++ b/frontend/src/app/pages/reservation-confirm-page.component.ts @@ -68,6 +68,17 @@ type ConfirmationState = 'loading' | 'success' | 'invalid' | 'expired' | 'error'

Check-in URL: {{ confirmation()!.qr_code_url }}

} + +
+
+

What to do next

+

Keep the QR code on your phone or print it. Staff can scan it directly at the entrance.

+
+
+

Need the link later?

+

Save the confirmation email so you can reopen the check-in page if the QR needs to be shown again.

+
+
} @if (state() === 'invalid') { @@ -115,37 +126,17 @@ type ConfirmationState = 'loading' | 'success' | 'invalid' | 'expired' | 'error' `, styles: [` - .page { - max-width: 760px; - margin: 0 auto; - } - .page-header { margin-bottom: 24px; } - .eyebrow { - margin: 0 0 10px; - color: var(--azionelab-accent); - text-transform: uppercase; - font-size: 0.78rem; - font-weight: 700; - } - - h1 { - margin: 0; - font-size: clamp(2rem, 4vw, 3rem); - } - .supporting { - color: var(--azionelab-muted); - line-height: 1.6; max-width: 58ch; margin: 14px 0 0; } .status-card { - border-radius: 20px; + border-radius: var(--azionelab-radius-lg); border: 1px solid var(--azionelab-border); background: var(--azionelab-surface-strong); box-shadow: var(--azionelab-shadow); @@ -172,7 +163,6 @@ type ConfirmationState = 'loading' | 'success' | 'invalid' | 'expired' | 'error' .status-panel h2 { margin: 0 0 6px; - font-size: 1.2rem; } .status-panel p { @@ -262,7 +252,7 @@ type ConfirmationState = 'loading' | 'success' | 'invalid' | 'expired' | 'error' .qr-panel { margin-top: 18px; padding: 16px; - border-radius: 18px; + border-radius: var(--azionelab-radius-md); border: 1px solid var(--azionelab-border); display: inline-block; background: white; @@ -289,7 +279,7 @@ type ConfirmationState = 'loading' | 'success' | 'invalid' | 'expired' | 'error' gap: 10px; margin-top: 16px; padding: 14px 16px; - border-radius: 16px; + border-radius: var(--azionelab-radius-md); background: rgba(159, 47, 40, 0.05); color: var(--azionelab-muted); } @@ -303,6 +293,35 @@ type ConfirmationState = 'loading' | 'success' | 'invalid' | 'expired' | 'error' color: var(--azionelab-accent-strong); } + .next-steps { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px; + margin-top: 18px; + } + + .next-steps > div { + padding: 16px; + border-radius: var(--azionelab-radius-md); + background: rgba(34, 28, 24, 0.035); + border: 1px solid var(--azionelab-border); + } + + .step-label { + margin: 0 0 6px !important; + font-size: 0.8rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--azionelab-accent); + } + + .next-steps p { + margin: 0; + line-height: 1.55; + color: var(--azionelab-muted); + } + @media (max-width: 640px) { mat-card-content { padding: 22px !important; @@ -325,6 +344,10 @@ type ConfirmationState = 'loading' | 'success' | 'invalid' | 'expired' | 'error' width: min(100%, 280px); margin: 0 auto; } + + .next-steps { + grid-template-columns: 1fr; + } } `], changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/frontend/src/app/pages/show-detail-placeholder-page.component.ts b/frontend/src/app/pages/show-detail-placeholder-page.component.ts index fe32853..a74e4fc 100644 --- a/frontend/src/app/pages/show-detail-placeholder-page.component.ts +++ b/frontend/src/app/pages/show-detail-placeholder-page.component.ts @@ -49,6 +49,10 @@ import { ShowDetail, ShowPerformance, ShowsApiService } from '../services/shows-

Show detail

{{ show()!.title }}

{{ show()!.description || show()!.summary }}

+
+ Published programme + Choose a performance below to continue +
@if (show()!.image_url) {
@@ -116,52 +120,51 @@ import { ShowDetail, ShowPerformance, ShowsApiService } from '../services/shows- `, styles: [` - .page { - max-width: 1080px; - margin: 0 auto; - } - .page-header { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(280px, 420px); - gap: 24px; + gap: 28px; align-items: start; - margin-bottom: 28px; + margin-bottom: 32px; } .hero-copy { min-width: 0; - } - - .eyebrow { - margin: 0 0 10px; - color: var(--azionelab-accent); - text-transform: uppercase; - font-size: 0.78rem; - font-weight: 700; - } - - h1 { - margin: 0; - font-size: clamp(2rem, 4vw, 3.2rem); + padding: 8px 0; } .supporting { margin: 14px 0 0; - color: var(--azionelab-muted); - line-height: 1.6; - max-width: 64ch; + } + + .hero-note { + display: flex; + gap: 10px; + flex-wrap: wrap; + margin-top: 18px; + } + + .hero-note span { + display: inline-flex; + align-items: center; + min-height: 32px; + padding: 0 14px; + border-radius: 999px; + background: rgba(143, 51, 45, 0.08); + color: var(--azionelab-accent-strong); + font-size: 0.85rem; + font-weight: 700; } .hero-image-wrap { overflow: hidden; - border-radius: 12px; + border-radius: var(--azionelab-radius-lg); border: 1px solid var(--azionelab-border); background: linear-gradient(135deg, rgba(207, 71, 51, 0.16), rgba(15, 22, 36, 0.08)), #f8f1ea; - box-shadow: var(--azionelab-shadow); - aspect-ratio: 4 / 5; + box-shadow: var(--azionelab-shadow-strong); + aspect-ratio: 4 / 4.8; } .hero-image { @@ -185,30 +188,39 @@ import { ShowDetail, ShowPerformance, ShowsApiService } from '../services/shows- .section-heading h2 { margin: 0 0 6px; - font-size: 1.4rem; - } - - .section-heading p { - margin: 0; - color: var(--azionelab-muted); } .performance-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: 20px; + gap: 22px; } .performance-card, .status-card { - border-radius: 8px; + border-radius: var(--azionelab-radius-md); border: 1px solid var(--azionelab-border); - background: var(--azionelab-surface); + background: linear-gradient(180deg, rgba(255, 253, 249, 0.98), rgba(250, 243, 233, 0.94)); box-shadow: var(--azionelab-shadow); } .performance-card { - min-height: 260px; + min-height: 280px; + } + + .performance-card mat-card-title, + .performance-card mat-card-subtitle, + .performance-card mat-card-content, + .performance-card mat-card-actions { + padding-left: 18px; + padding-right: 18px; + } + + .performance-card mat-card-title { + margin-top: 14px; + font-family: var(--azionelab-serif); + font-size: 1.28rem; + line-height: 1.15; } .performance-meta { diff --git a/frontend/src/app/pages/show-list-page.component.ts b/frontend/src/app/pages/show-list-page.component.ts index c0fe47e..1825463 100644 --- a/frontend/src/app/pages/show-list-page.component.ts +++ b/frontend/src/app/pages/show-list-page.component.ts @@ -19,7 +19,7 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service';

Shows

- Browse current productions published from the AzioneLab backend. + Browse current productions, open a show page, and move toward booking without friction.

@@ -64,6 +64,9 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; } +
+ Published show +
{{ show.title }}

{{ show.summary }}

@@ -78,42 +81,23 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; `, styles: [` - .page { - max-width: 1180px; - margin: 0 auto; - } - .page-header { display: grid; - grid-template-columns: minmax(0, 1fr) minmax(260px, 380px); + grid-template-columns: minmax(0, 1fr) minmax(260px, 410px); gap: 24px; align-items: end; - margin-bottom: 24px; - } - - .eyebrow { - margin: 0 0 10px; - color: var(--azionelab-accent); - text-transform: uppercase; - font-size: 0.78rem; - font-weight: 700; - } - - h1 { - margin: 0; - font-size: clamp(2rem, 4vw, 3rem); + margin-bottom: 28px; } .supporting { margin: 0; - color: var(--azionelab-muted); - line-height: 1.6; + max-width: 34ch; } .show-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); - gap: 20px; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 22px; } .status-panel, @@ -131,9 +115,9 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; .status-card { max-width: 680px; - border-radius: 8px; + border-radius: var(--azionelab-radius-md); border: 1px solid var(--azionelab-border); - background: var(--azionelab-surface); + background: var(--azionelab-surface-strong); box-shadow: var(--azionelab-shadow); } @@ -155,15 +139,16 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; .show-card { display: flex; flex-direction: column; - min-height: 220px; - border-radius: 8px; + min-height: 360px; + overflow: hidden; + border-radius: var(--azionelab-radius-md); border: 1px solid var(--azionelab-border); - background: var(--azionelab-surface); + background: linear-gradient(180deg, rgba(255, 253, 249, 0.98), rgba(250, 243, 233, 0.94)); box-shadow: var(--azionelab-shadow); } .show-image-wrap { - aspect-ratio: 16 / 10; + aspect-ratio: 15 / 10; overflow: hidden; border-bottom: 1px solid var(--azionelab-border); background: @@ -176,15 +161,52 @@ import { ShowListItem, ShowsApiService } from '../services/shows-api.service'; height: 100%; display: block; object-fit: cover; + transition: transform 180ms ease; + } + + .show-card:hover .show-image { + transform: scale(1.03); + } + + .card-topline { + padding: 18px 18px 0; + } + + .card-label { + display: inline-flex; + align-items: center; + min-height: 28px; + padding: 0 12px; + border-radius: 999px; + background: rgba(143, 51, 45, 0.08); + color: var(--azionelab-accent-strong); + font-size: 0.78rem; + font-weight: 700; } .show-card mat-card-content { flex: 1; } + .show-card mat-card-title, + .show-card mat-card-content, + .show-card mat-card-actions { + padding-left: 18px; + padding-right: 18px; + } + + .show-card mat-card-title { + margin-top: 10px; + font-family: var(--azionelab-serif); + font-size: 1.45rem; + font-weight: 700; + line-height: 1.12; + } + .show-card p { color: var(--azionelab-muted); line-height: 1.6; + margin: 0; } @media (max-width: 860px) { diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 6e568db..3a10e0a 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -1,13 +1,28 @@ :root { - --azionelab-bg: #f3eee6; - --azionelab-surface: rgba(255, 255, 255, 0.78); - --azionelab-surface-strong: rgba(255, 255, 255, 0.92); - --azionelab-ink: #1e1b18; - --azionelab-muted: #645b53; - --azionelab-accent: #9f2f28; - --azionelab-accent-strong: #7f211c; - --azionelab-border: rgba(30, 27, 24, 0.12); - --azionelab-shadow: 0 18px 48px rgba(46, 28, 18, 0.12); + --azionelab-bg: #f5efe6; + --azionelab-bg-strong: #efe4d4; + --azionelab-surface: rgba(255, 251, 246, 0.84); + --azionelab-surface-strong: rgba(255, 252, 248, 0.96); + --azionelab-surface-dark: #342924; + --azionelab-ink: #221c18; + --azionelab-ink-soft: #3a302a; + --azionelab-muted: #6f6258; + --azionelab-accent: #8f332d; + --azionelab-accent-strong: #6e251f; + --azionelab-accent-soft: #c88f64; + --azionelab-highlight: #c6a768; + --azionelab-border: rgba(34, 28, 24, 0.11); + --azionelab-border-strong: rgba(34, 28, 24, 0.18); + --azionelab-shadow: 0 18px 48px rgba(46, 28, 18, 0.10); + --azionelab-shadow-strong: 0 26px 64px rgba(46, 28, 18, 0.16); + --azionelab-radius-sm: 10px; + --azionelab-radius-md: 16px; + --azionelab-radius-lg: 24px; + --azionelab-shell-width: 1180px; + --azionelab-copy-width: 64ch; + --azionelab-section-gap: 28px; + --azionelab-sans: "Segoe UI", "Helvetica Neue", Arial, sans-serif; + --azionelab-serif: Georgia, "Times New Roman", serif; --azionelab-success-bg: #edf7ef; --azionelab-success-ink: #1f5f2b; --azionelab-success-border: rgba(46, 125, 50, 0.18); @@ -23,12 +38,11 @@ html, body { margin: 0; min-height: 100%; - font-family: "Manrope", "Segoe UI", sans-serif; + font-family: var(--azionelab-sans); color: var(--azionelab-ink); background: - radial-gradient(circle at top right, rgba(159, 47, 40, 0.12), transparent 28%), - radial-gradient(circle at left center, rgba(140, 116, 86, 0.14), transparent 35%), - linear-gradient(180deg, #fbf7f2 0%, var(--azionelab-bg) 100%); + linear-gradient(180deg, rgba(143, 51, 45, 0.06), transparent 140px), + linear-gradient(180deg, #faf5ee 0%, var(--azionelab-bg) 52%, #efe4d6 100%); } body { @@ -36,18 +50,79 @@ body { } h1, h2, h3 { - font-family: "Fraunces", "Times New Roman", serif; - letter-spacing: -0.02em; + font-family: var(--azionelab-serif); + font-weight: 700; + letter-spacing: 0; + color: var(--azionelab-ink); +} + +h1 { + font-size: 2.5rem; + line-height: 1.02; +} + +h2 { + font-size: 1.65rem; + line-height: 1.12; +} + +h3 { + font-size: 1.15rem; + line-height: 1.2; } button, input, textarea { font: inherit; } -.material-symbols-outlined { - font-variation-settings: - 'FILL' 0, - 'wght' 500, - 'GRAD' 0, - 'opsz' 24; +a { + color: var(--azionelab-accent-strong); +} + +img { + max-width: 100%; +} + +code { + font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; +} + +.page { + width: min(100%, var(--azionelab-shell-width)); + margin: 0 auto; +} + +.eyebrow { + margin: 0 0 12px; + color: var(--azionelab-accent); + text-transform: uppercase; + font-size: 0.78rem; + font-weight: 700; + letter-spacing: 0.08em; +} + +.supporting { + color: var(--azionelab-muted); + line-height: 1.65; + max-width: var(--azionelab-copy-width); +} + +@media (max-width: 900px) { + h1 { + font-size: 2.15rem; + } + + h2 { + font-size: 1.45rem; + } +} + +@media (max-width: 640px) { + h1 { + font-size: 1.9rem; + } + + h2 { + font-size: 1.3rem; + } }