From f35a04f3bc4ce3a4b45eb7858cef6b1814a71eaf Mon Sep 17 00:00:00 2001 From: Abhijeet Date: Thu, 22 Oct 2026 02:41:57 +0530 Subject: [PATCH 1/3] Refine registration preview, approval pass, and PDF download --- .gitignore | 6 +- components.json | 18 + components/ui/dialog.tsx | 1 + components/ui/event-ticket.tsx | 1042 +++++++++++++ docs/pass-experience.md | 38 + package-lock.json | 1285 ++++++++++++++++- package.json | 14 +- playwright.pass.config.ts | 11 + postcss.config.mjs | 7 + public/assets/payment-qr-code.webp | Bin 0 -> 38506 bytes public/assets/payment-qr.webp | Bin 0 -> 208192 bytes src/app/admin/scan/page.tsx | 30 +- src/app/api/pass/experience/route.ts | 23 + src/app/api/pass/route.ts | 14 +- src/app/api/register/route.ts | 3 +- src/app/api/tickets/route.ts | 3 + src/app/api/tickets/verify/route.ts | 3 + src/app/globals.css | 50 +- src/app/page.tsx | 3 +- src/app/ticket/page.tsx | 5 + .../innovision/ApprovedPassTicket.module.css | 11 + .../innovision/ApprovedPassTicket.tsx | 116 ++ .../innovision/AuthOverlay.module.css | 68 + src/components/innovision/AuthOverlay.tsx | 197 ++- src/components/innovision/EntryPassCard.tsx | 299 ++-- src/components/innovision/Innovision.tsx | 303 +++- .../innovision/PassIssued.module.css | 651 +++++++++ src/components/innovision/PassIssued.tsx | 210 +++ .../innovision/PassKeepsake.module.css | 69 + src/components/innovision/PassKeepsake.tsx | 37 + src/components/innovision/PassTicket.tsx | 73 + src/components/innovision/ProfileOverlay.tsx | 15 +- .../innovision/RegistrationStatusSync.tsx | 29 + src/components/innovision/download-pass.ts | 88 ++ src/components/innovision/pass-client.ts | 10 + src/components/innovision/useDialogFocus.ts | 29 + src/components/ui/dialog.tsx | 122 ++ src/components/ui/event-ticket.tsx | 2 + src/config/launch.ts | 7 +- src/config/payment.ts | 9 +- src/config/site.ts | 8 + src/lib/pass-experience.ts | 32 + src/lib/security.ts | 3 + src/lib/supabase.ts | 25 +- src/lib/utils.ts | 6 + src/proxy.ts | 2 +- supabase/manual/pass_experience.sql | 48 + supabase/schema.sql | 51 + tailwind.config.ts | 55 + tests/browser/harness.tsx | 16 + tests/browser/loader.cjs | 9 + tests/browser/pass.spec.ts | 118 ++ tests/browser/serve-pass.cjs | 45 + tests/browser/session.ts | 2 + tests/browser/teardown.ts | 4 + tests/unit/pass-experience.test.mjs | 67 + tests/unit/pass-transport.test.mjs | 21 + tests/unit/registration-details.test.mjs | 28 + tsconfig.json | 4 + 59 files changed, 5099 insertions(+), 346 deletions(-) create mode 100644 components.json create mode 100644 components/ui/dialog.tsx create mode 100644 components/ui/event-ticket.tsx create mode 100644 docs/pass-experience.md create mode 100644 playwright.pass.config.ts create mode 100644 postcss.config.mjs create mode 100644 public/assets/payment-qr-code.webp create mode 100644 public/assets/payment-qr.webp create mode 100644 src/app/api/pass/experience/route.ts create mode 100644 src/app/api/tickets/route.ts create mode 100644 src/app/api/tickets/verify/route.ts create mode 100644 src/app/ticket/page.tsx create mode 100644 src/components/innovision/ApprovedPassTicket.module.css create mode 100644 src/components/innovision/ApprovedPassTicket.tsx create mode 100644 src/components/innovision/AuthOverlay.module.css create mode 100644 src/components/innovision/PassIssued.module.css create mode 100644 src/components/innovision/PassIssued.tsx create mode 100644 src/components/innovision/PassKeepsake.module.css create mode 100644 src/components/innovision/PassKeepsake.tsx create mode 100644 src/components/innovision/PassTicket.tsx create mode 100644 src/components/innovision/RegistrationStatusSync.tsx create mode 100644 src/components/innovision/download-pass.ts create mode 100644 src/components/innovision/pass-client.ts create mode 100644 src/components/innovision/useDialogFocus.ts create mode 100644 src/components/ui/dialog.tsx create mode 100644 src/components/ui/event-ticket.tsx create mode 100644 src/lib/pass-experience.ts create mode 100644 src/lib/utils.ts create mode 100644 supabase/manual/pass_experience.sql create mode 100644 tailwind.config.ts create mode 100644 tests/browser/harness.tsx create mode 100644 tests/browser/loader.cjs create mode 100644 tests/browser/pass.spec.ts create mode 100644 tests/browser/serve-pass.cjs create mode 100644 tests/browser/session.ts create mode 100644 tests/browser/teardown.ts create mode 100644 tests/unit/pass-experience.test.mjs create mode 100644 tests/unit/pass-transport.test.mjs create mode 100644 tests/unit/registration-details.test.mjs diff --git a/.gitignore b/.gitignore index fd39b90..eb21281 100644 --- a/.gitignore +++ b/.gitignore @@ -49,8 +49,10 @@ next-env.d.ts /test-results/ /playwright-report/ -# tests (kept locally only; run with `npm test` / `npx playwright test`) -/tests/ +# Regression tests are versioned; generated results remain ignored above. # local tooling (check:assets, payment-proof migration; used by the local-only tests) /scripts/ + +# Isolated pass component test bundle +.pass-test/ diff --git a/components.json b/components.json new file mode 100644 index 0000000..99955cd --- /dev/null +++ b/components.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui" + } +} diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx new file mode 100644 index 0000000..b245a05 --- /dev/null +++ b/components/ui/dialog.tsx @@ -0,0 +1 @@ +export * from "@/components/ui/dialog"; diff --git a/components/ui/event-ticket.tsx b/components/ui/event-ticket.tsx new file mode 100644 index 0000000..5643ebb --- /dev/null +++ b/components/ui/event-ticket.tsx @@ -0,0 +1,1042 @@ +"use client" + +import * as React from "react" + +/** + * Event ticket — a two-sided pass. + * Front: black VIP pass with a halftone Moon that follows the pointer's light, + * plus a clarinet and a rocket that react on hover. + * Back: silver boarding pass with a perforated, tearable stub and a QR slot. + * Click either face (or the switch below) to turn it over. + */ + +// #region pass — pure helpers + +export const clamp01 = (v: number): number => (v > 0 ? (v < 1 ? v : 1) : 0) + +export const smoothstep = (a: number, b: number, x: number): number => { + if (a === b) return x < a ? 0 : 1 + const t = clamp01((x - a) / (b - a)) + return t * t * (3 - 2 * t) +} + +const finite = (v: number): number => (Number.isFinite(v) ? v : 0) + +export const toDMS = (deg: number, pos: string, neg: string): string => { + const d = finite(deg) + let s = Math.round(Math.abs(d) * 3600) + const D = Math.floor(s / 3600) + s -= D * 3600 + const M = Math.floor(s / 60) + s -= M * 60 + const pad = (n: number): string => (n < 10 ? "0" : "") + n + return D + "°" + pad(M) + "'" + pad(s) + '"' + (d < 0 ? neg : pos) +} + +export const coordsDMS = (lat: number, lon: number): string => toDMS(lat, "N", "S") + " " + toDMS(lon, "E", "W") + +export const coordsDecimal = (lat: number, lon: number): string => + finite(lat).toFixed(5) + "°, " + finite(lon).toFixed(5) + "°" + +export const project = (lat: number, lon: number): number[] => { + const a = (finite(lat) * Math.PI) / 180 + const b = (finite(lon) * Math.PI) / 180 + return [Math.cos(a) * Math.sin(b), -Math.sin(a), Math.cos(a) * Math.cos(b)] +} + +export const angDist = (lat1: number, lon1: number, lat2: number, lon2: number): number => { + const p = project(lat1, lon1) + const q = project(lat2, lon2) + const d = p[0] * q[0] + p[1] * q[1] + p[2] * q[2] + return (Math.acos(d > 1 ? 1 : d < -1 ? -1 : d) * 180) / Math.PI +} + +export const hash2 = (i: number, j: number): number => { + let h = (Math.imul(i | 0, 374761393) + Math.imul(j | 0, 668265263)) | 0 + h = Math.imul(h ^ (h >>> 13), 1274126177) + h ^= h >>> 16 + return (h >>> 0) / 4294967296 +} + +export const valueNoise = (x: number, y: number): number => { + const i = Math.floor(x) + const j = Math.floor(y) + const fx = x - i + const fy = y - j + const u = fx * fx * (3 - 2 * fx) + const v = fy * fy * (3 - 2 * fy) + const a = hash2(i, j) + const b = hash2(i + 1, j) + const c = hash2(i, j + 1) + const d = hash2(i + 1, j + 1) + return a + (b - a) * u + (c - a) * v + (a - b - c + d) * u * v +} + +/** Dark seas: lat, lon, radius (deg), depth. */ +export const MARIA: number[][] = [ + [18, -57, 26, 0.7], + [33, -16, 17, 0.85], + [28, 17.5, 9.5, 0.85], + [8.5, 31, 11, 0.85], + [17, 59, 7, 0.9], + [-8, 51, 9, 0.7], + [-15, 35, 5, 0.7], + [-21, -17, 10, 0.65], + [-24, -39, 5, 0.75], + [-10, -23, 6, 0.6], + [13, 4, 4, 0.6], + [57, 0, 8, 0.6], + [56, -30, 7, 0.55], + [56, 28, 6, 0.5], +] + +/** Bright young craters: lat, lon, radius, brightness. */ +export const BRIGHT: number[][] = [ + [-43.3, -11.2, 5, 0.45], + [9.6, -20.1, 3.5, 0.35], + [8.1, -38, 2.5, 0.3], + [23.7, -47.4, 2.5, 0.4], +] + +export const albedo = (lat: number, lon: number): number => { + let keep = 1 + for (const m of MARIA) { + const t = angDist(lat, lon, m[0], m[1]) / m[2] + if (t < 1) { + const w = 1 - t * t + keep *= 1 - m[3] * w * w + } + } + let a = 0.22 + 0.66 * keep + for (const b of BRIGHT) { + const t = angDist(lat, lon, b[0], b[1]) / b[2] + if (t < 1) a += b[3] * (1 - t) * (1 - t) + } + a += (valueNoise(lat * 0.21 + 40, lon * 0.21 + 40) - 0.5) * 0.18 + a += (valueNoise(lat * 0.9, lon * 0.9) - 0.5) * 0.08 + return clamp01(a) +} + +export const turnFor = (lon: number): number => Math.max(0, Math.min(60, 12 - finite(lon))) + +export const moonDots = (cx: number, cy: number, r: number, cell: number, turn: number): number[] => { + const out: number[] = [] + if (!(r > 0) || !(cell > 0)) return out + const row = cell * 0.866 + let k = 0 + for (let y = cy - r; y <= cy + r; y += row, k++) { + for (let x = cx - r + (k % 2 ? cell / 2 : 0); x <= cx + r; x += cell) { + const nx = (x - cx) / r + const ny = (y - cy) / r + const q = nx * nx + ny * ny + if (q >= 1) continue + const nz = Math.sqrt(1 - q) + const lat = (Math.asin(-ny) * 180) / Math.PI + const lon = (Math.atan2(nx, nz) * 180) / Math.PI - finite(turn) + out.push(x, y, nx, ny, nz, albedo(lat, lon)) + } + } + return out +} + +export const lightFrom = (px: number, py: number): number[] => { + const phi = ((clamp01(finite(px)) - 0.5) * 2 * 150 * Math.PI) / 180 + const v = [Math.sin(phi), (clamp01(finite(py)) - 0.5) * 0.9, Math.cos(phi)] + const n = Math.hypot(v[0], v[1], v[2]) + return [v[0] / n, v[1] / n, v[2] / n] +} + +export const idleAt = (seconds: number): number => 0.56 + Math.sin((finite(seconds) * Math.PI * 2) / 26) * 0.07 + +export const dotRadius = (alb: number, nx: number, ny: number, nz: number, l: number[], cell: number): number => { + const lit = smoothstep(-0.08, 0.32, nx * l[0] + ny * l[1] + nz * l[2]) + const b = clamp01(alb) * (0.07 + 0.93 * lit) * (0.7 + 0.3 * nz) + return cell * 0.46 * Math.pow(b, 0.8) +} + +export const tiltFrom = (px: number, py: number, max: number): number[] => [ + -(clamp01(finite(py)) - 0.5) * 2 * max, + (clamp01(finite(px)) - 0.5) * 2 * max, +] + +export const tearDecision = (dx: number, v: number, w: number): boolean => + dx > w * 0.2 || (v > 0.5 && dx > w * 0.05) + +export const resist = (dx: number, w: number): number => { + const d = Math.max(0, finite(dx)) + const lim = Math.max(1, w) * 0.12 + return d < lim ? d : lim + (d - lim) * 0.22 +} + +export const mulberry = (seed: number): (() => number) => { + let a = seed >>> 0 + return () => { + a = (a + 0x6d2b79f5) | 0 + let t = Math.imul(a ^ (a >>> 15), 1 | a) + t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t + return ((t ^ (t >>> 14)) >>> 0) / 4294967296 + } +} + +export const starField = (seed: number, n: number, x0: number, x1: number, y0: number, y1: number): number[][] => { + const rnd = mulberry(seed) + const out: number[][] = [] + for (let i = 0; i < n; i++) { + const big = rnd() < 0.12 + out.push([ + x0 + rnd() * (x1 - x0), + y0 + rnd() * (y1 - y0), + big ? 0.9 + rnd() * 0.8 : 0.3 + rnd() * 0.5, + big || rnd() < 0.1 ? 1 : 0, + Math.round(rnd() * 40) / 10, + ]) + } + return out +} +// #endregion + +export type Side = "front" | "back" + +export type EventTicketProps = { + /** Headline on both faces. */ + title?: string + /** Class of pass: the front's corner and the back's header. */ + tier?: string + /** The front's date. */ + date?: string + /** Bottom-left text on the front. "\n" breaks a line. */ + welcome?: string + /** Fine print beside the stub. "\n" breaks a line. */ + eyebrow?: string + /** The two words floating in the art. */ + words?: [string, string] + /** Two lines of fine print along the front's foot. */ + notes?: [string, string] + passenger?: string + from?: string + to?: string + craft?: string + dateCode?: string + gate?: string + group?: string + seat?: string + boardingTime?: string + /** Landing-site name, printed on both faces and marked on the Moon. */ + site?: string + /** Landing-site selenographic degrees. */ + lat?: number + lon?: number + /** Hide the reference artwork's lunar coordinates for terrestrial events. */ + showCoordinates?: boolean + /** Use actual participant/registration fields instead of the reference's flight fields. */ + registrationPass?: boolean + seq?: string + featuring?: string + /** The big thin line on the back. */ + headline?: string + /** What the stamp says when the stub comes off. */ + stamp?: string + /** Labels for the switch under the ticket. */ + sideLabels?: [string, string] + /** QR slot on the back. Any node: , . Stays on the main piece after the stub is torn. */ + qr?: React.ReactNode + /** Caption under the QR slot. */ + qrLabel?: string + night?: string + starInk?: string + paper?: string + paperInk?: string + stampColor?: string + fontCondensed?: string + fontMono?: string + fontDisplay?: string + defaultSide?: Side + onSideChange?: (side: Side) => void + defaultTorn?: boolean + onTear?: (torn: boolean) => void + /** Largest tilt in degrees. 0 holds it flat. */ + tilt?: number + /** The height follows the 1000 : 330 ticket. */ + maxWidth?: number | string + className?: string +} + +const VIEW_W = 1000 +const VIEW_H = 330 +const MOON = { x: 53 / 226, y: 201 / 330, r: 128 / 226 } + +const CONDENSED = + '"Oswald", "Bebas Neue", "Avenir Next Condensed", "Helvetica Neue", "Arial Narrow", "Roboto Condensed", "Liberation Sans Narrow", "DejaVu Sans Condensed", sans-serif' +const MONO = '"Courier Prime", "IBM Plex Mono", "Courier New", ui-monospace, monospace' +const DISPLAY = '"Futura", "Century Gothic", "Avenir Next", "Josefin Sans", "Quicksand", ui-sans-serif, sans-serif' + +const pts = (a: number[][]): string => a.map((p) => p[0] + "," + p[1]).join(" ") + +const STARS = starField(1969, 120, 240, 990, 10, 320) + +const CSS = [ + ".lbp{position:relative;width:100%;margin:0 auto}", + ".lbp-stage{position:relative;width:100%;perspective:1800px;touch-action:pan-y}", + ".lbp-tilt,.lbp-flip{position:absolute;inset:0;transform-style:preserve-3d}", + ".lbp-tilt{transform:rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));transition:transform .6s cubic-bezier(.2,.8,.2,1)}", + ".lbp-flip{cursor:pointer;transition:transform 1.05s cubic-bezier(.65,-0.2,.25,1.2)}", + ".lbp-face{position:absolute;inset:0;backface-visibility:hidden;-webkit-backface-visibility:hidden;", + "filter:drop-shadow(0 1.4cqw 1.8cqw rgba(0,0,0,.2)) drop-shadow(0 .25cqw .35cqw rgba(0,0,0,.14))}", + ".lbp-back{transform:rotateY(180deg)}", + ".lbp-night{position:absolute;inset:0;overflow:hidden;border-radius:.35cqw;background:var(--lbp-night);color:var(--lbp-star);", + "box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--lbp-star) 9%,transparent)}", + ".lbp-layer{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}", + ".lbp-grain{opacity:.16;mix-blend-mode:screen}", + ".lbp-piece .lbp-grain{opacity:.3;mix-blend-mode:multiply}", + ".lbp-glow{background:radial-gradient(circle at var(--mx,50%) var(--my,40%),color-mix(in srgb,var(--lbp-star) 12%,transparent),transparent 42%)}", + ".lbp-piece{position:absolute;top:0;bottom:0;overflow:hidden;color:var(--lbp-ink);", + "background:radial-gradient(ellipse at 16% 12%,rgba(255,255,255,.52),transparent 46%),repeating-linear-gradient(0deg,rgba(50,42,28,.018) 0,rgba(50,42,28,.018) 1px,transparent 1px,transparent 4px),linear-gradient(162deg,color-mix(in srgb,var(--lbp-paper) 82%,#fff) 0%,var(--lbp-paper) 48%,color-mix(in srgb,var(--lbp-paper) 88%,#000) 100%)}", + ".lbp-main{left:0;width:77.4%;border-radius:.35cqw 0 0 .35cqw;padding:2.3cqw 2.6cqw 2.1cqw;display:flex;flex-direction:column;", + "-webkit-mask:radial-gradient(circle at 100% 50%,#0000 .2cqw,#000 .24cqw) 0 0/100% .86cqw repeat-y;", + "mask:radial-gradient(circle at 100% 50%,#0000 .2cqw,#000 .24cqw) 0 0/100% .86cqw repeat-y}", + ".lbp-stub{left:77.4%;width:22.6%;border-radius:0 .35cqw .35cqw 0;padding:2.3cqw 1.9cqw 2.1cqw;display:flex;flex-direction:column;", + "font:inherit;text-align:left;border:0;margin:0;cursor:grab;touch-action:pan-y;transform-origin:0 100%;", + "transition:transform .75s cubic-bezier(.2,.9,.25,1.25);", + "-webkit-mask:radial-gradient(circle at 0 50%,#0000 .2cqw,#000 .24cqw) 0 0/100% .86cqw repeat-y;", + "mask:radial-gradient(circle at 0 50%,#0000 .2cqw,#000 .24cqw) 0 0/100% .86cqw repeat-y}", + ".lbp-stub:active{cursor:grabbing}", + ".lbp-stub:focus-visible{outline:2px solid var(--lbp-stamp);outline-offset:-4px}", + ".lbp-stub.is-torn{transform:translate(2.4cqw,1.1cqw) rotate(4deg);cursor:pointer}", + ".lbp-foil{background:linear-gradient(115deg,transparent calc(var(--mx,50%) - 24%),rgba(255,255,255,.62) var(--mx,50%),transparent calc(var(--mx,50%) + 24%)) no-repeat;mix-blend-mode:soft-light}", + ".lbp-main .lbp-foil{background-size:129.2% 100%;background-position:0 0}", + ".lbp-stub .lbp-foil{background-size:442.5% 100%;background-position:100% 0}", + ".lbp-c{font-family:var(--lbp-cond,var(--font-sans,sans-serif));font-weight:700;line-height:1;letter-spacing:.02em}", + ".lbp-m{font-family:var(--lbp-mono,monospace);text-transform:uppercase;line-height:1.05;letter-spacing:.03em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}", + ".lbp-d{font-family:var(--lbp-disp,var(--font-display,serif));font-weight:400;text-transform:uppercase;letter-spacing:.12em;line-height:1;white-space:nowrap}", + ".lbp-title{font-family:var(--lbp-disp,var(--font-display,serif));font-weight:500;letter-spacing:.02em;line-height:1.06;white-space:normal;overflow-wrap:anywhere}", + ".lbp-l{display:block;font-family:var(--lbp-cond,var(--font-sans,sans-serif));font-weight:700;text-transform:uppercase;font-size:.6cqw;letter-spacing:.08em;line-height:1;opacity:.82;margin-bottom:.45cqw;white-space:nowrap}", + ".lbp-at{position:absolute;white-space:nowrap}", + ".lbp-pre{white-space:pre-line}", + ".lbp-head{display:flex;align-items:baseline;justify-content:space-between;gap:1.5cqw;padding-bottom:1cqw;border-bottom:1px solid var(--lbp-rule)}", + ".lbp-grid{display:grid;grid-template-columns:1.08fr 1fr .78fr;border-bottom:1px solid var(--lbp-rule)}", + ".lbp-cell{padding:1cqw 1.2cqw 1cqw 0;min-width:0}", + ".lbp-cell+.lbp-cell,.lbp-grid>:nth-child(5),.lbp-grid>:nth-child(6){border-left:1px solid var(--lbp-rule);padding-left:1.2cqw}", + ".lbp-grid>:nth-child(4){border-left:0;padding-left:0}", + ".lbp-grid>:nth-child(5),.lbp-grid>:nth-child(6){border-top:1px solid var(--lbp-rule)}", + ".lbp-row{display:flex;gap:2.4cqw}", + ".lbp-foot{flex:1;display:flex;align-items:center;gap:2cqw;padding-top:1.1cqw}", + ".lbp-qr{position:relative;z-index:2;flex:0 0 auto;display:flex;flex-direction:column;align-items:center;cursor:default}", + ".lbp-qrbox{box-sizing:border-box;width:10.5cqw;height:10.5cqw;padding:.55cqw;background:#fff;color:#000;border:1px solid var(--lbp-rule);border-radius:.3cqw;display:flex;align-items:center;justify-content:center}", + ".lbp-qrbox>svg,.lbp-qrbox>img,.lbp-qrbox>canvas{display:block;width:100%;height:100%;max-width:none}", + ".lbp-qrbox.is-empty{background:transparent;border:1px dashed var(--lbp-rule);font-family:var(--lbp-cond);font-size:1.4cqw;letter-spacing:.2em;opacity:.7}", + ".lbp-sf{margin-top:1.45cqw;min-width:0}", + ".lbp-details{display:grid;grid-template-columns:1.5fr 1fr;gap:1.3cqw 2cqw;padding:1.6cqw 0;border-bottom:1px solid var(--lbp-rule)}", + ".lbp-details>div{min-width:0}.lbp-details>div:first-child{grid-column:1/-1}", + ".lbp-details .lbp-m{white-space:normal;overflow:visible;overflow-wrap:anywhere;font-size:1.4cqw;line-height:1.35}", + ".lbp-person{margin:0;font-family:var(--lbp-disp);font-weight:400;font-size:3cqw;line-height:1.1;overflow-wrap:anywhere}", + ".lbp-registration .lbp-details>div:nth-child(2) .lbp-m{font-family:var(--lbp-cond);text-transform:none;letter-spacing:0;font-weight:500}", + ".lbp-registration .lbp-main::after{content:'';position:absolute;right:13%;bottom:-8cqw;width:18cqw;height:18cqw;border:1px solid #89672b18;border-radius:50%;box-shadow:0 0 0 1.2cqw #89672b06;pointer-events:none}", + ".lbp-registration-grid .lbp-traveler{grid-column:span 2}.lbp-registration-grid .lbp-person{font-size:2.5cqw}", + ".lbp-registration-grid .lbp-m{line-height:1.3}.lbp-registration-grid .lbp-origin{font-family:var(--lbp-cond);font-size:1.3cqw;text-transform:none;letter-spacing:0}", + ".lbp-registration-grid>:nth-child(4){border-left:1px solid var(--lbp-rule);padding-left:1.2cqw}", + ".lbp-registration-grid>:nth-child(3){border-left:0;padding-left:0}", + ".lbp-registration-grid>:nth-child(n+3){border-top:1px solid var(--lbp-rule)}", + ".lbp-registration .lbp-m{white-space:normal;overflow:visible;overflow-wrap:anywhere}.lbp-registration .lbp-tw{animation:none}", + ".lbp-stamp{position:absolute;left:33%;top:52%;padding:.35cqw;border:.2cqw solid var(--lbp-stamp);border-radius:.45cqw;color:var(--lbp-stamp);", + "opacity:0;transform:rotate(-9deg);pointer-events:none;mix-blend-mode:multiply}", + ".lbp-stamp>span{display:block;padding:.45cqw 1.1cqw;border:.08cqw solid var(--lbp-stamp);border-radius:.25cqw;text-align:center}", + ".lbp-main.is-torn .lbp-stamp{opacity:.86;animation:lbp-stamp .5s cubic-bezier(.3,1.6,.5,1) both}", + "@keyframes lbp-stamp{0%{opacity:0;transform:rotate(-4deg) scale(1.9)}100%{opacity:.86;transform:rotate(-9deg) scale(1)}}", + ".lbp-hint{position:absolute;left:77.4%;bottom:1.6cqw;transform:translateX(-50%) rotate(180deg);writing-mode:vertical-rl;font-family:var(--lbp-cond);", + "font-size:.5cqw;letter-spacing:.3em;text-transform:uppercase;color:var(--lbp-ink);opacity:.45;pointer-events:none;white-space:nowrap;transition:opacity .3s}", + ".lbp-back.is-torn .lbp-hint{opacity:0}", + ".lbp-printed .lbp-v{animation:lbp-type .8s steps(14,end) both}", + "@keyframes lbp-type{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}", + ".lbp-registration .lbp-printed .lbp-v,.lbp-registration .lbp-person,.lbp-registration .lbp-details .lbp-m{animation:lbp-ink-write 1.7s steps(24,end) both;animation-delay:.55s!important}", + ".lbp-registration .lbp-person{animation-delay:.35s!important}", + "@keyframes lbp-ink-write{0%{clip-path:inset(0 100% 0 0);transform:translateX(0);text-shadow:none}25%{clip-path:inset(0 76% 0 0);transform:translateX(-1px);text-shadow:1px 0 #b6955866}29%{transform:translateX(1px)}50%{clip-path:inset(0 48% 0 0);transform:translateX(0);text-shadow:none}70%{clip-path:inset(0 24% 0 0);transform:translateX(-.5px);text-shadow:.5px 0 #b6955866}92%,100%{clip-path:inset(0);transform:none;text-shadow:none}}", + ".lbp-tw{animation:lbp-tw 3.4s ease-in-out infinite}", + "@keyframes lbp-tw{0%,100%{opacity:1}50%{opacity:.2}}", + ".lbp-ship{transition:transform .9s cubic-bezier(.2,.8,.2,1)}", + ".lbp-rocket:hover .lbp-ship{transform:translateX(14px)}", + ".lbp-flame{opacity:0;transform-box:fill-box;transform-origin:100% 50%;transform:scaleX(.2);transition:opacity .25s,transform .35s}", + ".lbp-rocket:hover .lbp-flame{opacity:1;transform:scaleX(1);animation:lbp-flick .09s steps(2) infinite alternate}", + "@keyframes lbp-flick{to{transform:scaleX(1.18) scaleY(1.06)}}", + ".lbp-note{opacity:0}", + ".lbp-clarinet:hover .lbp-note{animation:lbp-note 2.2s ease-out infinite}", + "@keyframes lbp-note{0%{opacity:0;transform:translate(0,0) scale(.5)}18%{opacity:1}100%{opacity:0;transform:translate(var(--tx),var(--ty)) rotate(-16deg) scale(1.1)}}", + ".lbp-body{transform-box:fill-box;transform-origin:85% 50%;transition:transform .5s}", + ".lbp-clarinet:hover .lbp-body{transform:rotate(-1.2deg)}", + "@media (prefers-reduced-motion: reduce){.lbp-tilt,.lbp-flip,.lbp-stub,.lbp-ship,.lbp-body{transition-duration:.01ms}", + ".lbp-tw,.lbp-flame,.lbp-v,.lbp-stamp,.lbp-note,.lbp-person,.lbp-details .lbp-m{animation:none!important}.lbp-rocket:hover .lbp-flame{transform:none}}", +].join("") + +function Star({ size }: { size: string }) { + const p: number[][] = [] + for (let i = 0; i < 16; i++) { + const a = (i * Math.PI) / 8 - Math.PI / 2 + const r = i % 2 ? 0.34 : 1 + p.push([Math.round((12 + Math.cos(a) * r * 11) * 100) / 100, Math.round((12 + Math.sin(a) * r * 11) * 100) / 100]) + } + return ( + + ) +} + +/** A Saturn V, nose to the right, engraved in white. */ +function Rocket({ ink, night, font }: { ink: string; night: string; font: string }) { + const y = 214 + const R1 = 21 + const R3 = 14 + const R5 = 8.2 + const seam = (x: number, h: number) => + const truss: number[][] = [] + for (let x = 907, k = 0; x <= 934; x += 4.5, k++) truss.push([x, y + (k % 2 ? 2.4 : -2.4)]) + return ( + + + + + + + + {[-12, 12, 0].map((o) => ( + + ))} + + + {/* S-IC, interstage, S-II */} + + + + + + + PSLV + + + {[448, 500, 548, 564, 594, 605, 617, 642, 667, 692].map((x) => seam(x, R1))} + {/* interstage taper, S-IVB, instrument unit */} + + + + + {[734, 768, 784, 821, 825].map((x) => seam(x, x < 746 ? 17.5 : R3))} + {/* adapter, service module, command module */} + + + + + {[861, 876, 892].map((x) => seam(x, R5))} + + {/* launch escape tower */} + + + + + + + + + + ) +} + +/** A B♭ clarinet, bell to the left. Point at it and it plays. */ +function Clarinet({ ink, night }: { ink: string; night: string }) { + const y = 96 + const holes = [392, 418, 446, 474, 502, 530, 610, 640, 668, 696, 724] + const rings = [446, 474, 502, 640, 668, 696] + const pads = [404, 460, 488, 520, 620, 654, 702, 738] + const notes = [ + { x: 300, d: 0, tx: "-34px", ty: "-52px" }, + { x: 310, d: 0.75, tx: "-12px", ty: "-64px" }, + { x: 296, d: 1.5, tx: "-48px", ty: "-30px" }, + ] + return ( + + + {notes.map((n, i) => ( + + + + + {i === 1 && } + + + ))} + + + + + + + + + + + + + + + + {/* turned shading along the underside */} + + {/* keywork */} + + {holes.map((x) => ( + + ))} + {rings.map((x) => ( + + ))} + {pads.map((x) => ( + + ))} + + + + + ) +} + +function Grain({ id }: { id: string }) { + return ( + + ) +} + +function Field({ label, value, size, d }: { label: string; value: string; size: number; d?: number }) { + return ( + + {label} + + {value} + + + ) +} + +export default function EventTicket({ + title = "INNOVISION 2026", + tier = "VIP", + date = "13 Nov '26", + welcome = "Welcome\naboard", + eyebrow = "The 1st station of\nthe space tour", + words = ["Space", "Jazz"], + notes = ["太空爵士・宇宙巡演", "首站—静海基地"], + passenger = "Neil Armstrong", + from = "Earth", + to = "Moon", + craft = "IV26-9042", + dateCode = "13NOV26", + gate = "F3", + group = "C", + seat = "21J", + boardingTime = "UTC2000", + site = "Tranquility Base", + lat = 0.67416, + lon = 23.47314, + showCoordinates = true, + registrationPass = false, + seq = "SEQ 060 MFDBAN 974294U89", + featuring = "Featuring all stars crew", + headline = "Space Jazz", + stamp = "Boarded", + sideLabels = ["VIP pass", "Boarding pass"], + qr, + qrLabel = "Scan at entry", + night = "#0b0b0c", + starInk = "#f1f0eb", + paper = "#c9c9c6", + paperInk = "#1b1b1b", + stampColor = "#a3362a", + fontCondensed = CONDENSED, + fontMono = MONO, + fontDisplay = DISPLAY, + defaultSide = "front", + onSideChange, + defaultTorn = false, + onTear, + tilt = 6, + maxWidth = 960, + className = "", +}: EventTicketProps) { + const uid = React.useId().replace(/[^a-zA-Z0-9]/g, "") + const [turns, setTurns] = React.useState(defaultSide === "back" ? 1 : 0) + const side: Side = turns % 2 ? "back" : "front" + const [printed, setPrinted] = React.useState(defaultSide === "back") + const [torn, setTorn] = React.useState(defaultTorn) + const [reduced, setReduced] = React.useState(false) + + const stageRef = React.useRef(null) + const tiltRef = React.useRef(null) + const moonRef = React.useRef(null) + const stubRef = React.useRef(null) + const pointer = React.useRef(null) + const sideRef = React.useRef(side) + const redraw = React.useRef<() => void>(() => {}) + const drag = React.useRef<{ x: number; t: number; dx: number; v: number; moved: boolean } | null>(null) + const swallowClick = React.useRef(false) + const cbs = React.useRef({ onSideChange, onTear }) + React.useEffect(() => { + sideRef.current = side + cbs.current = { onSideChange, onTear } + }, [side, onSideChange, onTear]) + + React.useEffect(() => { + const mq = window.matchMedia("(prefers-reduced-motion: reduce)") + const onMq = () => setReduced(mq.matches) + onMq() + mq.addEventListener("change", onMq) + return () => mq.removeEventListener("change", onMq) + }, []) + + const firstSide = React.useRef(true) + React.useEffect(() => { + if (firstSide.current) { + firstSide.current = false + return + } + cbs.current.onSideChange?.(side) + }, [side]) + + const firstTear = React.useRef(true) + React.useEffect(() => { + if (firstTear.current) { + firstTear.current = false + return + } + cbs.current.onTear?.(torn) + }, [torn]) + + // The Moon: a halftone redrawn from a cached lattice whenever the light moves. + React.useEffect(() => { + const canvas = moonRef.current + const ctx = canvas && canvas.getContext("2d") + if (!canvas || !ctx) return + let dots: number[] = [] + let cell = 1 + let W = 0 + let H = 0 + let cx = 0 + let cy = 0 + let R = 0 + let dpr = 1 + const turn = turnFor(lon) + const here = project(lat, lon + turn) + let light = lightFrom(idleAt(0), 0.38) + let raf = 0 + let visible = true + + const draw = (pulse: number) => { + if (!W) return + ctx.clearRect(0, 0, W, H) + ctx.fillStyle = starInk + ctx.beginPath() + for (let i = 0; i < dots.length; i += 6) { + const r = dotRadius(dots[i + 5], dots[i + 2], dots[i + 3], dots[i + 4], light, cell) + if (r < 0.3) continue + ctx.moveTo(dots[i] + r, dots[i + 1]) + ctx.arc(dots[i], dots[i + 1], r, 0, Math.PI * 2) + } + ctx.fill() + if (showCoordinates && here[2] > 0.05) { + const mx = cx + R * here[0] + const my = cy + R * here[1] + const s = R * 0.034 + ctx.lineWidth = 3.2 * dpr + ctx.strokeStyle = night + ctx.beginPath() + ctx.arc(mx, my, s, 0, Math.PI * 2) + ctx.stroke() + ctx.lineWidth = 1.2 * dpr + ctx.strokeStyle = starInk + ctx.stroke() + ctx.fillStyle = starInk + ctx.beginPath() + ctx.arc(mx, my, 1.2 * dpr, 0, Math.PI * 2) + ctx.fill() + if (pulse > 0) { + ctx.globalAlpha = 1 - pulse + ctx.beginPath() + ctx.arc(mx, my, s + R * 0.1 * pulse, 0, Math.PI * 2) + ctx.stroke() + ctx.globalAlpha = 1 + } + } + } + + const build = () => { + dpr = Math.min(2, window.devicePixelRatio || 1) + W = Math.round(canvas.clientWidth * dpr) + H = Math.round(canvas.clientHeight * dpr) + if (!W || !H) return + canvas.width = W + canvas.height = H + R = W * MOON.r + cx = W * MOON.x + cy = H * MOON.y + cell = Math.max(2.1 * dpr, R / 36) + dots = moonDots(cx, cy, R, cell, turn) + draw(0) + } + + const target = (t: number) => { + const p = pointer.current + return p ? lightFrom(p[0], p[1]) : lightFrom(idleAt(t), 0.38) + } + + const tick = (now: number) => { + raf = requestAnimationFrame(tick) + if (sideRef.current !== "front") return + const to = target(now / 1000) + for (let k = 0; k < 3; k++) light[k] += (to[k] - light[k]) * 0.09 + const n = Math.hypot(light[0], light[1], light[2]) || 1 + light = [light[0] / n, light[1] / n, light[2] / n] + draw(((now / 1000) % 2.4) / 2.4) + } + const start = () => { + if (!raf && visible && !reduced && !registrationPass) raf = requestAnimationFrame(tick) + } + const stop = () => { + cancelAnimationFrame(raf) + raf = 0 + } + + redraw.current = () => { + if (raf) return + light = target(0) + draw(0) + } + + build() + const observer = new ResizeObserver(build) + observer.observe(canvas) + const io = new IntersectionObserver(([e]) => { + visible = e.isIntersecting + if (visible) start() + else stop() + }) + io.observe(canvas) + start() + return () => { + stop() + observer.disconnect() + io.disconnect() + redraw.current = () => {} + } + }, [lat, lon, night, starInk, reduced, registrationPass, showCoordinates]) + + const flip = () => { + setPrinted(true) + setTurns((t) => t + 1) + } + const show = (s: Side) => { + if (s !== side) flip() + } + + const onMove = (e: React.PointerEvent) => { + const el = stageRef.current + const t = tiltRef.current + if (!el || !t) return + const r = el.getBoundingClientRect() + const px = clamp01((e.clientX - r.left) / r.width) + const py = clamp01((e.clientY - r.top) / r.height) + t.style.setProperty("--mx", (px * 100).toFixed(1) + "%") + t.style.setProperty("--my", (py * 100).toFixed(1) + "%") + if (tilt && !reduced && e.pointerType === "mouse") { + const a = tiltFrom(px, py, tilt) + t.style.setProperty("--rx", a[0].toFixed(2) + "deg") + t.style.setProperty("--ry", a[1].toFixed(2) + "deg") + } + pointer.current = [px, py] + redraw.current() + } + const onLeave = () => { + const t = tiltRef.current + if (t) { + t.style.setProperty("--rx", "0deg") + t.style.setProperty("--ry", "0deg") + } + pointer.current = null + redraw.current() + } + + const stubDown = (e: React.PointerEvent) => { + if (torn || e.button !== 0) return + drag.current = { x: e.clientX, t: performance.now(), dx: 0, v: 0, moved: false } + e.currentTarget.setPointerCapture(e.pointerId) + } + const stubMove = (e: React.PointerEvent) => { + const d = drag.current + const el = stubRef.current + if (!d || !el) return + const now = performance.now() + const dx = Math.max(0, e.clientX - d.x) + d.v = (dx - d.dx) / Math.max(1, now - d.t) + d.t = now + d.dx = dx + if (dx > 4) d.moved = true + const w = el.offsetWidth + const shown = resist(dx, w) + el.style.transition = "none" + el.style.transform = "translateX(" + shown.toFixed(1) + "px) rotate(" + ((shown / Math.max(1, w)) * 7).toFixed(2) + "deg)" + } + const stubUp = () => { + const d = drag.current + const el = stubRef.current + drag.current = null + if (!d || !el) return + el.style.transition = "" + el.style.transform = "" + if (d.moved) { + swallowClick.current = true + if (tearDecision(d.dx, d.v, el.offsetWidth)) setTorn(true) + } + } + const stubClick = (e: React.MouseEvent) => { + e.stopPropagation() + if (swallowClick.current) { + swallowClick.current = false + return + } + setTorn((v) => !v) + } + + const dms = coordsDMS(lat, lon) + const dec = coordsDecimal(lat, lon) + const front = side === "front" + const vars = { + "--lbp-night": night, + "--lbp-star": starInk, + "--lbp-paper": paper, + "--lbp-ink": paperInk, + "--lbp-rule": "color-mix(in srgb, " + paperInk + " 55%, transparent)", + "--lbp-stamp": stampColor, + "--lbp-cond": fontCondensed, + "--lbp-mono": fontMono, + "--lbp-disp": fontDisplay, + } as React.CSSProperties + const at = (x: number, y: number): React.CSSProperties => ({ left: x / 10 + "%", top: (y / VIEW_H) * 100 + "%" }) + + return ( +
+ +
+
+
+ {/* ---------------- front ---------------- */} +
+
+
+
+ + +
+ +
8 ? "1.85cqw" : "2.6cqw", maxWidth: "19cqw", whiteSpace: "normal", lineHeight: 1.1, display: "flex", alignItems: "center", gap: ".55cqw" }}> + + {tier} +
+
+ {welcome} +
+
+ {eyebrow} +
+
+ {title} +
+
+ {date} +
+
+ {words[0]} +
+
+ {words[1]} +
+
+ {notes[0]} +
+
+ {notes[1]} +
+
+ {site} +
+
+ {showCoordinates ? `[${dms}]` : "PAYMENT VERIFIED"} +
+
+
+ + {/* ---------------- back: boarding pass + QR ---------------- */} +
+
+ +
+
+ {registrationPass ? "INNO PASS" : "Boarding pass"} + {title} + {tier} +
+ {registrationPass ?
+
Passenger / Participant

{passenger}

+
+
From / College
{from}
+
+
+
:
+
+ +
+
+ +
+
+ +
+
+ + +
+
+ + + +
+
+ {boardingTime && } +
+
} +
+
+ {registrationPass ? "Arrival / Venue" : "Landing site"} +
{site}
+ {showCoordinates &&
{dec}
} + {seq} +
+
+
{featuring}
+
{headline}
+
+ {/* QR slot: stays on the main piece, clicks don't flip the ticket */} +
e.stopPropagation()}> +
{qr || seat}
+ {qrLabel} +
+
+ +
+ + +
+
+
+
+ +
+ {(["front", "back"] as Side[]).map((s, i) => ( + + ))} +
+

+ {registrationPass ? `Innovision pass for ${passenger}. College: ${from}. Venue: ${to}. Registration ID: ${seat}. Payment verified.${torn ? " Stub detached." : ""}` : front + ? tier + " pass. " + title + ", " + date + ". " + site + ", " + dms + "." + : "Boarding pass for " + passenger + ", " + from + " to " + to + ". Gate " + gate + ", group " + group + ", seat " + seat + ", " + boardingTime + "." + (torn ? " Stub torn off: " + stamp + "." : "")} +

+
+ ) +} diff --git a/docs/pass-experience.md b/docs/pass-experience.md new file mode 100644 index 0000000..d1178c4 --- /dev/null +++ b/docs/pass-experience.md @@ -0,0 +1,38 @@ +# Registration, payment approval and INNO pass + +The live flow is Google login → participant details → payment QR → screenshot and 12-digit UTR → pending team review → approved pass. College and roll number are entered by the participant. College is never inferred from their email. Financial approval always comes from the authenticated backend. + +## Reviewer preview and the single off switch + +`REGISTRATION_PREVIEW_ENABLED` in `src/config/launch.ts` is currently **true**. Set it to **false** and redeploy to remove all preview entry points, mock users, local uploads and simulated approval. There is no UI toggle. This is independent of `REGISTRATIONS_OPEN`, which controls whether live registration is open. + +- `/?preview=register` starts all steps, with a blank college field. +- Preview participants select a local screenshot and enter a 12-digit test UTR. No payment, registration, upload or acknowledgement is sent to the server. +- Submission shows pending review. **Simulate team approval** demonstrates the final pass using the details entered in the form. +- `/?preview=pass` opens an explicitly marked sample pass directly for design review. It contains no working entry QR. +- A real API failure never falls back to a mock approved participant, even while preview is enabled. +- All server authorization remains enforced while the preview switch is on. Turning it off requires no replacement backend or routing change. + +## Deployment prerequisites + +Apply `supabase/manual/pass_experience.sql` to the existing Supabase database. New installations can use the updated `supabase/schema.sql`. The idempotent migration creates an owner-authorized acknowledgement table and functions; it does not update financial status. Hosted database migration has not been performed by this code change. + +The existing entry-pass tables/functions and a valid `ENTRY_PASS_ENCRYPTION_KEY` are required for QR check-in. The pass itself and PDF remain available without a QR. The scanner continues to use the existing staff-authorized opaque-token lookup and atomic check-in functions, including duplicate-check-in protection. No default signing secret or simulated server approval is used. + +## Pass behavior + +- `/api/pass` intentionally uses POST: first access can mint an owner's opaque QR token. It returns real name, college, registration ID and backend status. Tokens are only available for confirmed registrations with active passes. +- Visible registration/pass screens refresh on focus, visibility and a 15-second interval. Hidden tabs avoid polling. Preview records do not poll the live registration API. +- Database claims elect one tab to show the celebration. A 30-second lease recovers abandoned claims. In-flight claims are shared across React remounts. +- Acknowledgement happens after the pass has painted, or an explicit skip. Navigation cleanup acknowledges only a presented pass. Failed acknowledgements retain the claim and retry on focus/connection recovery. No local-storage value is the source of truth. +- Subsequent acknowledged visits show the static pass. Failure of the celebration service preserves access to the approved pass. +- Phones receive a separate vertical card. Desktop retains the illustrated two-sided ticket. Long details use the flexible card when necessary. The real college is distinct from the NIT Rourkela venue. +- The text writes in once and settles in approximately 2.2 seconds. Reduced motion disables the effect. The registration ticket has no idle canvas rendering loop. +- **Save PDF** directly downloads a personalized PDF. PDF/QR export libraries are loaded only on click. Text is drawn with browser brand fonts before embedding, preserving Unicode names. The QR is included only when the backend supplies a token. The existing PNG export helper is retained for older callers. +- Keyboard controls, visible focus and QR-dialog focus restoration remain available. Font license notices are retained. + +## Verification + +`npm run typecheck`, focused ESLint checks, `npm test`, and `npm run build` verify types, compilation, registration validation, the POST transport contract, and real PostgreSQL approval/acknowledgement ownership, contention and lease recovery. + +The optional `npm run test:pass` browser harness is separate from production and mocks only transport. Browser checks are not run when reviewing code without Chrome. These checks do not constitute a 1,000-user load test; production capacity depends on the deployed application and Supabase configuration. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b151427..6eb0ede 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,17 +8,24 @@ "name": "project-spacex", "version": "0.1.0", "dependencies": { + "@radix-ui/react-dialog": "^1.3.1", "@supabase/supabase-js": "^2.117.2", "@vercel/analytics": "^2.0.1", + "@yudiel/react-qr-scanner": "^2.6.0", "@zxing/browser": "^0.2.1", "@zxing/library": "^0.23.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "gsap": "^3.15.0", "imagekit": "^6.0.0", "jspdf": "^4.2.1", + "lucide-react": "^1.61.0", "next": "16.3.8", "qrcode": "^1.5.4", + "qrcode.react": "^4.2.0", "react": "19.2.8", - "react-dom": "19.2.8" + "react-dom": "19.2.8", + "tailwind-merge": "^3.7.0" }, "devDependencies": { "@electric-sql/pglite": "^0.5.8", @@ -27,13 +34,29 @@ "@types/qrcode": "^1.5.6", "@types/react": "^19", "@types/react-dom": "^19", + "autoprefixer": "^10.6.1", "eslint": "^9", "eslint-config-next": "16.3.8", "husky": "^9.1.7", "lint-staged": "^16.4.0", + "postcss": "^8.5.31", + "tailwindcss": "^3.4.19", "typescript": "^5" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.3.0.tgz", + "integrity": "sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -1347,6 +1370,323 @@ "node": ">=20" } }, + "node_modules/@radix-ui/primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.2.0.tgz", + "integrity": "sha512-KABY+VMIRPJL+Vyzv/335FEhXXD/xDv8BMb1kl48/aXJZMH0LtHCTx5ga5RnxaEP3nZHtmTLf1P9vanmFX46bw==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz", + "integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.3.0.tgz", + "integrity": "sha512-v5AYEocMISkbJ+1fTXzZpiFv7NRr3D2WiYbLIKf+FkmJ8VkP6d503eV2n34MFussHXY1pcoq3yfJiQH77dc4Mg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.3.1.tgz", + "integrity": "sha512-+0E4qvVTwjAWra9sEhJ+9BTsvHE00zkUuNw1VGh7S+Gc13dfYk+S1PVQdchWDj+XYHhAai7Z7IpzXVDCGsDplg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.3.0", + "@radix-ui/react-dismissable-layer": "1.2.1", + "@radix-ui/react-focus-guards": "1.2.0", + "@radix-ui/react-focus-scope": "1.3.1", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-portal": "1.2.0", + "@radix-ui/react-presence": "1.1.11", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-slot": "1.5.0", + "@radix-ui/react-use-controllable-state": "1.3.0", + "@radix-ui/react-use-layout-effect": "1.1.4", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.7.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.2.1.tgz", + "integrity": "sha512-KIfDcAsx+oVylFZ4xryVKusJUrLLhTQmfnJW4kwk4Km5myvhHCrj04hnWWUC166+xD4DHdH8tQGylwYX1h6+Pg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-callback-ref": "1.1.5", + "@radix-ui/react-use-effect-event": "0.0.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.2.0.tgz", + "integrity": "sha512-MPm5R0iRGUDrDnPNxmLBkv+X7pN4XKzt+MbWJEuJQsH3NFH4omrbpXpucyYCCKTSt+na/ZxGhEWQrWTZ0285cA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.3.1.tgz", + "integrity": "sha512-ugeMhbXt4y5S2T1GnIqbWDKEN962PDwnX1fN0eKOOgf5f63Dh2mn8F1FUySlgW0iF6GiVsRF32DzuDIWTUyQJg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-callback-ref": "1.1.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz", + "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.2.0.tgz", + "integrity": "sha512-StX7xXnaRU41VvFtMm9zlhVGz8XF6GmWWTXftkQaY+tqVkbs/R9UmAp5mLzHHapk5hM9RMZQvO/3usyIP/g42g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.2.0", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.11.tgz", + "integrity": "sha512-Z7/atlkab36Z8hm+V8zYc79r0W+tiOB1o0tun1By94JyadkekLQmtEAnBSP9XKXBNQsStoStS4+gX10JpS5akA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.2.0.tgz", + "integrity": "sha512-HCTSPMNqv55Qk0IX4geJbpyXazmqulcimwuyjxTkKi29v+QZbG2Zho9BnbBq4YS2PF+KlNb2CXoLz66uUmblkg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.5.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.5.0.tgz", + "integrity": "sha512-tyYd9ddPXAysAbdbD9eYxgwpCSv6f3PncqVSNKQFSR5lcJVLz3cb/pANDoYrLiHBpXv7skortyUgGUWsYuPPFQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.5" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.5.tgz", + "integrity": "sha512-Y5GBf4NKeADoXI1geiMlMuMoURT3k9MizzzKhGb/m55H94aGigZ01PIpkvsO6lML13BA6XYAXSJ6gza7vTn5nw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.3.0.tgz", + "integrity": "sha512-TAcBI7bw2ljYCbv4+zuTSd6zICu8pRt6SDN2vJ/Z06K2MXh6I9WYFe/A9ovlFDtR5HVHGm5iDxDoABm/++dbKg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.2.0", + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz", + "integrity": "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz", + "integrity": "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1466,6 +1806,12 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/emscripten": { + "version": "1.41.6", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.41.6.tgz", + "integrity": "sha512-uN+9i8bFT5CUcZfyIEYDrSueACEyKGbUs5kC/72DGlZZoinh84sJfVV0i8UOJD1asdzkvLPBRrKs41kZ8MdEXg==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", @@ -1524,7 +1870,7 @@ "version": "19.3.0", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -1534,7 +1880,7 @@ "version": "19.3.0", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz", "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==", - "dev": true, + "devOptional": true, "license": "MIT", "peerDependencies": { "@types/react": "^19.3.0" @@ -2208,6 +2554,23 @@ } } }, + "node_modules/@yudiel/react-qr-scanner": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@yudiel/react-qr-scanner/-/react-qr-scanner-2.6.0.tgz", + "integrity": "sha512-WjNcSt7qquYUz1LVbwKzSnRQI47sNrh4Vh6nNiGKVxnYcP+KgN5q9rcSzXyZ/7GRV9PPrnzoIuE5YdOxB9yAog==", + "license": "MIT", + "dependencies": { + "barcode-detector": "^3.1.3", + "webrtc-adapter": "^9.0.5" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "react": "^17 || ^18 || ^19", + "react-dom": "^17 || ^18 || ^19" + } + }, "node_modules/@zxing/browser": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@zxing/browser/-/browser-0.2.1.tgz", @@ -2338,6 +2701,34 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2345,6 +2736,18 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", @@ -2538,6 +2941,43 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/autoprefixer": { + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.6.1.tgz", + "integrity": "sha512-cL1Qz6ADZhcEbny/8HPfe99J6HhNoYtpX2LFLIbhgGE7Q1hlQVkYFdetDN7Id3KiQxhDrHwzlHr/YQCnZ8+xSA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.9", + "caniuse-lite": "^1.0.30001810", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -2593,6 +3033,15 @@ "dev": true, "license": "MIT" }, + "node_modules/barcode-detector": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-3.2.3.tgz", + "integrity": "sha512-PLinpWGiOQoQH4X+YObWZ6iXeffXKDM3d4vnOD86481SvukIfvkf7jEE/tud9oI4HTDxtDdlHaFilA5Kn7Xa7A==", + "license": "MIT", + "dependencies": { + "zxing-wasm": "3.1.6" + } + }, "node_modules/base64-arraybuffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", @@ -2615,15 +3064,28 @@ "node": ">=6.0.0" } }, - "node_modules/brace-expansion": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", - "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -2741,6 +3203,16 @@ "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001814", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001814.tgz", @@ -2798,6 +3270,56 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", @@ -2912,6 +3434,15 @@ "node": ">=8" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3013,11 +3544,24 @@ "utrie": "^1.0.2" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { @@ -3169,12 +3713,32 @@ "node": ">=8" } }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/dijkstrajs": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", "license": "MIT" }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -4065,6 +4629,35 @@ "node": ">= 6" } }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4174,6 +4767,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -4575,6 +5177,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", @@ -5001,15 +5616,13 @@ } }, "node_modules/jiti": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "bin": { - "jiti": "lib/jiti-cli.mjs" + "jiti": "bin/jiti.js" } }, "node_modules/js-tokens": { @@ -5166,6 +5779,26 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.4.tgz", + "integrity": "sha512-zJZyBmQhArDRefuWTypZxwDpFDIYmrj8ypSBvwGD5P13Y95s6DjzKgu4DVdGbeQa5PDEsAOCAPNk4X+QOR006w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/lint-staged": { "version": "16.4.0", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.4.0.tgz", @@ -5323,6 +5956,21 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.61.0.tgz", + "integrity": "sha512-v2SQPPPNjnr+BlhL9Spuzmo5yR+hLkftfuE4E3jaxdNPgSH0hJKPcLJBP7yAta87jQNPsSERS59PJjCJ/CorBA==", + "license": "ISC", + "peerDependencies": { + "@types/react": "*", + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -5419,10 +6067,22 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { - "version": "3.3.19", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz", - "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", "funding": [ { "type": "github", @@ -5570,6 +6230,16 @@ "node": ">=18" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5580,6 +6250,16 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -5868,6 +6548,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/playwright": { "version": "1.63.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.63.0.tgz", @@ -5916,6 +6606,191 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz", + "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.20", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-import/node_modules/resolve": { + "version": "1.22.13", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", + "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.17.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.5.tgz", + "integrity": "sha512-TEHFzb5KRDKaOgJ4TYE+0jyJtFbjLvkdVOu0fZ2b6MTWzoqZd4Le+61aEppWkvTlYePgOX4ATL1wsAIPMLTw6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5974,6 +6849,15 @@ "node": ">=10.13.0" } }, + "node_modules/qrcode.react": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.2.0.tgz", + "integrity": "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6033,6 +6917,95 @@ "dev": true, "license": "MIT" }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/read-cache": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.2.tgz", + "integrity": "sha512-/peqiBB/n07gQGLsWaHho3WfvUyRscw0gYTsEFMhrIe/nWLkYaf5SbKYjGYqtRV3aPwykJgF2VEMo1ac4bnsGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -6273,6 +7246,12 @@ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, + "node_modules/sdp": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.2.tgz", + "integrity": "sha512-xZocWwfyp4hkbN4hLWxMjmv2Q8aNa9MhmOZ7L9aCZPT+dZsgRr6wZRrSYE3HTdyk/2pZKPSgqI7ns7Een1xMSA==", + "license": "MIT" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -6786,6 +7765,39 @@ } } }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6822,6 +7834,118 @@ "node": ">=12.0.0" } }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tailwind-merge": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.7.0.tgz", + "integrity": "sha512-XPPUyAc+cvspz3lHTcR/QgPfW2A0lv/xQNIjX3HGhLR+Nq2lHaLq5MtTesHn8GUr3W3DguT2KT5x3NVgRtYwmA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/tailwindcss/node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.22.13", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", + "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.17.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/text-segmentation": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", @@ -6832,6 +7956,29 @@ "utrie": "^1.0.2" } }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/tinyexec": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz", @@ -6925,6 +8072,13 @@ "node": ">=14.0.0" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -6970,6 +8124,21 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.10.0.tgz", + "integrity": "sha512-NoSdpq/WEiAg5sjmBkmV/hfxv6HJH4NqPNrqjtSO5CwRmpsDfaf4begxW34KdJykH/l1yHtwBWQkCRdoXO8mPA==", + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -7190,6 +8359,56 @@ "punycode": "^2.1.0" } }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/utrie": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", @@ -7213,6 +8432,19 @@ "uuid": "dist/esm/bin/uuid" } }, + "node_modules/webrtc-adapter": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-9.0.6.tgz", + "integrity": "sha512-CHbl2ZQbxx164IgWRgzJno4hWtM4tFbRam1QfI3Yxhs3w/DvqluVxVWeXs3oL5/fbGkSNLKo0Ty5MgUWceNhog==", + "license": "BSD-3-Clause", + "dependencies": { + "sdp": "^3.2.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7591,6 +8823,19 @@ "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } + }, + "node_modules/zxing-wasm": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/zxing-wasm/-/zxing-wasm-3.1.6.tgz", + "integrity": "sha512-mU7UNuvl+hOT+nlSOQTMHZ2tM8lRMsbjDIp5IO/+HmBl/FOq77q0OSZPJ3cm42A9c1MKU6Uve67FiGdkhsrT9g==", + "license": "MIT", + "dependencies": { + "@types/emscripten": "^1.41.6", + "type-fest": "^5.10.0" + }, + "peerDependencies": { + "@types/emscripten": ">=1.39.6" + } } } } diff --git a/package.json b/package.json index 557d316..41deb0c 100644 --- a/package.json +++ b/package.json @@ -8,21 +8,30 @@ "start": "next start", "lint": "eslint", "test": "node --experimental-strip-types --no-warnings --test \"tests/unit/*.test.mjs\"", + "typecheck": "tsc --noEmit", + "test:pass": "playwright test --config playwright.pass.config.ts", "prepare": "husky", "check:assets": "node scripts/check-assets.mjs" }, "dependencies": { + "@radix-ui/react-dialog": "^1.3.1", "@supabase/supabase-js": "^2.117.2", "@vercel/analytics": "^2.0.1", + "@yudiel/react-qr-scanner": "^2.6.0", "@zxing/browser": "^0.2.1", "@zxing/library": "^0.23.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "gsap": "^3.15.0", "imagekit": "^6.0.0", "jspdf": "^4.2.1", + "lucide-react": "^1.61.0", "next": "16.3.8", "qrcode": "^1.5.4", + "qrcode.react": "^4.2.0", "react": "19.2.8", - "react-dom": "19.2.8" + "react-dom": "19.2.8", + "tailwind-merge": "^3.7.0" }, "devDependencies": { "@electric-sql/pglite": "^0.5.8", @@ -31,10 +40,13 @@ "@types/qrcode": "^1.5.6", "@types/react": "^19", "@types/react-dom": "^19", + "autoprefixer": "^10.6.1", "eslint": "^9", "eslint-config-next": "16.3.8", "husky": "^9.1.7", "lint-staged": "^16.4.0", + "postcss": "^8.5.31", + "tailwindcss": "^3.4.19", "typescript": "^5" }, "lint-staged": { diff --git a/playwright.pass.config.ts b/playwright.pass.config.ts new file mode 100644 index 0000000..fcc5aef --- /dev/null +++ b/playwright.pass.config.ts @@ -0,0 +1,11 @@ +import { defineConfig, devices } from '@playwright/test'; +export default defineConfig({ + testDir: './tests/browser', testMatch: 'pass.spec.ts', timeout: 30_000, + globalTeardown: './tests/browser/teardown.ts', + use: { baseURL: 'http://127.0.0.1:3191', channel: 'chrome', trace: 'retain-on-failure' }, + webServer: { command: 'node tests/browser/serve-pass.cjs', url: 'http://127.0.0.1:3191', timeout: 60_000 }, + projects: [ + { name: 'desktop', use: { ...devices['Desktop Chrome'] } }, + { name: 'phone', use: { ...devices['Pixel 5'], viewport: { width: 320, height: 740 } } }, + ], +}); diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..4045a1c --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; +export default config; diff --git a/public/assets/payment-qr-code.webp b/public/assets/payment-qr-code.webp new file mode 100644 index 0000000000000000000000000000000000000000..3cf1c942f0f1e6d8b548f5241894d817b2e97fdc GIT binary patch literal 38506 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 ebh%D?+EiiYPFF`wCnEGCAN|$61?z7kwFoUd

hs`S9N9Is0ktY3&?% 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�>g>jg)%$eqL{XB(ksZ_x-M`MWOA^(Q7MMybYn(a@jyu5W9tRZ+3)7 zw&E8|d*tUuEKZs~jO2|>l}*uYFeeHK^HMU90Z?7a`8iU?@NOl}8NZU{fHpOZ6ARVm@<{7R~x>4+Dv6ysPsSlTgM^^4%F>q*3yQH6fjC5_$IV zm`w7^a6@attpnAL1hgGBI?e8-hxvo(d=&92^2!+UC!v9WhrAaAFIF$a!~nwVOfF_o zqf2!EG{D1{pY}`GF$#gQ=SF6^n2Nh%V)|2`k;@n-y3uy1!n%@seR_%mqtT08zm0V7LHuzp;B+3kAS!^4{^26W|i zwLqHCmsR(GiD`UBw>6#=UP_H&Pru?_kJ`i(#88{<$SS@f@I7ppU`0Fw?hFi>^z|v< zoTrPvDAUNXlA$J^$W>6%%ico+%5Ct@% zr?!*Rp$=3i`<)D;W>e*t-f(jY1nbZ!|K};_dmht_a07$bw;f%XBZLdDrB5=BDwib` zs}zP>->!Ii8#DS6Wz>15v@1;yzHq9+SmQsC?KD79C4z!1v||h2HO0&Wr)J-ui<$j! z0AcZigyRg(nR zk5$*z2jT1u+)JQDnV#yy%hIuqL=l`4vH8we8A0pzy+w?x=*pm!cLanZQFW5cNMvYm zGkFPi@(FCX=#7zuG?4$8P0Q`VX}lK)mwbr8cS1xA^{Ht9mj5dnYv_F7FuczHn@}7<3WFyk z@Y4YEw0bG%-I(go-qE(TDm9n6AaD*<;xyM`DzgWKTyGdXY=h#Ni1&&>H3biL~aX+M-7CM!L!Be&yubf@X6Q(D`4s8;!GpC0I3bkvaJ12C23uHGeT@GywMW|G@W4C^#AYoOIaX{KcQT)r>PFz8Ss9jO7xZ6FlzrEQVWepVG$4w_0Xlf( z-d8qCMC4dZeZnWWv#uPLlGS+CYW(DT`@f~0AeHcwk0sA77fltgP1T*Ec z{Iz{q?b1IH2>IhIhqE4yHv3gU6i7M&_mAK-9}lnNgXh6Eo20%XIVV*d98@7?mW}F; z6MBe&5l{dd!gWC8j5h4C%Of1_Z~sQajhei2?ODkKe7Lvb=B`k55HLd2<@|zixK-eb zL+$PBKw~rkknDYeoL%|?jWM!N%zBalOO2n)npOLt?HNS3TVQPRYzoM(e44Zod(jNk zWqjO$$}D+iS0QvB)(w4@Rv|_LBa8=?&qVn=Uz*k&t;4Fh??T%f^yw?OoIVAhhSM4c z;$e$2+c&eJ@}Cj%+pLDwhPqex?|kk;_?fC8r1`9e`uoKAR(jec0&((~NT9A~f|y%g zor2Zkq?oQBwtAg6@I*U!%1J#Vx9*uDTo@)&nVySFg5*=%pPqS*s(?JQgFyMKUiTaQ z?+S!I;`NS~|kW(LVz^Dz5w9U`E!zmI5?Pm1kbLd~sTrg%r*r!wjEejRw0ok#` z3sb>uJ_uoQs4{b(7&J(DB|HCP?8IKAsL7fArF~*_eKxIitxy6&@yDZmHt{186-)6A z<2@RxAjgvf+;>BhWqaeH;frTOJE&m;GS|2T)wD|N|ck$ z0odyq9|Sr6oPT;0{T-Wif+!q3an@8;j{qvlKFZU7+T$@(Sq1TlcIBImO4g+H=rQ$A z1|eH5gINQddK;Uqc>Sc2TKS5yQpOPDL>#-D+=IsCvKR8lb2CusESX?pXiB}zz#sT% zk+itUyMFNB^vJBES352>6@?d_c;H@DOMMt((wFB}0rXK*ygP&ehU2RccC2ak6?Z84 z&AJHz(LKs!8Av){xdy09wq)`16ei&16f*YYFp@&091>%VqOL-L=lGe4ozkG2+X~Gv z?SH8F3&QB$_d`5Rb#zKFz{lK!+$8JSnS1orYr7YD!#1Fw{PJJqUOjP1z~eOxHj?O* z08bYR6%OquAcqhoZ73$T0v;-t$ArotGc46{JOA@XFFT(t&}Ys7TA$C*$}s@A@MHi0 z0id_}B6p&B+felNe4$+DhPqaOeyR`s*!x##N}8^g1YJN{xiaUSRtMp0gC#AgD9OO9tjLL5#2 zl(!VtCKBE<_WU%``3U5a@h*ugF2EpR-9T?YkFe?~ht~COm0;u6QL55NA`X5w3LMYG zEdmth+Hn1l57beUNNPHY)Ke_E5b2BSh7zv$hl#L|v~`|Gp{Fym`(`$H6z@dHui9(? zApnGt1OS%1;WZMHby5VI!AQ5Ic;`LH2|J*bm(4f_BB&=g9ryGZ> z&~c0(w}}aoj>CcT;S(LPvh)W6HhiukI&?sCi!fv?$VZ4C% zt``6Qz<71m0*4{maJ9lo~dXrY73zoT8JVo;!UNn!{o@EqVg#O^4ZXb_6sI4YD@iK)#;T%mM%55 zGIr1kSKDt#bxdM0CvT$R$H&{r`LP=BGj65b3g#IhBXrYV_|-0YYhrV04Vyvj$b&MV zaErKmV-J@B!dh8VV?OV6?ABHG6oDv!9ajf&T8x5nIxVghgYJCdwhi9E<$NR=Cs=(m z-ErL(($4>J&Qoo#UM%IQ2ukHB#JDbm8^X5Wl!r73c}3p7?B3>%P#O_^ok5ub{&@bH z2X0gyc<3Xz6L;?b^gG z2gCr-)t-B!#l8v)bi2nTX`eF6A~XwL!xDGIx=8KJ{r!X=S!rh!Gh78T2W9M}!Plha z(oWr%4YwP;U!G^pfC2!qFmJ3CM9~p|>Z7>zip)9MNF=cr8(hQ=OC>Wk|d(xst^khL$|l$=|s@C z$-b)1p@)LNH%=4e=k`G0d^eM9m!{A8(LQ(?n6DjNdh1}CasfuDVX5WaY88uF;wB;x z1VI06BMTLE8i>ZpmToysflfPj7(JEC*j+NZ@rli^Kb-~)ZK7GTI&Ybd;}JE{#yRS} zuJAkLG*+&o1VKiq#QYZC79__ ze2$ZsI_g&)B}Y6oVuqxKItCdag8z*&_-e3~63u2<@EzADaCN$Z-Kx_uft-2~!l0eb z*+JD?pC4L=+5%3iWaK#w=KggXRo|JmczN`cAdMVYYbatTwgtt921fw4 z8#H;c9V)1}=e8X4k1$@wzSFZZi+ZOv*8bBB9!xgxKH+Y<`@r`;lf!o~?$RN5#BlGO z0#}rOok;w965)8R#{Hmyep}P-_f)P&K{$^1!G$Jii$lQ+qSEPaJW!Ab z;IznsOoL#D*8ujb!;ik8ymF|1=v@s~_m>Rizyf`4F}=4X3NCj|;7tc|od+I>M>LQ$ zI?KPQC4ioS2Us>!qGag?VZ$TBpn13shKZ4&U*4b%{ddWI2x54yJIgK@=*agu(WrkCyY-b$gO4JPR4oJ8BqK)F97l@=g~glvxIqrY;i) zl5!L=lVOhcvPfW8DUT`5=C9ed zMBZA}JKt&ih$Ja?s>Ipv;Ga`60ggAZ=^{a~0uX+BH_EaUZoDCL5V65o`iC#G$-A0q z<`iVJ1L*`r2JCRZQ!#Ozu$l!>xE#QsO!I+@4~f7ugU*|T_w%bM3r@&f%jR=^h6&5M z->&aoW6f3XRqN4C95=KEd`;w#I7io-GJK%gE}UaWnFgS4Z1 zRIW(f1)}#zXA@dZ^Q-lCj)vGK|y1A4*`;f3OtzuqH82x-nUgrSx&vrY34U=Q=GKk`bm9j$Fy}G1AvX}| zd4Z!C!8FEzK{8y|q2|-~{PXLdr3;g9Qbs4p%{RIW(-KlJ@(8F>qoQBXqD23>eWO>3 zSKPAtNo4y67OAXw4df>eH31^M!6o!9IQl-4rAfh{Abh?s!YNm;VO zbgCK*4gVmvJPH1d9rgmFBFg#V4Ans3^4exIIE6s(tFM`aaYH%Mt7Ykr2wl?~zOeto zq)kU7wvdWzn=r~WoZ4~-OnCb6wC?vr%@?ym4EEvlu-%n{inz5~&4fo8;i!=3^`C*{ zov=--b(#i4k@j;;rtB{*`b$tJ=CV2yNUR?sObd0!f={>G&YUFXEcYyT_%1BBWCx1; zo_PBZt^>%TbOov1QKd79gJ6dm%i|}V8;+Avoo%OFD@S);Ot~vCu^HZbAq#%twP*g4 zL)>);REXDz+gRZ|PrxP=xg)?_gG-*co_up#$HO%cRW3BM8Dnu)XLQCa%?+iOKKtDvP_#Rp+;mMwF{hff&_JUJ7Ss9Nwkx69+N%)0$Eit73#UL8`Ejkw-CxB zXDBT@hNnpDp>6>8g3#toj*>ivf)rs> zfaFUlHDB$}PE=C}(5~j9$KiBdcAyPTb{huSZ`1?C%SMMrB=q}9CAKXa7uW^r@V%BeIxZbbnl`B`Sw{r$JItR;+e3Ytm4OS%zLP2R(QwQf-y{H9S-n|Ri6 ztk+H{me%~c9~rrE9g+oE#D2(SN_9J>Ut+S9V%pvO_z*Q98%g>+JGpug62ia?n;t4q zg|r~NfnHthU41yBc`dm);S(&B=+Xxey^is3>y=<77R!%ceoJ8(V=c01XW`{loysk8 zw|BELnfcA^wd5QwM_fQ%eL|*~bk~qb!-YdrZxc8junoMYqmk|5O4# zPA5Nk4=J~{(C2|VJBU(iC!WqkRt3w_x4Mp)UWwMqElLZkq%aLukzl0K+XMw-V=18V zXj<=8>t(SuxkI{X`dPUnerb}e-?*PfW&=K;&u0dMY>??kW%0so9YW)`0K%)<$KMGuNYG`QpU9CP%PZ!;40#pS$ z;bG|4?>&0NT9fO-2uYTJ#1BYJGl)XQyS<^Q%-zDP^wYnM@BuSc#qF5T7gV>f1f>Uo zdQ}TMT7BI&uMg4aniAZsoFp-A)YK#lv!eV6B~>@TZ(e|RP2v9Itaot~$9&y%Rk-UI49S9%m}v>Dm6U8zAfbg!FD9h13nQTnZ0X4QIB{r#>Mon*j0m}M6QLzI zcMkh0LTo`wvUFux7gv!l`gxzeDIkL{+4G(vCYB?PL)wf>Y(+K_{H|O>=H(q3qG>#Ih$Jz zz!~D~-k-*OVoz$o01mjgr1)Yv62{I8@7N2n5m-{QPvvpo879s8nw>!a&@Z&6A~TvF zl`yMnK+4$R2o6;}gT`w`A`7{Ylz>I_Vu63K&IK50K;Y_dcs|=*hZ)qum<5WE4vq~6 zDht4*sdg~YU1m7UjxT*^Bx;`g(}E=ZqnR`fvV>1UoH|oMVkD;G3BR~a93Nc@ywv@Vw!v}DSIWwBZk=bp04-0u zNdWP1)Mgzkv5{2e!lkUP#VHclE&FLGN1x-;?u}^J!)6(mCJ}MD^9|1@^dCT02MwIM zsM(Y0Vj_~M9}!GZceI`zerSsl=+W7bj*7KF#vfltKj8^6!-3i!+`i#6(%>AU0SX)J zCH$`GP=MTWK5U5+NJL#2d|_QCi!Fxz(IKT>!w=optE6mpKqu~@nA@onk-?`l>-Wgc zBsK~~!*TD$xl(BGGD0is`Gu8Fgb~~aOEj%7vClR~cMOTcN)9XrxPMYNs_GgqcyG%&D9 zzoQ5#n8S!A0KwE}0#l-C)Rxsl{k5M^-Qjb-93iiq^zzAE)l zD}*SsT;UkPFp9I;eV*LwIL9%jQhrYbpGI#B&ZX+j2e*ylfs8kTW?f21kL{qHB@pWU z0lrDwQcti|?pea0dU@3#0z^Y(`WP&99rkhiv(CNJ(TVNWXWV2-f&*QC8#`fPGDba@ zm&c_5X(88WcNS&$Tj_9j02wXg>e5COWH8uOn_}Iyj4ZV|0eS3$vl@=rfY9 z?%*e5@U66bX!cmH-QjsuZsR(uDpGN z$ak*zcl@!b!_8D(oz|!h0lts??Z|)TuG}?5(HBs4f@^4JQt(`WFTr#@#M0}oxn>rh zj6BW`3n`KKbL2L?Q~+96e3oURiZvzdAT-jubvgYVZfJgU)z~}TwK7|i3NO=^DU=i# zlCg}FKM&CiBua<1T#qyu*S*jY;*iSO+j21g2~b>MJH@;tcAcnlum)LC*3`dOzBT>p@+Z03=M2@lC-fuV@CY>vhdgr7<2%n{>Vn4v2`zm41Hs;KiI?{r*UVum*8&Z#)ON{t;7Fe z^w>~wx0#!KtaaY+rB%t2K8mBQ+cXYJ0by?=}E*`cQ=&IRv4eTCsa%+Tg7>}(FNm% z4=`Im6_|ko`@yTk=9M`CmjJ{3V{RE0A(bGvf!b*nz`}-1JJY4j8~rnpr!fT+ zRYy%s%jo|2B=I455en=Trcan7y@;t1Ms;y(JdaEG%dvV!K&^)or>@7c#V6z>j_n=> zDBN1G$Vune(izX`I=hD%`k&!>glW8Q%=U#gr|@4SzS_JmiljjZWG2NsOlo`^v`el> zQ&{95*j}8}Bpev;agBz8pBF<~)>z^#>JF=m2r}H>sY3ve;X^1_Om*&IEAT`HaDrgf z?Kp)$2pu?j(pgw~IkDQLe2Z_w2FWv8O|z1+I4aWNR=ey|0tKKPu)y~%lu4QZ0)?Qy z4a50CBcl^C3&^;Nr%}GQQLa9upmBl|*iWIbCE3Q7T=#YY;Rfin{k##>xskHc5isjy zOLc<@D#@L4UV7|*%@gJ(uVE=QR-*|A=W~4rmxo3$>EX(twrkLMi8;4CAn-$YDeuRL z?O|PAr@RnlHyygmKh!N!W2Z2&{YF~s5viy1*a#+Nta6ieh@ms(2N%Am)fat!&jizg zDk42D|B+`#{Kvfa%fWt}nr@djom1gf@qL*SO*HS^M6#1I=jG|N*~8n6dd!WjDB@=e zd|fs$e@Q#X1$7M@?Q0e1k6G(SQ%$wASY9ID;uXxwNQvEYfJQnY1EiKuFY&{4xc0WM z5eGZycY3Tr2Z9!{LpPy>e09J&@a72>CMLMFf|C{e3J1`nYha{BG8*icMj5#=w*AoT z3$cG#vHGBi+#E(7IJ+w%L%%*PN!7RG^_KBIg+M^Ws$NK#BOe-NLK$rJ#ag38;W18+ z7OLVUcCs4Ddp1IAseMnghMPa;{O2$TFA%x+ z1VYQfCNNhLP@@WPo3_rwD8igZt-Z{p;WuaHh*ZY5sHW@bGu%b@E(- znf}}}hPVj-;6p^-s~WWh=Sa4e0L7<7eA?XbO!ZCYLR1W zpVF;0MHUIo90*k_^U7@Mj8O=&$_U(=r8gM(c_3k&(ioQAG9{^>CK!zAi06kv6+-0A z*r0uNL#6^AxYKf`^s|6EC3j4pX9RYWtb##+t*f78;Fhwy z8~y-GK(xQ{5Y~-2rX9u_o;}PS0XfmGhVD@ATK90PvtYHxt;Eau2|L3!5Oh~Ucdhw< zwVZB;JlRiQ+L}ev{{qJ{Ji7q!Alhs5U{+w7EYn6Xsi_a>&s2LdqwJKp+xY+@?mz;5 z3__2FA^A_Hok8vL(Gy2a92$omhCzs&Fg0?aO2xA^~9%yO#oLHxoYt?z^27l&xd4YvOk(Wch~=Loeke@X73xX*wHMCVmaZ zb}G)Ev$hE&0lFrzu1b>^d_xb&k!$-gra+&+p3X0(74r%;vVJB%Oofio8#oJjV6+*B zRCDGUdpb#s&#Ttw>#1fvq?b^6tP!`adPM7a=&-8aEd2;3;j>JaMs}ukYWWwPzrYnn- zwWEUHjrN|U?$L+nT5Tuwohj3Cg2koJG0n0mI1o`|;UpzPe&{Rd9fQrob(aZB1NpQk zFyk`-=)S_mG=#Hy|FZ-daFk;HHL+u!urJR;@FDQWmAln>43)hU8G8;e5O2AJdcEGcbOyojvPsge=J~uMBdU&Js)~9Rw z!Igvsl`X%2S213tA{z{~q+hZcFQ)8;Q5la<5ShHS&}ERgAgJ{)(8$)hSK4@e|IkL` z6P^*o-3Npek(1yID(-3Jo~}o&U>ocS{OJK&LHznnn_i6*YQTvns;&N^1)RKZ7%-gd z3_95ku^pIkOvyHnf2W3&A~W8-Lki@~<&J|DfJ-#$0%dWjdqAqKsw z-8^YB@gde=h?;CUYWc_wcI8oZcO%#MhpeC0KHBmn?CC;R-T)+a`ZnTzZriX92C?2Aa~t@gloIQkh&~}8)sdhPQ107yt85DUB*jg# zIjDv5h)9u|S9X7RZKNS&%pd-};73duXBI+o>K@_vhtr*?Gpo%Gtz!#e`ZFHyP3&4- ze5`a|3Gs98M7H8&b||gyYv^=a4zcRM?El`-wo7j^jz=8; zi)ujY?P7kFnM0(5FJF^~z|~3CAF5R@vIuNtgfv&HYJY;!6G0pq5KcrZ6Zpv21x}8f zQxM0OT4@3qkjb?f#DH6Hj^+}cIFWgx9a+AoK64$=dT_)IbP-N|xVq1Rmd}}gyV&-@ zLq5^tJbDIBV|!jZP2z=^tQ!QeFCSgus3B*22xO2!W8G&Jf{yZz@6vjN{NCKtesX1A zT3cf5iQZwJ80_c-B~ik&PSXZOoAU>KUT24=^nZ%22>@IhyS_GQ^@H~ra$(aw-=qiU z28Zb;?8}1^PyRjC{cs!1{oV6mVjD9x(C?~>BjtC4;lZa>l$I{F*m%YI%8EnG2T_9F zx5iN5XUsCaPm*8X zfBApn#9ZfwC&h1Wc**L2@b5=CZm{^~bve-qxgf7We7Bk!#GX{X{wEr_8o+%84+iXd z@P#+|d9Z>@_?0-goce>TcimN^z~2;AX=_v2-CB%}$=Aeo<6fNi6x1QLME))M<`KQd zj%|*;$t=K?#=`RzSHC~;^}ZDo25w}Fb3yBh>gr3N&r@LukgWs~IQ{qU-u9*!=V!u) z6vJDBxs4W>N|)#4b!r-%2>}5|BL?f!$!q5KcRueLO=5tkL?K8cJ`X?Elu%8Tr2zA;GN{f)bwDP#qkET8U?frWA|a{eZ^ zy;+UZho-faS;Q?u+`uuMuoo7V5KNj#)U>%dwzd3EgGO@f_+T({Y1UUj7$EsoRW+?OSLuw%7I5i=pZqjZMFexMA68PI5H21-jVHM(ok#uT@o8s z;-V(SrGHPK@(z4JAe3HU=k}jyCN9BX+5-+%=cTX((T_J9g=Ysa7}A-}%*hPjQ?}J^ zAINLvxv(+q-m_fYNHFfFBnZQ2TKU2=w}+qDd?S?Q>fch&LqTCNR`R?xfr0sdUi+qi zxTO;OT}TE-2a&-?DRCa)K+Z5(O0qJQwTjaRFi`vW{&iem=c&h+t6h``KBD0~C#K=a zp}%vX^;=b4{B2F0;1~?gv_nE8v~Y1P|0pESLE728Ri8O>1v<4-eF3lJ#Nc>jj6VV? z?euC6k{Z=f6ssz906j3kqLS>~#Vr&_g~}2xLzZG{+Y_$KB<*Su)zLfVSH_F+B0^xQ z20QCdnW4X>?nIB8918fE6!J!SvV+h1Aof$hb0C0LIo>|(Tmf{ccm8O#$I)3&neiyR zv}*#KMlM96OMh@WZ1ns<=7m^K?-fT)r=*=$uspGwYQa}GtXn%eH}cP?Cwna59wLcH zD;=gCm84-YvmMak3I! z;mzI^!lO&!t}b?zxm$bhi3q%dTH=Ax0d`dibH5JHR3v=~X;b$Yp!rHp4HQjhg9)dl zBQi&3awFz}U6i?n)qUf*9{p-1P&i)%q(ZyI5xdbQo7cb&Ttlpxfe^E7``;{vtywH) zat{|`KCAX2rFDG#UnsAiG8cXxQa}3Rymfnh!5QdtRm>%b(OA`4xjuk}^^@J-j zsj=L;hR2?Ab`<1S=q3lm{Awsq@2~LBHiO6+>fM1Dw6NVa;K;0fe`fIk3#Ba5i_t1p zlcOUpR!pTe@36>K>p6w2s$IFc8R3|5^>6Lk6d<^Yk^BorU#N7@spTq_I8n*LgBP~C zWJMSH{NKCdIt{*fJM$ZUnc)$5Fk)+C<-(|p5?Y)UKT%Wu`dkdWH0epd{s@TLOc1AC zsc8!gk-~>Q-3iHwTD0ob8bEXwiu3P2V;wDfxdZV5S3#gm7(S24Br*>v^Gx2Fp`}rn zkTA+!U=rCxSuSMmw~sNJsHdxFD#HWT$FD~01zv}$wX8Xf847<<9sAkr#Apn!3}h0h zipd)=dAQrAh@ui}>Zc@zWJ2r&=u@zy4c=ZY2QP<5eCmXIP0Ev1%vw!xnc^MElO8r# zG+nS;wKSIxM&gkj$XEjp^o+Xmx?j2v@GZ5Bh3FP^J-dUmk>~?rT|RnUTwW$;rV@&a zNpk&N80e{>pG?ZshIPJYF^S46q&nF9^cU|7NEgw{IYENpOUkJWQ@uLLu=IGPzk7b7 znRHvpDn>urS25+T+i`Tg2`|1)b2OWH`&~A2vO9SDq@#@0Tlp^hPMin)?*P7W5fmgL zrx5LmT)UyyBz5_mu?R}PR`<2YLInU-2i}`FGif8V|8rvfMKWt$5=dFlURRTgqVz)1 z4`}m!vxRP^vlqJ`ldhK#Gch^X_~|6qmpd^!Ba);8FTaFp`n7%$1?^^Dan&5qYS9IM z4mTa1Q#WB^#r0r4UN`Cz8={p6S5&WV9=$6ZHyW6N^*2dHd-Fg764Ymgb*M15KDj!O z079D6sS)7hr|`?4JN`#d*Q-XDf;!cgi)og6^8RoUa+f~H(VRar@k2-k!F|VMU7zT2qn#@ZWw#JDz|Cd@UxW~)uy}A_qY~=<2m*xENK2TvWyH2Y7YS$} zSz4ix^01%+M%nSY{WxRljO6ItIT5gnzZfa3%RH9r?K+6PM6JX{Qgek<#H$RK;&r9gLrGX_IHlF>{vpf5T@LYR+YyoVHhy(GX1n z{^*061Mv(+_zXgk0A$fAumS)oF4mD{*6dPAndS{oWj`MfKTy4vY#4aJmEWD@Vb-U; z%755A#rBoD9)KNp|0uqSd!@eLcpVsW?I`;OpQu-Z2?Y*&hag#nP>t}SGUzctS;ZiB zJuv$&4cr|LY_0hGBYAZmh6q9iaK{E(2r=_rk|w4XGcHDDte=q~Y!Olo-tvQ0ZZnD= z4KLuUD0we&oiFtb8S1}MhHz-52s+BMImwdby1Ur*F^z1GO{~y|@}MdY(b7(jeIinq z0a{hw{1Ee6n4!7LfMa*sgPtW1KSxx>40i^A?6*~_N1<2(!6j-duIE_-RwG1Hgs}FM zv3vXsB-=a{2fLQ?tR!Ap_mfo@$Q?1P8Ng0^XbQ??hxwi+6y008->E>8XNcDzX<*q#Z~zVqZGAd>$GXX8%M$1mFf)fQAY368!1KiDn~(a;{HyFo{bf0IAsK zqP&t14qHk!m@I1o+nlss8Md^L0m~^$J|aHxVh$lpqDJOhHp9zCB@UR`IvtH}0jK*F zU!n1OY2EAY;I);(c$651!5_lg9>gZE%yvSGlp=1B(~>9d#3I@8AY9Fp9wrq-b@~R( zHKOdU$*e#XH$fEgPG`H!FUwSYG!*!v!KcakGbD43L|n~gjCG-q=dHkmScGWxoCQ{~ zFLK_7PFO0kQv>xKD3k_;bY;vmCNNUy>JO;u1G<1eCMTMZyer}B6!DDOa`cjTEhtU} z)IE|9?Tn>|AA(_!H*#OShRQd}M(Jf$bW|yA53xV}*|uw-5G=D#LQxu<*W72=a!Vq*HFWW*0yH!e!`CJMy>1QTJ2Nin9zY zt1mIUPmbKZof)U^i86XGVRv1n2JhKy@f zvxm|`3aS-p;0)+X0@W)Sr1svLX)29NJVf{t1xk(?GdfCG6!Y@)BQi0ULdJ*wRky?% zRohi%Ke*Tf#4j{w%Xji=oZ3r9LRBs_tq{%&)-EMr)y{6xv*FrDn*Pbnv{~*t){c$Y z$*emwOCxk}5YI_^L&U17=>lKwv^hN$5{A{RD-R>={t%+}R0Ow?|3Red(9`0nNF04q z>QQ$oKSh~@sXE7Ec>5Rl5W`(kj9ApQ($BY2GZfYB^P)IuUQPGFTDnP}A|1L#P(Kzk zm8oxGZg1)V-c^?cvQmH<+rgee5Y}yqS2XIng|On<>A8lr^ylTDZYyX7;-^YI@aYAb z-2r4~#E_G*Up<%}9309`^MLsC(ZxAr&uxHzfjc7aPYU1p%iWm5`JQEe;-D;9Asi}D zKzD3*Od0R_T5D|4ASn3-P;t2|)p`*%@9oY5QEVw`>JWDTDj41|okq&e-~?Pl-Zs0( z5hGQIUj^(!JePz~b~%G2=*KQ9ck&TIB1x%a%mQ()aCa8>W1s}`?ea$tzXcju>|0%Gps)Mw2-x8GIj&6 zM4hFk;BnY8Rl%P2Z;mbPjx5A+2=^Sg@{3t+w5KeBVj^Eijz4AdJf-!%n=+g^FQfMht*@y9S7=w3@TsX{IxHV3BJ^3N8=-W(;V# zO#ZL-$2M1Pry03ZR(~n_+g9ztRj}l{^I5s^cz+jObU0|2ZN<1*1}>JsY#>0<7{BE^ zG+hT?s1l+nF*z8FvZ!={O+{iVc|JxAc>7atFhKvgi;1H@mF(&^s@0?U6zx;6AE4zI#mAWrNP*K~N zrsCq4J0%-$b$x*bc_{AtkpD+LN@=n1cl`R6K;{QC>4&~7DJup3cj#@RTl5_k)FrfV}s+|DX* zM%PcYPgg1qXd7*puM+F=QE7`*-5||3bi2SX{4r-W%++->;==(j`Bammz*>7^v4i$7X40pv z+^$#5u%nzuvI?z-^~ciqwwN_!rKi-(#pnree6(1?@pmGf?Q?B$F8p*DnZX9X_Q1#1 zb&8-qy4lcSZOzm_ch*UWd_Vl5)6sZ^R2Tws4oyGPJSXJao%edyMF-7j$BZ zp?sS-$%BWh24DDTs~i?=?E0?^$=gZyUJxWvPo@|Ckl-b%Kzl|kHaF(~V*LHY2B)zUGMZwlM;Mj>0I4)mXZIEhk zLh_Je`Cl^J8*!8@srmB+fcql2q2Pg20dr51C`-M;ha~l(?r{qX`8)MGW03@47+Jc< z;+O9RSSP}JwX)})cK92jH#WHIXt+NmiWqKBSKefI(M8KMQzf*u9ySWC(|(Q9cdIMI zbeQl@PxklX%^Z)@!Qzj?ideP|SI}k4Y-@5*{tPB%4jF{s^}f<^yMUMJd!!XNxM*zB zV5MoPlBIrkXPfrDZ%H}}Ly6^s`Xg57Xo-xx}@kW=r-k!gT;Kv?l+V*fG zOVYsV*i}(1EdIc=kCn9*^1ecT=;d@psOOpNEw!)5J}}EvbZVyzP;B!Xwi)5snDM83 zzxW3e29Dn^oIjt|%${}tB}ztfuZ>dsmVqI@(L>vGh|kJ`YQ?JTLU|Axq6OvePt!DY z20$79Go+=qa6G#kc7q+I3G$kVZV1vtNYpA7d0&g~sOe4bav>6uz+zV~TqH-3u1Fk4 zR2D`y52_HssS}}xmE?^ZpvoT360d_5fVMNYM9i&7AFz#!nE6kK?nl zi*dPGtTO=T9FBZHfGd@x=uQkqme&L} zyS?raT7m!!Qgv~!iZCFjQPR~nSr={i^IM|B)@%_|tk^<+4Pi(2mEvM>`Y*T z{!`sZ(Fh)@c#c>g$KcT=w{8G~!1=c_ZC1R;Ub}qbx1b>@`@+CGmLyYP7p`$SW{wE3 z?9s5PKaB0_ZGfo54*e%Auf>~DJrmUp)yLN=Zr{0vdZgxTR=_}(jG*n} z7D#tfZgH-)FC7iXo3!i9Kz*Yy1Am#;P*fam-e%lULrH3&P#khRj!ONkR+*;E5b@n} z^WQ3qBg=jyfw$<%4}Tujvn!XZbi%45*>;*4fwm6`JU;_9pVb@nD39%(aKob06E&eM zNRRsyVuI<>YZP<|7d#yIS0$sL`nM#>_kF(Xc6brk&~0;gTQ!s02TGBWK>#<@R&vH% zu0m?*XNu1=nlo&QGH8B8d#TtuKAkL>dDQ^pbT$^2n8=4hc%-Q?vWHUYQRHSYMjPz_ zEf3Cx2$eEG?bk|KFU}S?!NmR4TaM3-k)|S<-u;UuQ`^Lmc>b6(=l{g}aXFxKp0Fg< zyr;Ya&qdmGSBejWV$R(62K4Vpra(pn+Ri8)hj6IS3!U1A^Sg2t95xuVTCMTZ>q9bw zwE{xxcQZXd#b7Gyz?^zcznr}EJ?$FGprIwjw`#8q{cNq(uNSe5Xuu_hUEN3}YX7a|2%ww_TZ(R67&(<%q? z6d2RJAh+2yQh0dzkEqw#@N|rQEVRHT1p;~nW;tD#R_zgYhSoBzNZJsV^QsF9G|Bs! zB1QV&Y;1Q03ekRZfm+EY)8=-5JVBOW!d>vDOV%uSuP=87yEuF+V)~%HcQ5CK0Uk0I z9*#B7(Ie>baAO=s!r#H=uD1+!I#@zC4^OOwi#zF|=JqdZm(?2N20-xt<}vuBir_*5 z)SQ?};sDQ8US#Z~o9tnPOCv7vf@&Vw4ZwbrF|;@)ch&QKK9CZdkv>nqXNjpuIitm) z>ri8LBpb`Y4LmVm%d3i8CE`o{Ikvn4am_7Cl0a#L+^;_~amB}5oj&#cG4o-meY)sJ z3f%PNB&6dBHUt|y+eVr35 zDJVz}x&h%q52(1aVNt9F8DO@}GE^1ycuLk!)*^nZL|iQ>pX!>W0IEEs zUnCVl9PH|b|D>--2wi!v5UqUHyBbTtQ+CFtg4K&?WBI|JL1V@W_BSRg}WIhY)~tHBKe*Me@d-eHP@P4j$R|0-q&}5gU<*$P<=5%z(3p*o1M0)Fu}5aMK}rnb(+YMdmy^n3!$S9i zkSHF|R*jAkMuY{pG_9@8ZiPcUx=!K|yQv=wFwr=x{nS%Ci~mj&LWGv3A(ejy2^<@j zADX*((^HU&YlL{`W6V!r;14?*J==`n`DC7Dgfe||v}BIESR$H0h14uoA}R=@Es;0C0rf1@ z%Ad(-RWRg2NrGU7#IY#JS;GEUQ6US4YzMWlxr{`p8pPIF=P}dwdxr+nXI5qpz(Z{` zf4vlcTy0v4w?+#`cbGTjkQ0utVFnUuSUD2E$r%Aud9=e8FX-wkn$0m!cltXDds&(Y zwwFpT#S063{wzL|eom-3-EaGjS|LNrr2rm+KV4yZmnmmL;i)VhQl5T};2JhRiho?z za3O)bU)&(HD2tHpgR_D8)CICoU))KfV1b;fQ#olrXafIK9;D~k?s}3|Me%9-)LV2_SBoE*(OkgQSV6#M#j6tZ^9=W&X78wvLNq8p190)j*JTk!P1Fh`m zi^<}#K6iPP5S%azWbN;jhmW9H#0#ufnd+Dd#QN0;gE3|+TTEkQcs5{gF~23 zuH%a5o*FVobV-T}n9In%4-@?!&S&W@;-N0lrdkm5>5rg>vi2bFp38V_96$1Cb%a-2 z7f2zibHp|Ajxz(8PWLEhGm;rmu;U#c&QlJlqVE=&v);;Qh)THzYMDHi6FJwQygTs= zn+G(pqn{nT3a4V8-7xB@*SBAmzRL@)0;A#s`jL}Rhhq5JIu+RC{^obGi9_I>Fa&xc ztwX;aX!}%3elc!BVGVrY#}Tzlk{}-Xk#jKrOhvLUvA`mc2gMTYmkWrA`Za?-OMZet!Jt}pEn1$99bks+ie3vO^O z4XW!hkYi%0n}{bly0}e%7~5J>n_p?L5!I%9tK-+-OSoT1hF7J*RKmbO5Q=nox8eD! za?5@w%Jn1#{Q7T*X`Q784hfOZEi&&}H3?sYMpq=&>b{o`S3Xy)5Q*2w-k3b1(i&;3 z5w|rczG7m&c@Hc2O+h>M9c^U8pze=vU?F*$QL@nY%O4V0v|Xj4~-= zEjK)&g3skm`)8Nh>K{R%-!`%q3FAPafKUu!h=3*fSiy02KWiV*?g^MM(d#v{ z*=4MX@*9=Z)&GKmNr48tO(&qg!#}-%&C{KhfPcs;vzNevi(i} zZvc7Q{)4NQy6NLa6h7yfm`?RDO(bOzw0{PtfnOCg+`Kjq4!fCC84oL|P)YN02|5Y( zhY4UcNTsD5FO{&%>fs`_KH5ej32mkj$*n^sN++G1jrhGNikOXkH^mi=Yot$RsjJv! zaHWUk<9FSX*}uqN(7gHy!>SWH@aU;{t4(cPjU%dcwa|m*&~AHjxo$LPF(k1RD($Dn~rr! z@bpqF$LjD8xnfPuPp!!z5%RUhg5&?o+fv`5MI(RlmS@ai9y2W4n?;v`&s?~5M5XK0 zO4YG;EI0LW{o3RhuP1(|l8iL~;Y6QaatM;KXyCnVW}a$R=oJe-4CZDCv&DuWgS+Pz z)3>P7)94kS!GxobTw9qxg_jljJXdJTh*;2PTiBvWs(PoPH@~Th#GN7 zgHh;)Ea__%YGc8yXja{U);Yt9f$>iuLwiR~fZ8=x;_EjaCCgM62b00JMb%k-Vl#|p zfIFq_4e|_z9OXkHUJpc1Pr2vOFgqQtj5I6iKJi-ER6&jyeD^PFn%n7K@Fj5v_P8$4 zTP0zZ<4woVuXTQF)|j&Mo?w)6ub{N`!HgNhH>D{8#P7Dyy3|LQK-N5Q{>iX~oOl=A zj|7}qB;4E?&sa)?Cf~7{{f|&k>;Ml1Z@YdvL_?Et+NK>eklNyio2I8ssNC`YWKJQ> zPO3=^>$!&J@In=fz1x5v28TK14=s6e{6SfZ6Q1vm21NAT3DFIZ9h zR(xs;TipkSA!5L*I|3o6`S4^||4iZVY$U=VV7CrGVUgr-Q|vdfQ#t?Z?sq`(gQ2vY z!3@Sg8>)eAdaQX8q#9aF!gX1cI7>x!U#-Cl!)(s+zNcS;|Ngyl?E~q z^Qx(wQQQ)CuRyUtETY-&I{c{YCI6gO-CS2@nB>IQ33bKL(l{iD=hC@Gc7?t29cAxd z%j-{%L{l@=oHXFk%NlrRc&=xP6tjl`Fflool5m?UFr?FtKv+QR4_?|#bmyEoPU*LZ z!#AI_G8$es2Sl!kK634t-z>3_NIudS;+S*&i?{I;tR=v9WX=C|-G7l_gP@SPeVJFm zEu2_%TXU z>Tz^1As|vgBN)M;aqn&0!BuymeW4x8fxn3B!QopEVDa;a%Gk_6(O5~cSRgS1HC6y# zv8K-5b2Rq?6CR9~;fXr9M()1bj2P`4m8echS{$nP=0W%{m%R=%{r(R(#4W@Z zn2*>!eTcK#U4?Z}QL9C;a;_G4SkW1mw#Ad+D*Az$(#q<#=JAyf+C@MK&I*1j_H6L!VLztZvVRn(xil>@Wjvaz`qP=Aoj#~Jtstmp1^qWTS;$v%N#E#?uq7!R zCYUTr2QJUyH7M(<+ML$LSvsr)v&dp{f!Ln{Csyz%#RcImv@0OZM&iBcxUS+^Dav=q8pv8F zdwen7CGh7-^ouB4T4n5Il*I9X-UeAx`4bE4GA<672I(Cv)+0g2c0Gax`+T1OInH7H zt1tnxlCcG7n6<|$=ecJw067;(y&2`1=tDYw>bZ^Wo(>09Op}!N$qYwhO0pfE3b_QF z#|MHabq%7)=fG44PKW!W&T<@fm&Xz&od%Wa+~m zok`zxSsl^Lf4$;rR$y++3OBMYN!&=|{p&>azFD?0S%&jKH;92ZP4?c6wf2J(D_rEY z?ykplyJ$v1q=aaVjDH3VV`kZUxvBCaI>+Dpp+2*WgC8s1HAFqm7M~~zNl_WKaeVj> zW4;0$`heRaS+Q=Y{G1#qSTetEG+aszkxW2~lx5|F-K#d3Pf+2jCQS0$P8t$TdI2~& z^uK7_2L!(8aaoQ6&V3VM;R7a@izfbI2EIevtcreKVW*J15cD`gjt9&j{65jeDr4>X zK5g?TpMMHZGbe7CZAh*-ImwhsA|IA121QZ ze**m1U%kI(o3AipX}}rzJNvP9U+nK*?E(JzwW7O4H6%Mb15Cmc1JWux12}58?nG=^ zfKdVg#(8yXXEIu9>gJ?^4Pvk&v+7{KOI*)Wb$9>a@7|yBf~h6RQ2`%TRL~yralt3K znbkY1Bm1d?wt->#RW!~NG2za|EM^N_g$%=4I8zR9Q(FMw1CpfKafaDR&@&qY(okF* zVW2JFc~qi4)or#c-gthZ0-7w_?mV8$%+RGbaqyMZtyS?~cV?vvxT<>CyXTGxZ%xkd zS)g>acq6%Vc_u%6*qOn!S1v$g^HLiqzUS}1fV1-W+3sW*e*)olmQM1l9+`1rorp6= zR-M_TE@Ye>MnU%hdTc^#95BJkYLd7=d>5M2(QCwQ7s^|YA-l}a_wlE`PF`c~^HyOj zBC+@}A88xCe&=!4vsy=u7H~yr^C)Q~^QW1V=GIr_c!}1Z);k=yBt{|rm%*BNoj27A zK_|5Jb7o$7t`B&ZuE*~^CzGY!=R`!K_|7;3%R(c}e362Ltl9^k&w?L{|CRN$j!+0i z>(^q8Z0Ey->D7MWkYYJ43QwuPjkQi}z2aI`m{R12<61B-BW zVpUpRf#D>T7u{V)PK6))cvf1}$b%O)4+=*DE;f_DDca)MuN4O1W zM~*X7&BH)y+(+rSXhXK$9FsSWlgOWrb$k+E?H(1tctGkyX)Co(r;-IKdBcMoXQ4|V z0PIF%Ix92NvkQg6%%1)QHG~zjls;YxYs^3GV9&q?K&|~&B`DHup z6BbmBIGYl|{AE?LI%Kc2Z>i*Ppf()TbU7u!KLamOz^8rk;l!Fj0*xKG9^uW0RM+Cs zSZ-B>*z7( z65&62V*mxBl#|ePeS@M54;ehA@k?)CNzJ&%;J0g*Xed9uQQk`sfEuM0EuCv<9lxQm z(S(9W`5rvbV_>q)qzpy95b;_U<>a6;SYS^0jp3tCS}5+vTO6^>fDPB;%UXM9LnJv= z*k!{m8BhxDZkF26ZzE^0`NhQU?r82Pi5QrE-&+}HDf;~Kc<}XqctScN!$Dy_AZr@X zq_L~FUg}pSJLIBvQtN2(C$+E|r>?0$sUzt~Hx)g|a%mn~D_8H?n9d^d%={K0a08#! zUeJ1$yfbvCHSeCYsK?YrqWBT-v1dET?qrN3-7sQH4X0*jJ6jpf0Kd$IoM}aI!l1Zp zoiC(9grF{A!ZnFQsj_x>Q-RcI}Yn)PSChQ^( z%Q95>cZ)U^&Re?c_-088q+)wQO(GpgL(`eE;k;>C-H>!9&HtTcCG4L+fKj5?|F%Bm z^~|WV10ul5jH;JDa`*;kzlFkBgpepudbEU^jzsK9du>vvTEUQ#$A{S6_*S$6E*%Qqy%oJVbv5SjPg~^N>=s7Wh;V_fd!joI>d5#qYTf8c z8?LGwdL7&j`|{&xEh z;qyeWc5*NZ?C>D!c^rL;k=~Rbe_63Hq;k%`aIqrTzE~HIWV}|n*SM2FLF1kiS~Qfu ztNHQr?GHj4jVaerBfq1!Uhs!EEL%FDYF99n3>6WYMffne)4OX+)^g^!tc+K4&ZnLn zn9~l2ogef681b>Mf^<86X8DdN_aGYX=j;u2FY5>Mc+MXh#$I$*sVlh&%{;&l-Hr}vqjo--)RXb&3evc`Of6w6agETlNKVdSdWv!M@2$1}m*a>~W z+IUU@#S7}HRbWI^brvyfaphh@aZZ#d5_*aOmi@>x8ve}KeW=xzb;P*z6?O~C5@ za^f*HkfN#P2A0nx()P+qLBcpx^iPVaw4w}*Xot(yk{?r1QK?_ogiP zE#qQPmhb1bC0_$osCAASv#`GvUOqohu(G+9(dkb09SJcw5ZS?+Yga#3Keb=DednzD z8EiD9jOUcI@(SfnzKS48G$P}s$>H*!{onIj^Egh-hkRqoH3Zdj^r0s`_qo08u3_!{ zvipAHsKZznXw|;CVS;`HWMJ=aX5Q2~{J)#Tdhqz>O44Q*V=By6e?-fB2)(Wxv}O)l z4K7<`wI(}ECkJw{1KFHzWU% zBkl8v@{F_-YQ;%z%q(j%q1f%#Y4Ht7oZz}Lv}x|?rMA{}*4bu*s`Nmr9U8tJ9uoQ# zQI@py=j&d=`urjY)!U|ZQ}i#WitDuYDlm-2znMGm6qQ9duv3Jj>?&p_OdzOvfy!>^ z3llXd_)_jW2Pv3Y__$#1reoxXwos$}GGUIV&H$3d39^mPy^bi~V5m_tlQg6M)Z2V3 zXQ3>qb=VWT^29&*3jDlqSRMlQQIU+yW4+ziyot~{L?<@ai$=u7UPiN zfbd?okM-@YXV|dldS7@5xEaV;2`L1*R~CyUEQk$otN(c$!if*{cB;hMG3*fvXgJIK zf{5kK?QXK^Kend#pwi79ym!{lvEvjhAtF%E#pBj2^z!zz-82j!2P3710`_P}J^Qyz zD1~;{F3l@W0^e|eM+Xy{$8|_Xtu(N|nIS{fOn$cf=K|OP;9dI)XWRKt_-EEydS1;4 z&uLDljsMi`NC)X~dlckxWH9Hm`ZZz)9zv~AEI!ae9A}T=BQ}=l&9!wbXdF0_8@h-{ zM4X)cod0{K*L0^=O&qsZvy1Yj{M#^CCDDOC^@5`EhC%60*Ernt34Hg++1U}~plZ)3 z1pvr1@|HyF32L{)O#+w=9g$^1*lSE@PXD}?vFtA|^+8>5s2P>Adrp7U7*}(JqOXx= zt(sfZXcM;4-hH^Mj43yh=&^7|#r`NaL{AnBDpuJM>bRczU{*mZCZcZ){-3J3YC%)S z!wOWw$?BdG!(7+oB(9c(+tJ6*V4;U-=$mo(IUZQ=$m`Vb-|Fcwxp}QeMv2ZMZ@oK> zH%?^1(b}(0`LXq8u7VK;FV{WD_G%iXfgXSSGv#nLc4}WC)?SnJ5-pE7jGn6cKbco6{yk`I4>va!@K(^UZVKHno{Kx&K4u4UGlH9 zMaXq(J@2`XwaJn-&6IYRiag9(K4zZl$qqdIY-BS}Rb`tC1XnyLPZ#7Oaq&R9C|;cD z9GKiyvB zE|@?MPG)o$Bd#Q^o^bdER*UN6AiMg(L99P0w)XA>-R;nz9>)0Y2QXpYm2$+=(;FZM z9enyXNz1UKW~~O7*K{UkNL4TV&~O)#g1a8>KX^3VL` z8k(p#aW7`*Q3nozU|8~H<~8hkub-j1ps_%Xxaf|!u6mrU1>~Z}R|ZpQQ(pdEVAmPw z>S}o|v&;H=aHUaODrrx#Es^{i1Zu{E*?#oe4Fy!8DP|3-9)afa3w-M2BuEvxHOkm&>r#6qIwUm_fmkr5 zQ29~%XMMF(2*6vT!|GQ~Rp8R>;P<4A-;@s?7SImlQA@qiSPa9{? zh?VxG&U%$Iti+UVB^MCZo#hNP&Ytg`m-=fFw}Y138}lPdnS+ni07JD)XOe37Qy#k4 z+bj`?EjlywcrHv{tmFvW#W%PMtb$&(+?6SP}zzc7+xF){Yyi&8{mgzR$>#&L;# zgv3w|l0Pb@PL`YpEXT|aS_yESv_}~wYm+xRh-+;e&KDCx;k6WbdEyD=KvUqQ#?ttu zQJ~DJ<+%)_@z}Jv%X3-H2nzJ^z;zhy2{2 zn7)C`t^v|__u~%5(@p-Zq(mNa``qxfOy3!qUz|kKriWrci_vso(vM>G%9NyR2H0b? zop>Qco%vR#aX*YiNka`(!jt7R=O_its9R8>QP!(!MKbgY6XY-uR-GZZ!ukomTybXBaE7*Zdx^&S^8@#}Sf#UG%$Y)|*|&!2gx<^_|UT7G@B(0$uy%jpw} zw2>|8WXV=sNfMuI4tu7VyQ@Fj518j6$^Ue6JraEcsQjgL&Es_nQ$s8b)f5|E?=ddN zZ#vEpk_7`ssoaLo9OS5-|1e$EBZte9)$Gs-4S$Y&ulp>ixaHwF;g!a7c6Hc z%~?*IOO;!^8WHUlY=^JdNnxvOr}NYsNk>7=^Av78)c5f^gwr*pS>yF)Gf&ggbj0&Y z@<7bE(S&$_`u)=GDfICjG$YmEJ35A8iI0)0<8>BdD(@9z)_soGA*S6+_9;g=8S3+{ zLs<-*q=pajE`T*^Xynh8?9VY1edinkIeK-*ABaB9Z8Y6qRImZJ&2rz*TZw>;svS06gW9MG$uNFDgyS>T!(fRt$n$C-soDFRQSbs7b@ zLHu{Z+({4*xoIhfYZCsyUlI&z{qV+>%|u7*Q4HRED%$cMz1m*kr33vp2jNNn@!5D# zj2Cp`%O!KQlX#NL-xjxr!zXrwUtkiEjrA5EHIcdii9;Q9hbiNyzmu;2mPgFASp2_L z9?d_ZVx?PncteZ8vO1GdXZWh^*uS+NK%EKC8x0mL>G`t)CM)7aFSp=DN$rfZf=uP% zsZ*TKfFl%sDIgM|oBTP~U2U~|Lj5sDEjIX%f;PFDHlF}HK*Yapri}Di%xGD^mS*jY z7TI`>()2@u3CvRviP&U7kJp_`bnVdUjMW;d)HdDW|_zx~hWsg}7K!CdPXlUuNbYk-Jq0qfwOF4lO{qX?#bfH1hky)XX6H0@szMC|CR$qS=(J^L#&g&1&v}E<}%_O z-pjJ;D`+#}kQ1<#t0kXiw>}Tb*=YjGa*S4gRk~DlyhlZel%wVXz5ti1tiby8Qo_a#fmDz&+3Zc@soR`r9N#08*E^S12$^$gRc}Q-E<8Q(1X7 ziH+d4FTIScMwm9IL88ZtJ8o_bfw))^B7_aJx+D-sQ?MyZQ6Bnl$M89e>6xGCV;iXo zISN#kV})KT4rX^Hcy;G6kf_U>8*t?q-4Apj{m|>0Azy{XN%%Z%w(8p~A1r{U@-(Bh zzuf=;0Ia_jGr3rRQnzxz;9WOQ;0E)M-!EPzgh>dLOG7phV{%EsO~`6rStzgSx*rah z1N#Sngc~PY+9^NA{&OFrlKs4|Ahrt?xI{EJm(^AT1RvsdAI7xcAk{r54swEdVG1F9Ds644M)2@_Y#^ zS4JS94s6}XXu_@vJi13|H!z{P;D0M``VuX!&cSTTYi3axlpr*;&Da#rQjwqbASU;7 zF|G$?S^eJ#=d>~DZ<&~hLFR+Z=%qsDZ0_J>!&!rYo7_D8Tx-zN4m!6s{T_q&qI9&@ zJT0~lOnsauou|L^+1;wfyph8je!(r6%`^(sf+R#rvhUhIRj5SgODg0`driXe#WeJwB zY<{>`_d1#npne;L>DWl18iK`$)(~U)VEh&pu>pg{J>rA@#(oS)NCG7)I-;;-Uj6T0 zO)|q{+p094sD&vyGB#};MH4$fYX5?Sgbr!79b~pg9It>2 zy%wym8E3c??_DH#Vx&0v^c@BL=P|5w99O~*U>x>OsgXPJMLk$|v=7-!%`|%h0%j54 zseZRgL*YGU>cf*kGzBou=Fl2~;QSZn>6!>37&iF>G)mcc1$$90!DZJ^J)r#vLa(g~ zM4b?v?ESM~7=U3h5xnVl61O^TAfnt&6-`95x}r#y4QS zkdERWmgO-F@~jC#FzXQkNhegNF{mm6Yto-i{mgTi?ca(YlYj+z&ZiL|YRCN6Tk)UL zrLB%?RP~&s13hm5PVubNCw!~n#ZFHNEaex89tjE`;!-X@vCf*t!I3g0?gh(2nC6Bz zT9_Vs_OxW!#HaCW&u3jg85XTZd&FK>Xx&cCbe@CzKe}Ch>h;}lCQ>v#R=tVP{W|Ha77*fwqfG7cKgS zoC;fAQjyJ3vq|-rg&o!DKVSbtj#h8D^~!D+O6gDWOJPVOE*0KGWtC}7V$$b%$Enh^ zif#X7!KM|UJx;&LrWnLB%5f#T4nl87LF-)(2ktMTiw|LXo2NMcsftSjJTjcR5a3>2 zU)j2AJG@LkOg)^M_bKe*ema@qjw=L`yS0JPjk@Kft*OXQryCW_7=y1%hD^N?f~nP1 z?VnKpZnaGv1Aq`U=ZCFRv4fgP9a3xTQwnz{m)qp=6sdJ)Y9LZGz+*1_V7}sy-A`MQ3YgYXAoX^n}n}&~u zLTU1GI0sG6bI1%9LlHD1;()%Cb4B2A09l0zipk(pVgSGOxLw6OOMq0PVBEZ$DGX6m zEcMfXchEa+HUR!_@h?*P|DC7sx7uqBr7!wtmcW{nUuj@pzDVVi>F%twTIMUiecupP zf@WuHNYU~N!@8qz@LX4u!8@7Yu~7qIgueW+Hh=ObCZKIGLbN>H(Z{A+jMwbe540wq zLQ2z}Axbo6GHuoAd-=Gmg~O*< zf(80GvLh{h^5M_Eq-liFiFRVO>Si@EtyeSknX*HHnpGlzyY!Dr9A9@@nY!S538kqt z`AeZ4L6hYQ%3>NDt0NaWmd~G1a zs^JQB)=^FED}X=E7nMFUnHZ9W?Jx!lZtum|ifX0x$mWIOA`sD@v zj9IXvKx`~R5_c_vdHK>|@3?%M%!u^i44qVt@%ZduU6>w@X9`3m`q4rp1n!d021{`& zVgHIst9I(K*ha+M^T9fPHm{=#UmRltvCpElr)n7qzxKqlcA!6+Jwd5Rm41dLN&F;7 zEITQ&c*eLRRUh*h{hB5g|DD(kPdh<0MXS%BxcADOf^zY2nsa&LI|kEyyChQsy~xYn zZ+zHzDJSlZvE>~yLp^0y5}i+|9haISa!Q~$@wVS;*JhP~g}~IMsDg6#HMe%d0F zJimWo^k2j4OD2|r_7rA8$DERd!{-vNM>!+?qV~uoJ&G)3#g@9T975WsJT-x)sEo|hP-CdMQ}j1)W$(Z?G)E}c zZ<{P2jk#8Gc3N}@9L#XAA}+~gV=28yf^7DmWLBk-SXqP*A10OCP27O+W7h1GFX@5{ z88m+hFI}Z%RjT2v>WL}_&k^cpfXem7&DEf11-m7nwKJ6<14AHnQkCwsKoJO>K|19$ z1}GSr5Zf*1gTHH#w=#@G`VGOGg#@JB*zd6>lEp%hDNIAvUKg~H%?f_GlQXb~jjR7U zW^-tBMv>(nc&!cYa)1v+{i+B=2i9m@{=lG{SOV-*YmHMim-Py>73pbfVPdH@;3|_q za_m)>vgc(V*EZ}9`D}i{qVM+MnjhT0(0tg{a-)5uQv6?1W@3rg9he`BbSsJvr1dPf zSU+3I0WtJ8s`zvBic%Y(&^y=e`}CU0!t>a;R~!g_q>-6pYzpjKSj%3s3M`vki&NCT zz`Kk0tPJNuqfBS#5ya_H`joIByt=$=2IH^lF#A^ycf*6!eV(vU$)@eGCyAsC)0X{N6wQWp(}PR{q~* z9&g+(qk-V-r!4%KVaC7(>-4dfvTByfb4=_T$*6byaw&21W9p43xSdIik!$FZy!294 zPJATZnyOEf*55l~K5OV|^^Cl9_ilyKkv{&J#jd(t^D386#MeV_qavFQp%S#Ur(#CK z$H5N_)26#IlZ9go$sOqN%D~)p^PK-h_f|uv%Cg2^vQecXB{7$9!qd)a6NkD4Mtfkzm>t z&K18sCbPx6w4D9vq5WA0*ash)T>l*RyjOm=wqTpKDKRy~!%FOed|gQPY9C@-gBNpM zbPaT#YnsI+LFU6!|3`@%zJ-7mcy42|7us$4dFz@FRfCkjuuo(lfUF+{16K#AY;;-Z zyoyCMZ%l3Ig>kipc5*(Lyxkf1^nsJNfs=DUc1Ypmw@?wDU6Pd$1*!J{4>3Tq_r_a1 zwANvfK&cHPmy~~&Zb%sycS>Z=^aLUu$Gpe{MBQPH+%wacr4-BHv?Ou)xh3v!tq9E@ z#nF{v*MYV845xio=io{2i$Yht_meHP;m2H8+zc@;8)L{8Mak4t)H>IVHNN#9#pg@^ z@DnYr3}O?=Ld}s~?laa0+*ICrQ`qiFu4p2%n67Fns1jeY)r1hz;I3i6FlnFDEHNg~ zj4?oN{ydw+f|)wp#VY`nN5~KB>zf$Qp6=s=bMv}7nlo_=X#G7c?))=8Z5RuBqgj<) zXN>L5QRawtR_&sn`|8Tv%q)M|!o9_XI&IXqGcW>st-e;MW8&Ls#LiFC{T=g~1j-}D zxfzS?`x^9=&~H&MOX9ktGGp8KPuH;cAP?sa2d++1gZiF)o)G<=@ak&3PDjsHJb;lKDemHHW3P`zX&^f)u@ zMqQcKHzyjlz#-PB1FpOtu7O6qw7H0!Xhv?X2E>XGOz+r?EYV{sz5_J@l&a3Ty|$$A zH6V&|!D-jZtExUdY{54W;P2sUE^nBUMeS z^V2KJ*S9qNzx5)^B0*A#YiPtgP43(`-QU`GXJ!9Yq%`OF9&Z*^w#pc-UWD25;$df` zXwUhB+O`u6|A$bX%pnlKqP_o-prKZIr!E<9pnI+f zMmVcKH@1lA4E3j9+)I-~53eS_V2s1tV2`8A0W3!fRb;zLO5y-{V1onHVGn z-?hX%a;gs@WN4#hY$&e=IL>K7mmYD&TOVZ?3fPs~;VUc9{x)IRgQL7KyiRa)o)lrP z_km#KOQ@Snui_wQTQ8YC<;jb>r?XS)W>@Zkj^2A(+88UIB8$Q3p@)tf$BEFHW*QFh zimoJaaTnJYI$-0GCN|yzs^3I;xm8~3KF!b{oHZ9bx7KPU1&y}_ zc-C>BlhPR$ChdJ-$|g#n}dn1^sppV_ES6 z`vVClkpSe$+CdD3j@m}@)&}WmQe11${1~rL#aFXiF}?S<+{&FWQSiT^uw4Yh=L$H*&C*FB9$YtsmXVrz0|W%-qm+8wOt`P8Iz&l8u^ zIFp?BoxKHE8(<>9+=jon5X%W>G#+elQ2p@-(Jfo7tC%2GV@XTP zev+Jd(7*|_=DjG2efKptz=4Ord6EOm=C?;bh84XhvkW!A?gZLzdH;MA@bKMT=jEj@ zmLU7A?sju$W^huoAI2Y5>{IQ~N!P&aun0Dxa450yO6*r5H~&Nc(n{Av?29X@Mq-dt zox#=hu@HS$#98`cGBh%_#j`-Irnau6-Q_WF=lsio?lkVgHW$}@Re~7s*HqnEDKO^F zrB}C5Ov#r`?KIckRJ;o^spKySi8v1smfP=Bn)*Fo;>by6#VGSj07JZsm0!o?Xh-$+ zF@*HU$&na#2nBYBM)MkIyXSOKne%@R6k^ElD@*qIH!kQN;KoSZdh=>`x)ix`9oi4D zy4P4oah!<|a?`)pFK$_9?+;guV7zm@_*2J3DHwGm>g)(x>5w-Z>~_5IqL}-HAtoaO zJ`$&1T|4^jczt~G;0%1!EC^dNL$1@lia_kC8{2_q`AXQ@fd#z$sOZTyqAGa~m@t_% zo5(8skku<=hLi)ihkwVY;7X!v@Q^|D7CgJIb13bCKN<@xi_8q7U{r|TYLgyRiUFbf z(C4Cv1f3dt?7j`|S72H8OKP%J9Ajb0KpRoDZblp;T*EL7Mz&y!HS|zji?kP~?#2!6 z5yyrk;OKPb_sd(di8p@MPyajnh|#Ex23tMWAlS3q)}v&-PasV{hAi=DnCOx1b7q_Ju7c%b-p7%;Lfr4gjOYbak&Zs06{zMqU4CeJvf18ogoP#ym<9W?63J%injmfwf+cEm|;b+BrYE z()Fy

F{tt=&UjX3cfi9D(E^!-zaw0?kp2z9C|}F+WMqp(C}Lh-%g#B}!lKtMVxw z{A91fLOs`$pKkjmyF1t_xcOwl%UrP5JTrK_xGn&E&A!J;?l^LP$QHr2(^b)~PH5;n z!fK-zFuY-j(9v`Aq#L=h4DCht7z*5QZw^GZi-Tof;Vz|8OYMI{;Tr0f{#HZ*84xI| zl~v%tw2{4`c8PcDd4T$P@FcfZuGB-$ zmgKJX6^qPeNc0nkOFh0xHY0!P0abL@|FD~xv-5z}{`1Vy{vcBa_EHGa%RY2DyIxck z(Y~DUrOGh6DBv&->!n71WLDF4_vyVKs;}7Zaprl#R)2tf7GDL$IiGa9hbdXRT!67+5l;p5R_fvV{0Vj_9y+<38gEYqU^mm-d6DW=&*iLwpW7ejaExX5lH*dB3Zl#gRT7qD6Gm2%7%U-z1;vjYF2oaQ226Y<{Km`Mwc6K1tsdR&H= z4aM6)l$>qhKyPOKtTaP3BCN=k&uaLB3&}hYWbvcV%d%ls6_ICo1jKtPNJY;?Ej+`l zx*0Q(QHj6vPLr!)wmXDn`b89B%ZTeJIU_Pk1Z{nvxM+Xjf=XjJjaS8ohH1l_B`*B< zAW$UhRdN(a|Nf8ICuEWTD)doFioaz-el!ZU1@H zDXktK0C32Gb=k39?D-U}fBv|yU&+)eM?9e%1#=vUvUsRLST4-G&`=5F*}ZkL>*)tb zAS{v{G9j7@a30A&3*SVTeS95z;)es7BzcI;bq@R1S@HG?u+7%eK2u}&M5r-u zQHfFYa}tqnGItFUBA>g&cCy@JqLq$?XZH;~zcz)HL|uFR94vvfT9aOeB@+21V!;i4#Tzl%-|DebU-v=xtvy)!B( zAQU{yU4KI}XzwtsUzGfe3F#m8Eqj-r!s%ZcT12-DGK}jLNNM_-+Wq$(+a;f2#9E@* z&}uuq>pAp-^YdHrD?mV2RbG*n7=G#_I=baNv2L_x&fMKYX^l5 zPGh;LE>9^E2izk2J+`Ff7HF{*@?+}dI@!gm(Wri4u523>2fdHI*%`9Hm{Rc{a zm@a|Hjhk&F;=Fv3-5}CLv;;d8yntbcX?qO;lnIUEAJV*nRIA_!6Q%n}#r#BmW%2YQ^9^ahnrn2DP5Y7^16_Zbjoe=%Xb>wNth1gdM{Bl-I15`$m9g6qriJ^ccDN* z#!n~*R6ISL>~D(2lAB1rfl`gBNjTBOu*+zBFtSqk?T=Z;V!m@XGHf$0X};`aVpUjp zg`RTxil|nP0FB;sDR?2qcrK3m`Yt$|hF(fSFAv1@`O#%T;4>I-4pGIy12_?kh-~$f zZUD{89-YtYWoVaIY&;T#2v+O2`x=>v&&j4m3r+pgMqob&oY}b;SPvaqZ0kx_iv&jk zH{}M6oCXwoBXH7r)MHI7{}SAL%7iD_IfD`&TsU)4%j|(!fTz8hrIxB6+?1qDTE6v{ zVK&GPMF0lb)C=q~8CIVOiqa&R|D?mdj`8j4ee! z;vfU(W?$U6SoX`r8q|l}%JTiNo6hhL7QzuKJm0mzw`jmU3ID_R0z&ha{Tf9#;oKpn zA3<#}>L5PKR7)JO02UZmDq#?m2Od`2mcU48nuxnM$T!Mm3-swGWC(2D9An0VvXQ+H zIRBpC{zj@yb^yD{xYU~o4iNZP15Xp;y4hKBHcGPEd^hzSkmgGg`@9b5ADgJet^m70 zL1&Cq(SdqAJFFbZcGlq`{JwGMt^-SG;l4fajb%inGX0hF-9?}8sq+7~9!2xa9ohP7 z7Y*aU2Q(6_EpR!AMgp-P)aQ^M<}Bc``cYKMV(;+vO2se8DJAlD9rM1g?eYwbvAEU{ zppIAgZbqxSjHNvj1WXiygbmto$U(h2rAH^!)-}Q32-^>eSPSQS{Y}w@P6g#m?z5{6 zpxHQBIG`^r4;|UsX%-sjYJr2K;i&*CLeUIIaqdKe782Fm>Ab2sF%0HAh7M+=zGy=y z`|Dt;dzR!kh=U^hNyjmxhRU1gl514zUTTG6@2C`AG&e8l|3;F30sCWXN6HTTRwtc# zb^LLz9hk{`tJaJd()(?m%r+-AUHa`0b|8>9KhsR!12wy02=GjVj6Jpm>yw}=*Ax>| znU1^6dn$qu3L@v-M#8GwyTo;STHa3e)HNe3Lb8JaG)KDmKS^$`?IpY_TsAHa*jE1 z`8pe|0l%O?&UH>i_%DHD?v0^(+tC+=YP#VQN^B|ajbgi89Zbck4M65)g|_3_33DYz z9odN#Ab}OiIn|nNv~RBkH=O`#{sOcHJcR8>#e*)09qdi^VAsu2&~f?iO}A6ibj#kB z#9Sy3nKlZHyjJ| z#WLUw`oc7eK}*fiLJF&L3sq4YigNwV9+^C=r1`fLylO zp@HBRXFt&{AyeG~+3S~8voReq>*(7KrI`r)yUvLJE!V7?vhfs%A10FH1?ZD^;X&ij zKhoabp$skXAy_R2P20FRP(=OgY!DN%2oeq?^Yq&u;(Zboz&dfOrV3&tMc9dWPfcHW zs#{a2rUMZ#moB0ITJZvyc)*z;AlRcyZM6HpV}b}L)~VV@Xd9LWshR8l;@h(Bb*SPD-g&wmLqC(j7LxM~?RZ4@NsFKpVoi z)LTaymj)tD;OI@qVy>NzA`V4ad&cKu7YNTiE6~9vQ$GY{6%4YGOPO)!Suy{2JGEqN zwhev8OX8z;Gg$y{J|}kotcHak8qxx7$?w&hgOzU|wFn-u$4wyVL%~f~D5(w~iVVCX z!4}c^+i;qf2>u)U39J&wEV9C0ECyUP!l}z=uIV*4msSXp?jB3D9hCU9WzBa`;MAS! z*w|<$w)*$dq|zLBcJcsfD8E{kXU<}?FC<7E!xBHB@B(3%3>1Ns=|cJea3mMv3c;Gj0ZA2|X0Mq;{;&DHp6{0jjs^=w8qV9uB%+LYmU1a~a0*rw3?WQH<_hXZY1E-V+m*GPrSD|vBvjc%_W^rX$k3y5MaQzvHJ?g0 zt=ECWErNtjQAa9E)bjf_|ILWH$$KuP4>;1HT#ya9SmZfn+i{~M09L}>g`6uJ;}iu3+O0=kd#gE;-R6V=e z@Ab~0lOR1I`u9ttX)X+s=SMY=SVj@{O^)@?>+W|*y(Dmc5Tb-RtsI!uLcAUQNY3-_ zRzM!0_y9=Djo%-d&Sivlh-C?4v+n0Y)sh#)1LM>V|E#8MPaIV%=n`JIxfzxj9X|F^ z>s|T~L5*fsuMupU+2R>63zUi{TvOkf=lMvWGvzwRfraMiVUu#^;#IQECX6~g-L#U? z9{mu`f*w&jgvmwOpMWv<0~(bRqGSo;nSYN-*;kGbk&MRMznt-$zCrz9MqIY{o|E)g zt&0_<*xi{8c{G%@O}o*)Cqa5JrzpVqT*pyV4kuUw45JQhRmMnh96JT~oXL7t7++G} zIemimr>{pN7bZ$lX1mQ$KG5!V+C&BCr zDVlmxhhrxxm4g0W0S`Qyh=nbU@srdW)Sgu#d2&Q*gK~(Fu@J9VJ#`^sUb#s2_ZM`^ zdW)QI;X-P8&iwxoDcen5qH)Qn(fH|wzB00sb*);~OR6R*c6t$uZ&L&~=>a~UL3)UbGi0jhm^H9nK?4Kbw#ZRH zq9OHRt!W7h5XmJS>tq@7A4@0F6)1`D6+B#tbsEz!33VnarjpYAPzS39jE#lEb+(TO zdYpYfj^>|QHdOqE2^+dpd}uG zfl5>L@9wane&?|_b7J3 zUVB+P=XAThpz}LZ%=j}*rReu9#d1%MJHNNmBB{hR3rlP;UIHt!jN~D?DJP}I*(jD# z6u=lqXD&xcdC$CrNWE;EzS5);fz=jzYf!%euVZ!)(X-T(;SoR*;(kwwAYsY(`OF`?3?j{bQMVX3>*sw>IY}sKg)Jz#NZB1AjF;+_k*fJMJzEn zScj~nvKCIc7~gP_Pfg^>ns23@?;j`X;bh|f7n{9GUe>OGoo6MkonxjZhT3I>!Idu5 zl+_)^#N4fS@P-{X;^+&&E^JgQt7qoyo>5JC55ywM&!!ECF)9_Vtc&4Arzk6XJRU%) z8VWzIx*IoTA`^@BI^>2$u>=zcB#ZsFwn#9A?AO0rXiC$lDYi;p7HyI(LZ9g%jc z+xi+y&s=(K{Ba{ynlr7WqTCr>h==uusz%LtoTZYy&lr~ov7C;_l3Juq^T4?%an!?B zcze96&q9GO`K5(xy_e8*mZo;jh)V5^tzx{<9A;I? zKCY1jz>YJVMDib{CrbKK@4~#Aqt=c}y#ym&w@<$TV$2E%S>F(YAGz>HYY`1tQk}b~ zz&pcRZ|W(l-&JB+n%BfY$5OtN^=Q8&f%gfs18RR_6xc$10_p;9Pm_SLx8e~ZH0pC0 z&)gH`53GSRxWf|{QO3#c8zj()wT-RRv)0~g7S(s9*AIxR(jHcqqp8x)fazQm<=iqH3Xj5HC>nkZZ5o$J zIp-CF8ciP;v&2y6@Jw5j5bj>Qf&7v>{+2H^icLI4tL5G}yRmQHO=!+fS zi+wl}<-$yT#YjXEVsbzu_t4|bi@Un48$bhTt(~(hI1rbv9GTw4;ArZ?K_gy(u;o{W zKr{JZyf)(gIDueEQ>8F=$?7Viwd*FGK8m6!VDD@m{j-JX7ij zu)Luo>s;)}0fZvPjmhty3XI-tYyc?5wN^rigW&&27NhgBFdZ)(R<_xy+!O$?qg2NJ z)+1ITjOu(9s2qPs76mbg3DF_QY69&bI&RWZdXCB067YK6$F=~QRFY@H!qZ9wch?0n z(XR5G-EPNYLEdAr9gsg&o4?IM9=^)@hsRCBGczBpIF>B+A|&cqnypwpWrwGBd1&sq~|6 zB}|xmGMUxSQECvi4UFRqw@4=Cl7>g4mj7I}@2oZOE=ed}_(vE3b+XQz-(SV`FW&Fk3--8_az=LDBwADdNE026pA z$H_%)q0~6pX}z&xQxpJ5)M4pP{b za%i2LIaF!V8B?c3)ec7`c0Z1PX5fTYh5flhPjg~*u=X7V_#1`T{M>-#Xr4tAvD@<5 zPqrRswv}7K;~qCXR5kGhxR}R(ZX2hX2o!mR7Anj?2wk~B=$Kp*&f9D+%DL60Tr5sr ztB_e3F8IB2BRZ&`g9?W{I47SYZXTAh!COYaOtoCy;zz5G)VPzkmOv&v`Hz;MqBOIt zQ15J?oJ<4`L9Lh=(wSb+1IH=SH_Eu;6`^ss;XIcm!jwQhRoct=4y2UtKO z+-CTBuzI1$qzPhQ{88@<6R9%H;(&T_PHl&u0XcZxG9ls@a645NKA}VA*lMOy;yi&% zd{V3?LdZisqOr>y=o9nS6Q}3;018-O)+K^uG{`G-Xv;|FO$#rXjf6wRm!1X(Y-aYER*<1D+*RmIrh+} zA}{%BAPDttBu4S7D&|3k_*$En#nN4jtV1|>zR}J~He&CXqWdfpnLvN4$NR9U47NRM zMeOadf1(7I0Wv~-!4I;lL>XAMTkYE(3`O09a(qkV_TK0rPi`_SEr#-2@VQo&kgi~t zp1QzTTc(cb8?Q=5`%>yUG#M2-GC~KIEx`muCVdm~6yq3-2`k^Oc2`6^J)FLuU)MU- z4pr~s-qMhJ9%;C}k*Hu4F+8NHoFK9QQel1TjJ)%Ym}m>}99$>F7=fhc^KoO@uu zbnzXv0Bpw+)!}XYIsaHB2+xBvz8(3!Qes+95QzPI{?D8u?m}B<%F02seYiXY@s8i( ze(hX9>SZtaTOeYc>xfWqAa$Wi<|?KV?o#-q+#@qc{olS2TIRZ!PbC^zh`!hUz4Urs zmvLC-i6kH~+9)@KK{zwiU&K+&knd^v5r8cJAf%46xfq$i1u!IKr`f|UBpvt%fw_#B-zv6V8rZpM*vFkDQb@$|{ zb0=KfABlJmd})DX-+9uPG-r`4ezbvMKrZ)7A5e{S8oI6{49OW7yItxbTkRQOEb$OF z6`^v>SNnpZWtTbi9vukiZnKG1pnn2ui()Y_`|B)xIkgV_2R>E9Zqyah1-6bYMofup-ZvGM-@0N$)E*qi>od+CH-ERYNE8CiX7bf;@r!6=ZB;G< zTtM2FZhH^@xv6DXY7IOQo1vvE#Y_)MZY>mgiF2(G^uUmz7WQXX9g?3JM9&s3kJyH! zDZQ#!Fv6)de99xy?!tCyP6JWiCRyDm$WnB~?@OPtGqg?`tARz_7;);CLOgB9M2Q{*NpM`@n zkflJNe|=3B5JwMDY%XZaarGR>e+XPHN({ZJERN7@Aerl})YZ@t)mhhDfj5x577~?w zZFys=iFE;+_O~!3N}z3wo=3rr$DfZ6nIGnkd%NP2@i9B3w4Zi$ z)D9pG5A^LE8X<))kTK|Q-~zZQ;-08#j}`zndNZd!DE8&#EZ_;#MKE>RljS#IRlbFP z98zS7?EgDUT`IFxBlu%{?TVeSx-gVtmdGlfYv8V2fh$&?2YmrozgQ!rcHItsKI~9u zO2WbZo9Y10usm|3uL!Y@k!#h3z@_ri>G(=Xp9gHiNuyJoM#6~Kg+`H3$xn<>k`~() zr2U8lS;tGkaUt2!W33E?5DA|0hEVbvBDe#4`?w&z6=^J|REE&;5^{5v5+W?EQ~}D= zL3X^+TEEDy!QeX=mp{3TIH=))=h;W8F$+SFg+Bf0#D z2BxIR-6ZL>uiV%?44zB{AOeF4eRQxB-Fo`(puFwb0?QwT_{u5xu73ZkVjp2Gd{oBO zDZuoQA4gC|cA5Ce=8qYjW*|dR$+ES+0m-h}fAM-nL*zj!p{TFy0GTMcao=9yt(&tO z-gBrzfxYZoA=(}fElVz#xg8+e(hY7{&>9867m#?A2)m67}ns(K`dUrabfG z2X-@xwQH)1IjQCN3AEf`3BKQK`nMhmQA+2E-|C*LYW!$55Pti9TMA}l z>@Oy?ANYUtwl}izH+yS;V%Euar2Pq67Vw@VGI`;wUlNxHnRJkvrLWIx&*ctLmV~3H zl1X{5Rg|jeGRzpX9n;!AS`Rbl&60btH;u(!8$+Mk1pexz9({54u}JTrTfbK2Zt4Oo z&_Z*6(|VQHIcLn7-_w9;y28a*dUDDc_rddC0?-KDre;GBswUY1He-+_1zq1+beX+R z-z`f$3#)fUIDt(TK-!ZbH5xP4dFJl2x%A9}iX@yT>siUrb#rqlTLp0J=nBok%PkOg z50ty9L{hw&2_-+Pn6H((8npnRirkY3&;ClcK{YHdflUx}tE>MPb&PU*309nwg4g)^ zPs+L>Pbr?{so-oz(+D_z5BP}k{Yec_y>wFfHd^F zQ<6g=u*;_%_so(Uen=1@dW_qxwet|Lh*G0NC-o^Sp5MiPzWe>4QpO*3p0J=-Grraiv*#&IS2P0;0pIP?vZjN-NUxjtHL*Q#M*} zXQfRmSk^mt#p1rMp-7ldrWqEr${bg)*2RB@d|@nu-}D^){$#O{RXRbNzw_JCbST6f zS$ZZ+;1@}A!=-JL09)`@qjW~DUFY%GVij$_v*2!RMG#|cLp7Sj z=biQ4t?AA8qaart$H0o$faKLn)wEjTu>xUIX(MeT~Esj z+gZ=^g*T;42(y&&WYvDHZ5WlbULT<#`a35Tk?A++9WbMtpkqP?8vgcqD9+S4e(~1v zOjf1SDlcYuom%CsI1|nYb$a6g>&myO!x6-RpX)#aFQGB%c)Aceq8h~UIP4LmAMpuu zQTR0UydClEwnkZ0$Y2}VIr25@@` z$MoaLG)_rt3Q9po+z%_5yoJIJHa(pAw@8eS?m1Y6X`)kVhKuykydwrC#lzPz_pW|a zUay%bjNKj^PmLYZc*dc`!H~5F&tOQ!Kb2VmH>4=gi9}6QuobL2f^&ZKM!e^_=9t&*=gQZ?gD&UWrOA>h94y+pc&HG^p((+DDDA zp`TU!Yv(gL6(7W{5oL+y{EDM0m?<1>m!Y-+6l3MzA-;C9;<*sVPd5b# z6b_DlQ9^{TbxAbgb-M(0$AyE5;OtUnnsDFO;`Bm@d&D`3 z&kIlqmUVn7g>{qL1~P5Ov?@cgn5EhH!ZMMw&*_jC0WkI6?r4;+Dy}_qkOF&XxIC!g z^8k?U`0*15syA1sGuG5Z@B2jpr|U0tYVIG|f(s4^=C){UADI_?mbUx@^qO|jS97$o zDW`8)O4z4}h-t327)^6Ax*`R%c-o4ldrVN4U z&(as)D9VlQY;Q#_YHVFsI8gqdp()zh4Xova1N`LC_q>ES99}<6HD;r&H7OniBIq} za0tS@dx9RvZH-*Lg9)^yPY4r7lBb8gRAJSTzmFYz12-Xajg+1&6agLTZ`fcr!V&z^ zv{dg`vI?J7&m{Onk2$tBPGB;bo_FI|MnPP7@uOm3 zbXW*qc?os$Jib&sz6AH5vAu#sHs#+_qDHR?i@(jzD)3X>3TOQq017HDF$5DIMd{fu zV;~I4Be2vIq`1X4t~6{b7or>CbVy7 zSP)3{1)dL~M0&S5yK!m|jyoeGXeq`&xpZ=*djhKkz=xv5v?>VlbOlNLb$()% zO1b|tF%TMVRaQx}^Td~-!nh(7X@|o!2QS>;%6K+f%*Dr5Y^?s%_NmZ1DtRxz_>y3$ZBAmg{@s#G#Ee1`CdA9b{*+Sow3vUsqZ#4Svt8>#bLm94X6j38D>@ z1SkbHGQGA(2ov`|gjRH=3<}!y4lmw!&Vqo{8?)}Bf<#f>N3zOmKTok6JQt4I#+Ze? z5Kyx`htbmH^*u&kBT4g)PJRiBW)mD#}0$uf27K z%)W8JnIpI1cim?ew$ZS3#dVzW8Q55L^fG$RXVj3=Es5IlqZ}_WJyUhDdSTIXJR8Pg zN@=LnTsaViwm~U;v!RneeU27(DpE?p?*JyAkb@ec4AMwS(? z4KI^%{?FqD%3kTk`9e$%h&b~#kfe}}cd7)S5A=P=wUjHtRKuPf{G-VJzyQ|flNdX1 zy0pXa6p)0*Lvu$wD1FY##6Cc@RH4jW@b}Deg(f$iCG*9aXs79Op}YQcZO_2E?!LdX z!p#mI5XQ&V@>Bab#1T^R@xf=}0t1(xJ&EIp2_EkHHljfb3iShxFPojI#TpZT{oe|-_ zH^U^#g|lN1T$juP!VI028A$yAAh1g}vPoN(LRcJ00yyGG0$4!#yE&dqhc+B&#F0v{ ziknU#U1UY37f#!lbMg7R_iu%?l*9bnz;4!YooP84z;8=7E}!6+S|=Rn2MnEPZ* zhGRy%3wD=qk{m!$-*#K0Y`6x$YX4V9Yn{d!FoHiEXQ7up#JxA;_%qPbQKR)6M6A>> zW59{55Ju z^Q8vxPmvkREh;VPH4QS;1t^|8FxKMl9Q42k<^%4}4CAU|aS`9U^KC=%FJGfJ1P0Za zR;Ot_&i2${1GIL~Yn}(GTs$W%O@`l0Wck(WDS<5~w#aoXXYH+;b$ne?UTdbMY}hTx zP(f8OqqkVO+o{tp0F;*tJ4_Z?A^>3@)*}>wRo}xuC;3$v$O?Je| zGO}qcq`o=4;+0Ebls-JMW9|;<`KPCESJcM=a}Op$_zWt=nyPg2%Nz3dkdbGSxt<0l z)?H1rV}&aZ`N%;UMlC0Q-2qr9bin}!lh=56up*iMs!OQyHJQ~nM;Ty)Avz{0pl#}fU-s@z@SbFAyFj{Kaf+OdQ zR>nj^o-=ZPOPB}<5>B1uKUKv4u(s%9AtpMKDfzmIf?dydN!|Dzld+z%#hLS?G=!0# ziuMa-r-1M1ikiKYR#6P;&}JBXNHk~34onR-mF5w`iMp~_Cu2VdI7IXQ444|e=+X=m z&y06Iq28;b4Q?<>BH|t_@p?;7^?EY&c*)-Cp4P&I*`GxwB5sw^x*m`&P44dKdi!e& zWmbS!>U&6^T&cA0AHH53c-DlM8|W;jXuId~iXj(Js3sWtjwK~bd3#a($GhB=z;l4j zd^2?!cyHYiNCvyfJF5SQ>os)X>sF3Sj<|egxWPc!uO4dZAWhtyW?f)GgBdn}CM8gr z0)^AZ=|$p#>g6Ob2{iSP?yKR zsHGxG#@Zk7z|NDuLmS=XJG-f%U6K!r^8UOz>8^6x^SLHPEO{iRYQGU%?k`33L5doN z#!GfbzK%*y&6lMgFQoE9i`Uq)70#@ui=pq-+Qcd?wep7vVwML!97sCCwMm=z_{Ks~ zn>44bOT02x0&gi9&#ZpbMq#;%1;+zw>ZqK4Kf~QgfT+DPg%o9q7mJLY14G%TdLIry zzmF*QHHoWEwWIl>5crMN?B=!=h<1z-7ypADy8{b=@O|ezAIY24=yUHqms0~Z4(>N# zUi{PLTfry7y`lWQ?<}W;ntk+&N#bE_7c5^Z0vQ3a<;ad6*1X1%nhyO}1gLch)VS5^ z>~tTg>}8@Ag!?$*O^M*Z+)_6244UiZY*HBh;=VO;?>aPAjO@o;_Ns#ZYEeo7U*)Qi zzzw&BpAAO2v0SOmmQ_IWt=f+B!X})5%~4ngc{NvO%x&6ULN$q^a{?=Rk4c|itJ_2G zHwNA$8>h!$)ryB~>axV&DcYdoO@l&i7zn%v@DED)G;bf_uaMX>)jR)Hb;=5s#B?k6 zYsM>qf|J{iWn(k12EI#efbskl%xXn@Ss~gEB4zc+as^8@fU=1=xmGK+Brja9A2)CK ze!!$;4gJed_mC7iSwSxO-syUMbW3*VCWSHA2m#0#)5RN6XSi`YbQSI_o7!`2J?dOp zoQ`KQ=aNInRS`41VsqqG_Q1v z%j$718}`^v@LM|$7PQy%ffnos-n%%l1@qk>OLEu`z9f3~1#G7OT>*AckQ9R_^W}7< zYTW93IEwL+h#@EXtSSIseou6x<% zk*1hNm};^nH`{aDM8IdrZkisC0Zy{x?3uYm9V%%OsvBid$q- z>Rc5j`BJobbvL?W_92G^J|!&Pfb~IV^CvQ!-$|SrTEoRt7U6>#Fj|Y(E!+K-8nnZ_ zShq9h6k?RHPW6?D2G+QpiT7IV^r>4b*7{JCD5szd7L}``Cg^N2BWr2QO>BV2kV|UF zBsp5&8D*kv7-7@ggvjt#4T*n^qylvJ;rn@QJT?SrvdX;CE|U zEv5f;CK-UFH#9B7YzdUr_C1M2`5V>QJUsD4024K$1qasgc*|VDYopRg1U89}Rd5fR z4gEkbx&Rwyy&~?(gB_`}#d2mt*`##@o3Pf))Ocr4>!yK(g5bVxhIX|QH8)6iT@%hNT=&>wc8B zNYY+B*W4=H#aNBuIrgG;Sligj%1u2uPImzFXgV)We2%YZ?{5T&G@i>~5Ik`724*Jk z3kj#><$7mcD`5KmmiKA-+@gZrFsYWLbBXY%jdpdgc61>-F?UKy_=Ncu$7(OdC?7Rl z&KJdt)kkYRjQ7ldjq_E}nQrzuMtm{f?>Z~|=$q{mm0#MjJp${~H_%)o%oVp6bVjS% z2E1RzsW4o*7aCFyamEAhvQhQNG@M)31sf`$urEGnZj<4Go4?$D!SdI-G1Wy5gY>Jc z1O_e+GgxE+nHWntOUrkzT07Qn=w{V%2-~c7xMRho)07hq*-n46oAs;B^5sMy*PRU9 zSZ_52bEQ*uP(@A?L7T&Q3$WhHd%FUr`4VXz)qCDhGLT+Q14+e-!(TKoaHKaOD=Jv!QJ34PU6*H4G#-(zsmNFvw}GyrxG{Sp*M-)WW0N)~URL2!9` zNBbkI{Sfnt6mG6R-8=4IkmngA1~5}S5*3e%QX0$d0ml;q|BQ3&K;w|?)xAnyp2I@c zr-{Z&2vTthi5aO?F6z$yx5LLlFNg&uKzk$*T87d%nQojnT017UT&`IMCGIT|qln+d zJ_xMSW-Q@}$5Co?E2YJ~JJW4t;uu3e0ZJSDWtw?aMet@U2cpAdHsda-p_#e0V{v~~ z`Fw4Gx_t@JR?S*bYK4iK^YcfFYNklmvYzm%Kzd<&YNhVyJZiI6-PC9&@iSpm#5Xk(fYKR z@+X8OyM8td6l>s58J3xV0K~_yordQg)<{5Jz3}#qdVaM1S%X|xYy^y=PTJ|MCX|F+ zhjmWF6jcy^VwYF)w{7{PNTpbV+;E{YqpYjjV357skvf6PAqX-#un1g)@*L*UVg#G~ zfZR6*K!rdb1a*gx8q34REh%u=J8v&`ipi4CZ+EBnPa4$9l6vBF;6%j8s+qO`Pt zCeh`QJ3fM1;v0tN#r*S9LXImz;WWCBLU5x{M84PamN^(smmeZrXCSzzq$Z1&!(xP8$uu>ecc8VM-O~U zpuAnW$kVW%(Tl#(5*jb9XdEgy?W@Cn6e6XQE|M!WH_~RpxIr#1GNvk(4xkh0N6Ff3 z*hS-NoZQKmP5=cjd=_|2fV?of?{;Tz%IvnvE6C-pf+F>>ArPv1s^8h?TLiKGHH;W3 zSG}jUFau*Q@=9bndkgjECKG_vRV!X`T%S}6+X!FlwVAgQNd~a>$e;7ZAx?0_ox7Lh zOiGyu)4Q0ofCbL7=UvqME1LtE!Ecg9UY?gc)?5QF>Ph|pzwAp+f%gOWWwrdmg6C%U zB6_{Zr7mjx*`1E=(wEl^s>9txq4u9H%D!ZeAb5BUd9Ff&{Ud-&UKw(FUWn6EIBI$vZgC*IwnRwE|g_^6YK=pbaW91 zER1SAYC=$hhF5+jAS%@oPC9gRvstjOQI0o;Yoof?aTrGr$rggqa!@xz*a|feW!0Oo zm-R#eOU}hEL#kM{0kVGf9DaFAHduP!9p8xep3~-Wr!R)M%7DekMy$0w%&QtqejML> zC_o(yR4)SK5J3Wi;*2&Qfc7`bidam4@H-gQk%z9Wp`1Q|(Qn7RHrD0C0E{cN+H343 zVL?)YZ>!^0e|Qv+Vw5|*7weCT9Y8t^{(QkX=N6jCf=E+^n+^>c5)S7cI#GhX5Z{Yj zo!O|>!oJZ>bJxL$wC8a1S#pT;O|g8EkrlwU8jLs?HE; zFcg22uNygMz97Z?bmMLc&);p49t1f33%SYRsGmYFa|;_sKt4$}mnjUa2d8^m~47e3+LSTe_E&T?@lrU&3Dw8}7JunK9F z;0!*i@}PdXVo)zpM)ab7HKlrGWjdsUQ6j%(P23K5(a1tVV{aISZbVllg*wfY;D2BJ zI?`5Ggz{>o1an;DBDoIY@tFFH?1Mgb26#^fShhg#r~C_MJfGLqty__6(!1&$OL+hI z>V#Qu@IsquPtq7UMt(`72I&mek3WqrAnE;jE4VPtfmEfcQrRDgidDp zixoiDrHDY|+NIS=|K?R16{PQ}F7xkZADWhR11)T6i^7f4S?33sqjr9F+??s}p<*;<*rC3=Dq^QYu_W0GZZvB2ubZ^|GoJt9-_>3_(! z#d4mvt}u%w<_eNtuQYYsoSB{gc^?%GjoBVUn&2+f2D8ml-j33wE2T;BjkcB8vL40Q z0V8W}Ogs|mIRHi6oALF+EzAyH?8mzjN}9{t_@vSbgN<{0+o?Ye~;Ji7v9$3p9QVt#u0pDH&Fnry~E&=Rho6wsAJ)NBcKYcim*WUDu zQL#q(0?HV3sSo>~s7jwWC}N2XJQ*QoyDPX1W5;GBU86VGAga!3cNZO`BV6)eXw*

-IR_!Ms6O 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 - redirect(auth.status === 401 ? '/?auth=login&required=scan' : '/'); + if ("error" in auth) { + if (auth.status === 401 && source.cookies.get("inn_refresh_token")?.value) { + return ; + } + redirect(auth.status === 401 ? "/?auth=login&required=scan" : "/"); } const name = auth.user.user_metadata?.full_name || auth.user.user_metadata?.name; - const staffLabel = `${typeof name === 'string' && name ? name : auth.user.email ?? 'staff'} (${auth.role})`; + const staffLabel = `${typeof name === "string" && name ? name : auth.user.email ?? "staff"} (${auth.role})`; return ; } diff --git a/src/app/api/pass/experience/route.ts b/src/app/api/pass/experience/route.ts new file mode 100644 index 0000000..d8296f8 --- /dev/null +++ b/src/app/api/pass/experience/route.ts @@ -0,0 +1,23 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { getAuthenticatedUser } from '@/lib/auth-server'; +import { getSupabaseAsUser } from '@/lib/supabase'; +import { createRateLimiter } from '@/lib/security'; +import { entryRateLimited, entryRpcFailure } from '@/lib/entry-route'; + +const limiter = createRateLimiter({ limit: 40, windowMs: 60_000 }); + +export async function POST(req: NextRequest) { + const auth = await getAuthenticatedUser(req); + if (!auth) return NextResponse.json({ error: 'Sign in required.' }, { status: 401 }); + const limited = entryRateLimited(limiter, auth.user.id); + if (limited) return limited; + const body = await req.json().catch(() => null); + if (!body || !['claim', 'acknowledge'].includes(body.action) || + typeof body.claim !== 'string' || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(body.claim)) { + return NextResponse.json({ error: 'Invalid experience request.' }, { status: 400 }); + } + const db = getSupabaseAsUser(auth.token); + const { data, error } = await db.rpc(body.action === 'claim' ? 'claim_pass_experience' : 'acknowledge_pass_experience', { p_claim: body.claim }); + if (error) return entryRpcFailure(error, '/api/pass/experience'); + return NextResponse.json({ result: data }, { headers: { 'Cache-Control': 'private, no-store' } }); +} diff --git a/src/app/api/pass/route.ts b/src/app/api/pass/route.ts index 9d343ea..4313fba 100644 --- a/src/app/api/pass/route.ts +++ b/src/app/api/pass/route.ts @@ -3,6 +3,7 @@ import { getAuthenticatedUser } from '@/lib/auth-server'; import { getSupabaseAsUser } from '@/lib/supabase'; import { createRateLimiter } from '@/lib/security'; import { decryptEntryToken, encryptEntryToken, entryPassKey, mintEntryToken } from '@/lib/entry-pass'; +import type { ParticipantPass } from '@/lib/pass-experience'; export const runtime = 'nodejs'; @@ -45,22 +46,27 @@ export async function POST(req: NextRequest) { } const mine = data as MyEntryPass; - const pass = { + const details = await db.from('registrations').select('college') + .eq('user_id', auth.user.id).eq('registration_id', mine.registration_id ?? '').maybeSingle(); + if (details.error) return NextResponse.json({ error: 'Could not load your registration.' }, { status: 500 }); + const pass: ParticipantPass = { registrationStatus: mine.registration_status, passStatus: mine.pass_status, registrationId: mine.registration_id ?? null, name: mine.name ?? null, + college: details.data?.college ?? null, checkedIn: !!mine.checked_in, token: null as string | null, }; if (mine.registration_status !== 'confirmed' || mine.pass_status !== 'active' || !mine.pass) { - return NextResponse.json({ success: true, pass }); + return NextResponse.json({ success: true, pass }, { headers: { 'Cache-Control': 'private, no-store' } }); } const key = entryPassKey(); if (!key) { console.error('/api/pass: ENTRY_PASS_ENCRYPTION_KEY is missing or not 32 bytes'); - return NextResponse.json({ error: 'Entry passes are not available yet. Please try again later.' }, { status: 503 }); + pass.qrUnavailable = 'Your payment is verified. The check-in QR is temporarily unavailable; please check again later.'; + return NextResponse.json({ success: true, pass }, { headers: { 'Cache-Control': 'private, no-store' } }); } let ciphertext = mine.token_ciphertext ?? null; @@ -83,7 +89,7 @@ export async function POST(req: NextRequest) { console.error('/api/pass: stored token does not decrypt (wrong ENTRY_PASS_ENCRYPTION_KEY?)'); return NextResponse.json({ error: 'Your pass could not be loaded. Please contact the help desk.' }, { status: 500 }); } - return NextResponse.json({ success: true, pass }); + return NextResponse.json({ success: true, pass }, { headers: { 'Cache-Control': 'private, no-store' } }); } catch (err: unknown) { console.error('/api/pass error:', err); return NextResponse.json({ error: 'Could not load your pass.' }, { status: 500 }); diff --git a/src/app/api/register/route.ts b/src/app/api/register/route.ts index d87ba7b..d3f568b 100644 --- a/src/app/api/register/route.ts +++ b/src/app/api/register/route.ts @@ -11,7 +11,6 @@ import { generateRegistrationId, isFilterSafeEmail, NEW_REGISTRATION_STATUS, - NIT_ROURKELA_COLLEGE, readJsonObject, REGISTRATION_FEE_INR, validateRegistrationInput, @@ -145,7 +144,7 @@ export async function POST(req: NextRequest) { return NextResponse.json({ error: parsed.error, field: parsed.field }, { status: 400 }); } const input = parsed.data; - const college = studentType === 'internal' ? NIT_ROURKELA_COLLEGE : input.college; + const college = input.college; const adminClient = getSupabaseAdmin(token); diff --git a/src/app/api/tickets/route.ts b/src/app/api/tickets/route.ts new file mode 100644 index 0000000..6ec99a7 --- /dev/null +++ b/src/app/api/tickets/route.ts @@ -0,0 +1,3 @@ +/** Compatibility alias. Pass access may mint an opaque token, so it uses POST. */ +export const runtime = 'nodejs'; +export { POST } from '../pass/route'; diff --git a/src/app/api/tickets/verify/route.ts b/src/app/api/tickets/verify/route.ts new file mode 100644 index 0000000..5edc44c --- /dev/null +++ b/src/app/api/tickets/verify/route.ts @@ -0,0 +1,3 @@ +/** Compatibility alias. Same staff authorization, opaque tokens and atomic check-in contract. */ +export const runtime = 'nodejs'; +export { POST } from '../../admin/entry/check-in/route'; diff --git a/src/app/globals.css b/src/app/globals.css index a0de7ef..c03c78e 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,3 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + /* ---------- base (from the Innovision 2026 design) ---------- */ *,*::before,*::after{box-sizing:border-box} /* ---------- typography ---------- @@ -6,7 +10,51 @@ --font-sans Manrope, variable: subheadings, eyebrow labels, buttons, navigation, body copy and data (IDs, prices in lists). Weights by role: 400 body, 500 navigation and secondary text, 700 labels, buttons and subheadings, 800 small badges and ID numbers. Display text is never bolded (the face has no bold). */ -:root{--font-display:var(--font-dm-serif),'Times New Roman',serif;--font-sans:var(--font-manrope),'Segoe UI',system-ui,sans-serif} +:root { + --background: 42 22% 90%; + --foreground: 30 5% 8%; + --card: 42 22% 90%; + --card-foreground: 30 5% 8%; + --popover: 0 0% 100%; + --popover-foreground: 30 5% 8%; + --primary: 38 92% 50%; + --primary-foreground: 0 0% 100%; + --secondary: 40 10% 80%; + --secondary-foreground: 30 5% 8%; + --muted: 40 10% 85%; + --muted-foreground: 30 5% 45%; + --accent: 38 92% 50%; + --accent-foreground: 0 0% 100%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 40 10% 75%; + --input: 40 10% 75%; + --ring: 38 92% 50%; + --radius: 0.5rem; + --font-display:var(--font-dm-serif),'Times New Roman',serif; + --font-sans:var(--font-manrope),'Segoe UI',system-ui,sans-serif; +} +.dark { + --background: 240 10% 3.9%; + --foreground: 0 0% 98%; + --card: 240 10% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 240 10% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 240 5.9% 10%; + --secondary: 240 3.7% 15.9%; + --secondary-foreground: 0 0% 98%; + --muted: 240 3.7% 15.9%; + --muted-foreground: 240 5% 64.9%; + --accent: 240 3.7% 15.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 240 3.7% 15.9%; + --input: 240 3.7% 15.9%; + --ring: 240 4.9% 83.9%; +} html,body{margin:0;height:100%;overflow:hidden;background:#ECE8DF;color:#141312;font-family:var(--font-sans);-webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent} img{display:block;max-width:none;user-select:none;-webkit-user-drag:none} button{font:inherit;color:inherit} diff --git a/src/app/page.tsx b/src/app/page.tsx index b5be0de..b5c5388 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,8 +2,7 @@ import Innovision from "@/components/innovision/Innovision"; import { SITE_DESCRIPTION } from "@/config/site"; import { homeJsonLd, jsonLdScript, pageMetadata } from "@/lib/seo"; -// Canonical "/" also covers the query-string entry points (?auth=login, ?open=register, OAuth ?code=) and every -// #/ hash route, which all render this one page. +// Canonical "/" covers the main Innovision 2026 website experience export const metadata = pageMetadata({ title: null, description: SITE_DESCRIPTION, path: "/" }); export default function Home() { diff --git a/src/app/ticket/page.tsx b/src/app/ticket/page.tsx new file mode 100644 index 0000000..737465c --- /dev/null +++ b/src/app/ticket/page.tsx @@ -0,0 +1,5 @@ +import { redirect } from "next/navigation"; + +export default function TicketPage() { + redirect("/"); +} diff --git a/src/components/innovision/ApprovedPassTicket.module.css b/src/components/innovision/ApprovedPassTicket.module.css new file mode 100644 index 0000000..488f9a2 --- /dev/null +++ b/src/components/innovision/ApprovedPassTicket.module.css @@ -0,0 +1,11 @@ +.root { width:100%; max-width:920px; margin-inline:auto; min-width:0; } +.root > article { max-width:560px; margin-inline:auto; } +.actions { display:flex; justify-content:center; flex-wrap:wrap; gap:10px; margin-top:22px; } +.actions button { min-height:46px; padding:12px 22px; border:1px solid #ece8df40; border-radius:6px; background:transparent; color:#ece8df; font:600 13px/1.4 var(--font-sans),sans-serif; cursor:pointer; transition:background-color .2s; } +.actions button:hover { background:#ece8df10; }.actions .print { background:#ece8df; border-color:#ece8df; color:#141312; }.actions .print:hover { background:#fff8eb; } +.actions button:focus-visible { outline:2px solid #c9a24a; outline-offset:4px; }.actions button:disabled { opacity:.6; cursor:wait; } +.note { margin:12px 0 0; text-align:center; font-size:12px; line-height:1.5; color:#ece8df99; } +.dialog { width:calc(100% - 32px); max-width:380px; padding:26px; border:1px solid #ece8df30; background:#100f0e; color:#ece8df; border-radius:12px; } +.largeQr { margin:8px auto; width:min(100%,280px); }.largeQr svg { display:block; width:100%; height:auto; }.qrName { margin:0; text-align:center; overflow-wrap:anywhere; font-size:16px; }.qrName span { display:inline-block; margin-top:6px; font:12px ui-monospace,monospace; color:#ece8df99; } +.printRoot { display:none; } +@media(max-width:680px) { .root { max-width:440px; }.actions { display:grid; grid-template-columns:repeat(auto-fit,minmax(130px,1fr)); gap:9px; margin-top:16px; }.actions button { padding-inline:12px; min-height:48px; }.note { max-width:34ch; margin-inline:auto; } } diff --git a/src/components/innovision/ApprovedPassTicket.tsx b/src/components/innovision/ApprovedPassTicket.tsx new file mode 100644 index 0000000..ca0d744 --- /dev/null +++ b/src/components/innovision/ApprovedPassTicket.tsx @@ -0,0 +1,116 @@ +'use client'; + +import { useEffect, useRef, useState } from 'react'; +import { createPortal } from 'react-dom'; +import { QRCodeSVG } from 'qrcode.react'; +import EventTicket from '@/components/ui/event-ticket'; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'; +import type { ParticipantPass } from '@/lib/pass-experience'; +import { VENUE_CITY } from '@/config/site'; +import PassKeepsake from './PassKeepsake'; +import styles from './ApprovedPassTicket.module.css'; + +export default function ApprovedPassTicket({ pass }: { pass: ParticipantPass }) { + const [compact, setCompact] = useState(null); + const [qrOpen, setQrOpen] = useState(false); + const [saving, setSaving] = useState(false); + const [saveError, setSaveError] = useState(''); + const qrButton = useRef(null); + useEffect(() => { + const media = matchMedia('(max-width: 680px)'); + const update = () => setCompact(media.matches); + update(); + media.addEventListener('change', update); + return () => media.removeEventListener('change', update); + }, []); + + const savePdf = async () => { + if (saving) return; + setSaving(true); + setSaveError(''); + try { + const { downloadPassPdf } = await import('./download-pass'); + await downloadPassPdf(pass); + } catch { + setSaveError('Could not save your pass. Please try again. Your pass is still available here.'); + } finally { + setSaving(false); + } + }; + + return ( +

+ {/* Only mount the illustrated canvas ticket on larger screens. */} + {compact !== false || (pass.name?.length ?? 0) > 70 || (pass.college?.length ?? 0) > 90 ? : ( + : undefined} + qrLabel={pass.token ? 'Your entry QR' : 'Registration ID'} + night="#08070d" starInk="#f6f2e8" paper="#eee9dc" paperInk="#141312" stampColor="#89672b" + tilt={2.5} maxWidth="100%" + /> + )} +
+ + {pass.token && } +
+

{pass.qrUnavailable || 'Keep your pass handy. Your registration ID is always available here.'}

+ {saveError &&

{saveError}

} + + {pass.token && + { event.preventDefault(); qrButton.current?.focus(); }}> + + Your entry QR + Show this code to the registration team at NIT Rourkela. + +
+

{pass.name}
{pass.registrationId}

+
+
} + + {/* A direct child of body, outside the clipped/animated registration overlay. */} + {compact !== null && createPortal( + , document.body + )} +
+ ); +} diff --git a/src/components/innovision/AuthOverlay.module.css b/src/components/innovision/AuthOverlay.module.css new file mode 100644 index 0000000..62f0ace --- /dev/null +++ b/src/components/innovision/AuthOverlay.module.css @@ -0,0 +1,68 @@ +.layout { position:relative; display:flex; flex-direction:column; align-items:center; gap:18px; width:100%; max-width:640px; margin:0 auto; padding:10px 24px 32px; transition:max-width .4s ease; } +.intro { min-width:0; width:100%; text-align:center; --auth-title-size:clamp(32px,3.5vw,46px); } +.intro p { margin-inline:auto!important; margin-top:12px!important; } +.intro ol { text-align:left; } +.previewNote { margin:0 auto 12px; padding:8px 16px; color:#e6c675; font:11px/1.5 var(--font-sans),sans-serif; text-align:center; } +.previewApprove { padding:12px 18px; min-height:44px; border:1px dashed #c9a24a; border-radius:4px; color:#e6c675; background:#c9a24a14; cursor:pointer; } + +/* When pass view is active — expand to full desktop proportions */ +.layout[data-pass-view="true"], +.layout[data-approved="true"] { + max-width: 1140px !important; + width: 100% !important; + padding: 8px 24px 32px !important; +} + +.layout[data-pass-view="true"] > .intro, +.layout[data-approved="true"] > .intro { + display: none !important; +} + +.layout[data-pass-view="true"] .panel, +.layout[data-approved="true"] .panel { + max-width: 1140px !important; + width: 100% !important; +} + +.layout[data-pass-view="true"] .panelBorder, +.layout[data-approved="true"] .panelBorder, +.panelBorder[data-pass-border="true"] { + background: transparent !important; + padding: 0 !important; + clip-path: none !important; +} + +.layout[data-pass-view="true"] .panelBody, +.layout[data-approved="true"] .panelBody, +.panelBody[data-pass-panel="true"] { + background: transparent !important; + backdrop-filter: none !important; + -webkit-backdrop-filter: none !important; + clip-path: none !important; + padding: 0 !important; + box-shadow: none !important; +} + +.panel { position:relative; width:100%; min-width:0; max-width:560px; } +.panelBody { position:relative; padding:clamp(22px,3vw,36px); background:rgba(16,15,14,.9); backdrop-filter:blur(10px); clip-path:polygon(19.5px 0,100% 0,100% calc(100% - 19.5px),calc(100% - 19.5px) 100%,0 100%,0 19.5px); } +/* Static orbital details give the centered form a setting without rendering work. */ +@media(min-width:1100px) { + .layout:not([data-pass-view="true"])::before, + .layout:not([data-pass-view="true"])::after { content:''; position:absolute; width:210px; height:210px; border:1px solid rgba(201,162,74,.12); border-radius:50%; pointer-events:none; background:radial-gradient(circle at 50% 0,#c9a24a66 0 2px,transparent 3px); } + .layout:not([data-pass-view="true"])::before { left:-214px; top:170px; box-shadow:0 0 0 36px rgba(201,162,74,.025); } + .layout:not([data-pass-view="true"])::after { right:-214px; top:330px; width:140px; height:140px; border-style:dashed; } +} +@media(max-width:900px) { + .layout { gap:22px; padding:16px 20px 36px; } + .intro,.panel { width:100%; max-width:540px; justify-self:center; } + .intro { padding-top:0; } + .layout[data-pass-view="true"] .panel, + .layout[data-approved="true"] .panel { max-width: 100% !important; } +} +@media(max-width:480px) { + .layout { padding-inline:14px; gap:18px; } + .panelBody { padding:22px 18px; } + .panelBody[data-pass-panel=true] { padding:0 !important; } + .layout[data-pass-view="true"],.layout[data-approved="true"] { padding:8px 16px 28px!important; } +} +@media(prefers-reduced-motion:reduce) { .layout { transition:none; } } diff --git a/src/components/innovision/AuthOverlay.tsx b/src/components/innovision/AuthOverlay.tsx index 1f1b0e5..47a78a5 100644 --- a/src/components/innovision/AuthOverlay.tsx +++ b/src/components/innovision/AuthOverlay.tsx @@ -2,18 +2,26 @@ // @ts-nocheck "use client"; /* eslint-disable @next/next/no-img-element -- decorative/user-uploaded images not suited for next/image */ -import React, { useState } from 'react'; +import React, { useRef, useState } from 'react'; +import { useDialogFocus } from './useDialogFocus'; import type { V } from './types'; import { Logo } from './icons'; import EntryPassCard from './EntryPassCard'; +import styles from './AuthOverlay.module.css'; + +/* ── Payment QR lightbox state lives here, outside JSX ── */ export default function AuthOverlay({ v }: { v: V }) { + const dialog = useRef(null); + useDialogFocus(v.authHidden === 'false', dialog, v.closeAuthH); const [userCollege, setUserCollege] = useState(null); const collegeValue = userCollege !== null ? userCollege : (v.regVals?.college || ''); + const [payQrOpen, setPayQrOpen] = useState(false); return ( -
+ <> +
-
+
-
-
+ {v.isPreviewUser &&

Registration preview · No payment or registration is sent to the server.

} +
+
-

{v.authTitle}

+

{v.authTitle}

{v.authSub}

-
    +
      {v.prog.map((p, pI) => (
    1. @@ -63,7 +72,7 @@ export default function AuthOverlay({ v }: { v: V }) {
    2. ))}
    -
      +
        {v.prog.map((p, pI) => (
      1. @@ -73,9 +82,9 @@ export default function AuthOverlay({ v }: { v: V }) {
-
-
-
+
+
+
@@ -107,7 +116,7 @@ export default function AuthOverlay({ v }: { v: V }) { COLLEGE NAME { setUserCollege(e.target.value); if (v.clearErr) v.clearErr({ target: { name: 'college' } }); @@ -115,7 +124,6 @@ export default function AuthOverlay({ v }: { v: V }) { onInput={(e: React.FormEvent) => { setUserCollege(e.currentTarget.value); }} - readOnly={v.isInternal} autoComplete="organization" placeholder="Full name of your institute" aria-invalid={!!v.err.college} @@ -123,17 +131,16 @@ export default function AuthOverlay({ v }: { v: V }) { height: "54px", padding: "0 16px", borderRadius: "0", - background: v.isInternal ? "rgba(236,232,223,.08)" : "rgba(236,232,223,.04)", + background: "rgba(236,232,223,.04)", fontSize: "16px", color: "#ECE8DF", outline: "none", transition: "border-color .3s,background-color .3s", border: `1.5px solid ${v.bc.college}`, - cursor: v.isInternal ? "not-allowed" : "text", + cursor: "text", }} style-focus="border-color:oklch(0.8 0.12 85);background:rgba(236,232,223,.08)" /> - {v.isInternal && Verified NIT Rourkela student.} {v.err.college ? ({v.err.college}) : null}

Pay the fee

-
    @@ -193,6 +215,7 @@ export default function AuthOverlay({ v }: { v: V }) {
  1. 2Pay exactly ₹{v.fee}.
  2. 3Screenshot the success screen. You'll upload it next.
+ {v.isPreviewUser &&

Preview only: don’t make a payment. Continue to try the screenshot upload and 12-digit UTR fields.

}
@@ -260,48 +283,60 @@ export default function AuthOverlay({ v }: { v: V }) {
+ {v.isDev ? ( +
+ REGISTRATION PREVIEW + + +
+ ) : null} + {v.gErr ? ({v.gErr}) : null}
-
-
-
- -
-

BOARDING PASS

-

PASSENGER

-

{v.passName}

-
-

COLLEGE

{v.passCollege}

-

GATE

NIT Rourkela

-

FEST

Innovision 2026

-
-
-
-
-

REGISTRATION ID

{v.passId}

- {v.passStatus} -
- -
-
- {v.passQr ? : null} - {v.refCode ? ( -
- YOUR REFERRAL CODE - + {/* Payment QR Lightbox */} + {payQrOpen && ( +
setPayQrOpen(false)} + style={{ + position: "fixed", inset: "0", zIndex: "200", + display: "flex", alignItems: "center", justifyContent: "center", + background: "rgba(7,6,5,0.88)", + backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)", + cursor: "pointer", + animation: "fadeInLb .15s ease", + }} + role="dialog" aria-modal="true" aria-label="Payment QR code enlarged" + > +
e.stopPropagation()} + style={{ + position: "relative", padding: "16px", background: "#ECE8DF", + borderRadius: "10px", cursor: "default", + boxShadow: "0 0 0 2px oklch(0.8 0.12 85), 0 40px 100px rgba(0,0,0,0.7)", + animation: "popInLb .22s cubic-bezier(.34,1.56,.64,1)", + display: "flex", flexDirection: "column", alignItems: "center", gap: "12px", + }} + > + {`UPI +

Tap outside to close

+
+ +
+ )} + ); } diff --git a/src/components/innovision/EntryPassCard.tsx b/src/components/innovision/EntryPassCard.tsx index 6a19e82..8914cdf 100644 --- a/src/components/innovision/EntryPassCard.tsx +++ b/src/components/innovision/EntryPassCard.tsx @@ -1,220 +1,161 @@ 'use client'; -import React, { useEffect, useState } from 'react'; -import { getSupabase } from '@/lib/supabase'; -import { httpErrorMessage } from '@/lib/api-errors'; - -/* - * The participant's QR entry pass (profile overlay). The QR holds only an opaque random token, fetched from - * POST /api/pass for the signed-in owner and kept in memory only (never in localStorage). Shown only while the - * registration is confirmed and the pass active; otherwise the status is explained instead. - */ - -interface PassInfo { - registrationStatus: 'none' | 'pending' | 'confirmed' | 'rejected'; - passStatus: 'none' | 'active' | 'revoked'; - registrationId: string | null; - name: string | null; - checkedIn: boolean; - token: string | null; +import { useEffect, useState } from 'react'; +import { isApprovedPass, passStatusMessage, type ParticipantPass } from '@/lib/pass-experience'; +import { passRequest } from './pass-client'; +import PassIssued from './PassIssued'; +import styles from './PassIssued.module.css'; +import { REGISTRATION_PREVIEW_ENABLED } from '@/config/launch'; + +interface EntryPassCardProps { + onContinue?: () => void; + previewPass?: ParticipantPass; } -type Load = - | { state: 'loading' } - | { state: 'error'; message: string } - | { state: 'ready'; pass: PassInfo; qr: string | null }; - -const GOLD = 'oklch(0.8 0.12 85)'; -const box: React.CSSProperties = { - marginBottom: '18px', - padding: '16px', - background: 'rgba(236,232,223,0.06)', - border: '1px solid rgba(236,232,223,0.12)', -}; -const label: React.CSSProperties = { margin: 0, fontSize: '12px', fontWeight: 700, letterSpacing: '.18em', color: GOLD }; -const text: React.CSSProperties = { margin: 0, fontSize: '14px', lineHeight: 1.5, color: 'rgba(236,232,223,0.8)' }; - -async function fetchPass(): Promise { - let token: string | undefined; - try { - token = (await getSupabase().auth.getSession()).data.session?.access_token; - } catch {} - const res = await fetch('/api/pass', { - method: 'POST', - headers: token ? { Authorization: `Bearer ${token}` } : {}, - cache: 'no-store', - }); - const body = await res.json().catch(() => ({})); - if (!res.ok || !body.pass) throw new Error(httpErrorMessage(res) || body.error || 'Could not load your entry pass.'); - return body.pass as PassInfo; -} - -async function downloadPdf(pass: PassInfo, qr: string) { - const { jsPDF } = await import('jspdf'); - const doc = new jsPDF({ unit: 'mm', format: 'a5' }); // 148 x 210 - const W = 148; - - doc.setFillColor(20, 19, 18); - doc.rect(0, 0, W, 210, 'F'); - doc.setTextColor(220, 183, 106); - doc.setFont('helvetica', 'bold'); - doc.setFontSize(10); - doc.text('NIT ROURKELA · TECHNO-MANAGEMENT FEST', W / 2, 16, { align: 'center' }); - doc.setTextColor(236, 232, 223); - doc.setFont('times', 'normal'); - doc.setFontSize(30); - doc.text('Innovision 2026', W / 2, 30, { align: 'center' }); - doc.setFont('times', 'italic'); - doc.setFontSize(13); - doc.text('The Celestial Odyssey', W / 2, 38, { align: 'center' }); - - doc.setFillColor(236, 232, 223); - doc.rect(29, 48, 90, 90, 'F'); - doc.addImage(qr, 'PNG', 32, 51, 84, 84); - - doc.setTextColor(220, 183, 106); - doc.setFont('helvetica', 'bold'); - doc.setFontSize(9); - doc.text('ENTRY PASS', W / 2, 150, { align: 'center' }); - doc.setTextColor(236, 232, 223); - doc.setFontSize(18); - doc.text(doc.splitTextToSize(pass.name || '', 120), W / 2, 160, { align: 'center' }); - doc.setFont('helvetica', 'normal'); - doc.setFontSize(12); - doc.text(`Registration ID ${pass.registrationId ?? ''}`, W / 2, 174, { align: 'center' }); - - doc.setFontSize(9); - doc.setTextColor(200, 196, 188); - doc.text( - doc.splitTextToSize('Show this pass together with your college ID card at the registration desk. Valid for one check-in. Do not share this QR.', 118), - W / 2, - 188, - { align: 'center' } - ); - doc.save(`Innovision-2026-entry-pass-${pass.registrationId ?? 'pass'}.pdf`); +export default function EntryPassCard({ onContinue, previewPass }: EntryPassCardProps) { + if (REGISTRATION_PREVIEW_ENABLED && previewPass) { + return ; + } + return ; } -export default function EntryPassCard() { - const [load, setLoad] = useState({ state: 'loading' }); +function AuthenticatedEntryPassCard({ onContinue }: EntryPassCardProps) { + const [pass, setPass] = useState(null); + const [error, setError] = useState(''); + const [loading, setLoading] = useState(true); const [attempt, setAttempt] = useState(0); - const [downloading, setDownloading] = useState(false); - const [downloadError, setDownloadError] = useState(''); useEffect(() => { let cancelled = false; - (async () => { + let busy = false; + + const load = async () => { + if (busy || document.visibilityState !== 'visible') return; + busy = true; + try { - const pass = await fetchPass(); - let qr: string | null = null; - if (pass.token) { - const QRCode = (await import('qrcode')).default; - qr = await QRCode.toDataURL(pass.token, { errorCorrectionLevel: 'M', margin: 2, width: 512 }); + const data = await passRequest('/api/pass'); + if (!data.pass) throw new Error('Could not load your registration details.'); + if (!cancelled) { + setPass(data.pass); + setError(''); + setLoading(false); } - if (!cancelled) setLoad({ state: 'ready', pass, qr }); } catch (err) { - if (!cancelled) setLoad({ state: 'error', message: err instanceof Error ? err.message : 'Could not load your entry pass.' }); + if (!cancelled) { + setError(err instanceof Error ? err.message : 'Could not connect to verify your pass.'); + setPass(null); + setLoading(false); + } + } finally { + busy = false; } - })(); + }; + + void load(); + const interval = setInterval(() => void load(), 15_000); + window.addEventListener('focus', load); + document.addEventListener('visibilitychange', load); + return () => { cancelled = true; + clearInterval(interval); + window.removeEventListener('focus', load); + document.removeEventListener('visibilitychange', load); }; }, [attempt]); - if (load.state === 'loading') { + // Loading state: never flash approved ticket while status is unknown + if (loading && !pass && !error) { return ( -
-

ENTRY PASS

-

Loading your entry pass…

+
+ ● Checking registration +

+ Checking your registration status with the backend… +

); } - if (load.state === 'error') { + // Network / Connection Error state + if (error && !pass) { return ( -
-

ENTRY PASS

-

{load.message}

+
+

Connection Error

+

{error}

); } - const { pass, qr } = load; - if (pass.registrationStatus !== 'confirmed' || pass.passStatus !== 'active' || !qr) { - const message = - pass.registrationStatus === 'pending' - ? 'Your entry QR appears here once the Registration Team confirms your registration.' - : pass.registrationStatus === 'rejected' - ? 'There is no entry pass for a declined registration. Please contact the help desk.' - : pass.passStatus === 'revoked' - ? 'This entry pass was cancelled. Please contact the help desk.' - : 'Your entry pass is not available yet. Please check again later.'; + if (!pass) return null; + return ; +} + +function PassState({ pass, onContinue, preview = false }: { pass: ParticipantPass; onContinue?: () => void; preview?: boolean }) { + // Unapproved states: Pending review or Rejected + if (!isApprovedPass(pass)) { + const isPending = pass.registrationStatus === 'pending'; + const isRejected = pass.registrationStatus === 'rejected'; + return ( -
-

ENTRY PASS

-

{message}

+
+
+ + {isPending ? '● Payment under review' : isRejected ? '✕ Registration declined' : '◌ Registration incomplete'} + + {pass.registrationId && ( + + ID: {pass.registrationId} + + )} +
+ +

+ {isPending + ? 'Payment Under Review' + : isRejected + ? 'Registration Not Approved' + : 'Pass Not Yet Issued'} +

+ +

+ {passStatusMessage(pass)} +

+ + {isPending && ( +
+ + VENUE + + + National Institute of Technology, Rourkela + +
+ )}
); } + // Approved state return ( -
-
-

ENTRY PASS

- {pass.checkedIn && ( - - CHECKED IN - - )} -
- {/* eslint-disable-next-line @next/next/no-img-element -- a locally generated data: URL, nothing to optimise */} - {`Entry -

- Show this QR together with your college ID card at the registration desk. Do not share it. -

- - {downloadError &&

{downloadError}

} -
+ ); } diff --git a/src/components/innovision/Innovision.tsx b/src/components/innovision/Innovision.tsx index cdaf878..fc2dc9c 100644 --- a/src/components/innovision/Innovision.tsx +++ b/src/components/innovision/Innovision.tsx @@ -22,6 +22,7 @@ import WorldNav from './WorldNav'; import Curtain from './Curtain'; import AboutPanel from './AboutPanel'; import ProfileOverlay from './ProfileOverlay'; +import RegistrationStatusSync from './RegistrationStatusSync'; import PhoneModal from './PhoneModal'; import EventPopup from './EventPopup'; import AdminDashboard from './AdminDashboard'; @@ -50,7 +51,7 @@ import { type EventItem, type GalleryPhoto, } from '@/lib/supabase'; -import { REGISTRATIONS_OPEN, REGISTRATIONS_SOON_PATH, MERCH_PATH } from '@/config/launch'; +import { REGISTRATIONS_OPEN, REGISTRATIONS_SOON_PATH, MERCH_PATH, REGISTRATION_PREVIEW_ENABLED } from '@/config/launch'; import { REGISTRATION_FEE, UPI_ID, UPI_PAY_LINK, UPI_QR_SRC } from '@/config/payment'; import { SKIP_INTRO_KEY } from '@/components/coming-soon/SkipIntroOnReturn'; import { isValidGoogleDriveUrl, GENDER_OPTIONS as GENDERS, normalizeReferralCode, REFERRAL_CODE_PATTERN } from '@/lib/validation'; @@ -353,17 +354,41 @@ export class Innovision extends Component { const isOpenRegister = search.get('open') === 'register' || window.location.hash === '#register'; const isOpenLogin = search.get('open') === 'login'; - // Registrations closed (src/config/launch.ts): a register deep link lands on the "opening soon" page instead. - if (!REGISTRATIONS_OPEN && (isOpenRegister || search.get('required') === 'register')) { + // Local dev shortcuts: ?preview=pass, #pass, #ticket or #receipt opens the boarding pass & ticket directly; ?preview=register or #dev-register opens the form + if (REGISTRATION_PREVIEW_ENABLED && (search.get('preview') === 'pass' || window.location.hash === '#pass' || window.location.hash === '#ticket' || window.location.hash === '#receipt')) { + setTimeout(() => this.devOpenPass(), 600); + } else if (REGISTRATION_PREVIEW_ENABLED && (search.get('preview') === 'register' || window.location.hash === '#dev-register')) { + setTimeout(() => this.devOpenRegister(), 600); + } else if (!REGISTRATIONS_OPEN && (isOpenRegister || search.get('required') === 'register')) { this.showRegistrationsSoon(true); } else if (isAuthRequired) { // Remembered across the Google sign-in round trip, so the student lands on the form once signed in, and a // volunteer sent here by the check-in scanner ("Log in again") goes straight back to /admin/scan. const required = search.get('required'); if (required === 'register' || required === 'scan') sessionStorage.setItem('inv_pending_action', required); - setTimeout(() => { - this.openAuth('login'); - this.toast(required === 'scan' ? 'Please log in again to continue scanning.' : 'Please log in to register.'); + + // Clean auth and required query params from URL so they don't loop on refresh + try { + const cleanParams = new URLSearchParams(window.location.search); + cleanParams.delete('auth'); + cleanParams.delete('required'); + const cleanQuery = cleanParams.toString(); + window.history.replaceState(null, '', window.location.pathname + (cleanQuery ? `?${cleanQuery}` : '') + window.location.hash); + } catch {} + + setTimeout(async () => { + if (!this._authReady.done) await this._authReady.p; + if (!this.alive) return; + if (!this.state.user) { + this.openAuth('login'); + this.toast(required === 'scan' ? 'Please log in again to continue scanning.' : 'Please log in to register.'); + } else if (required === 'scan') { + this.leaveTo('/admin/scan', true); + } else if (this.state.registration || this.pass) { + this.openAuth('pass'); + } else { + this.openAuth('register'); + } }, 1200); } else if (isOpenRegister) { // Waits for the session check, so a signed-in student isn't sent to log in first. @@ -1431,6 +1456,7 @@ export class Innovision extends Component { } onKey(e: KeyboardEvent) { const s = this.state; + if (s.auth || s.profileOpen || s.phoneModalOpen) return; if (e.key === 'Escape' && s.eventPop != null && s.view === 'detail') { this.setState({ eventPop: null }); return; } if (e.key === 'Escape' && (s.about || s.menu)) { this.setState({ about: false, menu: false }); return; } const v = s.view; @@ -1744,7 +1770,7 @@ export class Innovision extends Component { college: registration.college, id: registration.registration_id, email: registration.email, - status: (registration.status || 'CONFIRMED').toUpperCase(), + status: (registration.status || 'pending').toUpperCase(), utr: registration.utr, }; } @@ -1789,6 +1815,17 @@ export class Innovision extends Component { } }; + syncRegistration = (registration: Registration | null) => { + if (!this.alive || (registration && registration.user_id !== this.state.user?.id)) return; + if (JSON.stringify(registration) === JSON.stringify(this.state.registration)) return; + this.pass = registration ? { + name: registration.name, college: registration.college, id: registration.registration_id, + email: registration.email, status: registration.status.toUpperCase(), utr: registration.utr, + } : null; + this.setState({ registration }); + if (registration?.status === 'confirmed' && this.state.authMode === 'pass') this.authSpin(false); + }; + refreshUserProfile = async (userId: string) => { const epoch = this._authEpoch; try { @@ -1990,7 +2027,7 @@ export class Innovision extends Component { const sc = this.$('[data-auth-scroll]'); if (sc) sc.scrollTop = 0; const ins = this.$$('[data-a-in]'), ui = this.$('[data-a-ui]'), planet = this.$('[data-a-planet-wrap]'); g.set(root, { autoAlpha: 1, pointerEvents: 'auto' }); - this.authSpin(true); + this.authSpin(mode !== 'pass'); g.set(planet, { rotation: -Math.min(this.state.step, 4) * 26 }); if (this.reduce) { sec.style.clipPath = 'none'; @@ -2070,6 +2107,7 @@ export class Innovision extends Component { } // @ts-ignore focusAuth() { + if (this.state.authMode === 'pass') { this.$('[data-auth]')?.focus({ preventScroll: true }); return; } if (matchMedia('(pointer: coarse)').matches) return; // @ts-ignore const el = this.$$('[data-auth] input').find((i) => i.type !== 'file' && i.offsetParent); @@ -2107,7 +2145,7 @@ export class Innovision extends Component { } - playClick(); + if (m !== 'pass') playClick(); this.setState({ authMode: m, step: m === 'pass' ? 4 : s.step, err: {}, gErr: '' }, () => { if (m === 'pass') { this.passReveal(); @@ -2177,6 +2215,13 @@ export class Innovision extends Component { if (old && old.url && old.url.startsWith('blob:')) URL.revokeObjectURL(old.url); const previewUrl = isImg ? URL.createObjectURL(f) : ''; + if (REGISTRATION_PREVIEW_ENABLED && this.state.user?.id === 'dev-preview-user') { + this.setState((st) => ({ + files: { ...st.files, [kind]: { name: f.name, size: f.size, url: previewUrl, pdf: false, status: 'done', remotePath: 'preview/local-only' } }, + err: this.drop(st.err, ek), + })); + return; + } this.setState( (st) => ({ files: { ...st.files, [kind]: { name: f.name, size: f.size, url: previewUrl, pdf: !isImg, status: 'up' } }, @@ -2289,6 +2334,10 @@ export class Innovision extends Component { const files = s.files || {}; const user = s.user; const isInternal = (user?.student_type === 'internal') || (user?.email?.toLowerCase().endsWith('@nitrkl.ac.in')); + if (user?.id === 'dev-preview-user' && !REGISTRATION_PREVIEW_ENABLED) { + this.toast('Preview is disabled. Please sign in with Google.'); + return; + } if (s.authMode === 'login') { const em = v('lemail'), id = v('lid').toUpperCase().replace(/\s+/g, ''); @@ -2333,7 +2382,7 @@ export class Innovision extends Component { if (s.step === 0) { const name = v('name').replace(/\s+/g, ' '); - const college = isInternal ? 'National Institute of Technology, Rourkela' : v('college').replace(/\s+/g, ' '); + const college = v('college').replace(/\s+/g, ' '); const email = user.email; // LOCKED - CANNOT BE ALTERED const phone = v('phone').replace(/\D/g, '').replace(/^(91|0)(?=\d{10}$)/, ''); const enrollment_no = v('enrollment_no'); @@ -2342,13 +2391,13 @@ export class Innovision extends Component { if (name.length < 2) err.name = 'Tell us your full name.'; else if (name.length > 100) err.name = 'Keep your name under 100 characters.'; if (!GENDERS.some((g) => g.value === gender)) err.gender = 'Select your gender.'; - if (!isInternal && college.length < 3) { + if (college.length < 3) { err.college = 'Which college are you from?'; - } else if (!isInternal && college.length > 200) { + } else if (college.length > 200) { err.college = 'Keep the college name under 200 characters.'; } if (!/^[6-9]\d{9}$/.test(phone)) err.phone = 'Use a 10-digit Indian mobile number.'; - if (isInternal && !enrollment_no) err.enrollment_no = 'Enter your NIT Rourkela Roll / Enrollment number.'; + if (!enrollment_no) err.enrollment_no = 'Enter your college roll / enrollment number.'; else if (enrollment_no.length > 50 || (enrollment_no && !/^[A-Za-z0-9/_ -]+$/.test(enrollment_no))) { err.enrollment_no = 'Use only letters, numbers, spaces and / _ - (up to 50 characters).'; } @@ -2366,6 +2415,53 @@ export class Innovision extends Component { } else if (s.step === 1) { this.toStep(2); } else if (s.step === 2) { + if (REGISTRATION_PREVIEW_ENABLED && user.id === 'dev-preview-user') { + const utr = v('utr').replace(/\s+/g, ''); + if (!files.pay || files.pay.status !== 'done') err.payfile = 'Choose an image to preview the payment screenshot upload.'; + if (!/^\d{12}$/.test(utr)) err.utr = 'Enter a 12-digit UTR to test this step. No payment is submitted.'; + if (this.fail(err)) return; + this.wait('SUBMITTING', 600).then(() => { + const r = this.reg || {}; + const regId = 'PREVIEW-9042'; + this.pass = { + name: r.name || 'Alex Explorer', + college: r.college, + id: regId, + email: user.email, + status: 'PENDING', + utr, + }; + const mockReg = { + id: 'dev-reg-temp', + registration_id: regId, + user_id: user.id, + name: this.pass.name, + email: user.email, + college: this.pass.college, + phone: r.phone || '9876543210', + enrollment_no: r.enrollment_no, + gender: r.gender, + student_type: 'external' as const, + payment_proof_path: 'mock/proof.png', + utr, + amount: 999, + status: 'pending' as const, + referral_code: 'INNO-' + Math.floor(1000 + Math.random() * 9000), + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + }; + this.setState( + { + authMode: 'pass', + step: 4, + registration: mockReg as Registration, + busyLbl: '', + }, + () => this.passReveal() + ); + }); + return; + } const fp = files.pay, utr = v('utr').replace(/\s+/g, ''); if (!fp) err.payfile = 'Upload the screenshot of your payment.'; else if (fp.status === 'failed') err.payfile = 'Your screenshot did not upload. Use RETRY UPLOAD to send it again.'; @@ -2395,7 +2491,7 @@ export class Innovision extends Component { }; const saveRes = await createRegistration(regPayload); - const savedReg = saveRes.registration || (saveRes.success ? regPayload : null); + const savedReg = saveRes.registration; if (!savedReg) { const msg = saveRes.error || 'Registration failed'; this.toast(msg); @@ -2448,16 +2544,151 @@ export class Innovision extends Component { }; // @ts-ignore passReveal() { + this.authSpin(false); const sc = this.$('[data-auth-scroll]'); if (sc) sc.scrollTo({ top: 0, behavior: 'smooth' }); this.animPane(1, true); - if (this.reduce) return; - this.warp(1.8 / this.speed()); - gsap.to(this.$('[data-a-planet-wrap]'), { rotation: -4 * 26, duration: 1.8, ease: 'expo.out' }); - const w = this.$('[data-pass-wrap]'); - if (w) gsap.fromTo(w, { clipPath: 'inset(0% 0% 100% 0%)' }, { clipPath: 'inset(0% 0% 0% 0%)', duration: 1.2, ease: 'expo.out', delay: .1, onComplete: () => gsap.set(w, { clearProps: 'clipPath' }) }); - setTimeout(() => this.scan('pass'), 260); } // @ts-ignore + devSkipToTicket = () => { + if (!REGISTRATION_PREVIEW_ENABLED || this.state.user?.id !== 'dev-preview-user') return; + const r = this.reg || {}; + const regId = 'IV26-' + Math.floor(1000 + Math.random() * 9000); + this.pass = { + name: r.name || 'Alex Explorer', + college: r.college || '', + id: regId, + email: (this.state.user as any)?.email || 'alex@nitrkl.ac.in', + status: 'CONFIRMED', + utr: '987654321098', + }; + const mockReg = { + id: 'dev-reg-temp', + registration_id: regId, + user_id: 'dev-preview-user', + name: this.pass!.name, + email: this.pass!.email, + college: this.pass!.college, + phone: r.phone || '9876543210', + enrollment_no: r.enrollment_no || '122MN0999', + gender: r.gender || 'Male', + student_type: 'internal' as const, + payment_proof_path: 'mock/proof.png', + utr: '987654321098', + amount: 999, + status: 'confirmed' as const, + referral_code: 'INNO-' + Math.floor(1000 + Math.random() * 9000), + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + }; + this.wait('SUBMITTING', 800).then(() => { + this.setState( + { + authMode: 'pass', + step: 4, + registration: mockReg as Registration, + busyLbl: '', + }, + () => this.passReveal() + ); + }); + }; + // @ts-ignore + devOpenPass = async () => { + if (!REGISTRATION_PREVIEW_ENABLED) return; + const mockUser: any = { + id: 'dev-preview-user', + email: 'alex.explorer@nitrkl.ac.in', + full_name: 'Alex Explorer', + student_type: 'internal', + role: 'user', + avatar_url: '', + phone: '9876543210', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + }; + const mockReg: any = { + id: 'dev-reg-1', + registration_id: 'PREVIEW-9042', + user_id: mockUser.id, + name: 'Alex Explorer', + email: mockUser.email, + college: 'Example Institute of Technology', + phone: '9876543210', + enrollment_no: '122MN0999', + gender: 'Male', + student_type: 'internal', + payment_proof_path: 'mock/payment.png', + utr: '987654321098', + amount: 999, + status: 'confirmed', + referral_code: 'INNO-CELESTIAL', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + }; + this.pass = { + name: mockReg.name, + college: mockReg.college, + id: mockReg.registration_id, + email: mockReg.email, + status: 'CONFIRMED', + utr: mockReg.utr, + }; + if (!this.state.auth) { + await this.openAuth('pass'); + } + this.setState( + { + user: mockUser, + registration: mockReg, + auth: true, + authMode: 'pass', + step: 4, + }, + () => this.passReveal() + ); + }; + + // @ts-ignore + devOpenRegister = async () => { + if (!REGISTRATION_PREVIEW_ENABLED) return; + const mockUser: any = { + id: 'dev-preview-user', + email: 'alex.explorer@nitrkl.ac.in', + full_name: 'Alex Explorer', + student_type: 'internal', + role: 'user', + avatar_url: '', + phone: '9876543210', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + }; + this.reg = { + name: 'Alex Explorer', + college: '', + phone: '9876543210', + enrollment_no: '122MN0999', + gender: 'Male', + referred_by_code: '', + }; + this.pass = null; + this.setState( + { + user: mockUser, + registration: null, + }, + async () => { + await this.openAuth('register'); + this.setState({ step: 0 }); + const sc = this.$('[data-auth-scroll]'); if (sc) sc.scrollTop = 0; + } + ); + }; + devApproveRegistration = () => { + if (!REGISTRATION_PREVIEW_ENABLED || this.state.user?.id !== 'dev-preview-user' || this.state.registration?.status !== 'pending') return; + this.pass = { ...this.pass, status: 'CONFIRMED' }; + this.setState((st) => ({ registration: { ...st.registration, status: 'confirmed' } }), () => this.passReveal()); + }; + // @ts-ignore clearErr = (e) => { const n = e.target && e.target.name; if (n && this.state.err[n]) this.setState((st) => ({ err: this.drop(st.err, n) })); @@ -2477,7 +2708,7 @@ export class Innovision extends Component { const isInternal = (user?.student_type === 'internal') || (user?.email?.toLowerCase().endsWith('@nitrkl.ac.in')); const regVals = { name: user?.full_name || R.name || '', - college: isInternal ? 'National Institute of Technology, Rourkela' : (R.college || ''), + college: R.college || s.registration?.college || '', email: user?.email || '', phone: user?.phone || R.phone || '', enrollment_no: user?.enrollment_no || s.registration?.enrollment_no || R.enrollment_no || '', @@ -2494,21 +2725,21 @@ export class Innovision extends Component { pick: this.pickFile(kind), over: this.dragOver(kind), leave: this.dragLeave(kind), drop: this.dropFile(kind), remove: () => this.removeFile(kind), replace: () => this.replaceFile(kind), retry: () => this.retryUpload(kind), }; }; - const showRail = reg || (am === 'pass' && st === 4); + const showRail = reg; const notes = [regVals.name, 'by UPI', 'Submitted']; // Same three steps for every student: there is no free tier. - const railSteps = [['DETAILS', 'Name, gender, college, phone', 'DETAILS'], ['PAYMENT', 'by UPI', 'PAY'], ['CONFIRM', 'Screenshot and transaction ID', 'CONFIRM']]; + const railSteps = [['DETAILS', 'Name, gender, college, phone', 'DETAILS'], ['PAYMENT', 'by UPI', 'PAY'], ['SUBMIT', 'Screenshot and transaction ID, then team review', 'SUBMIT']]; return { noUser: !s.user, hasUser: !!s.user, showLogin: !s.narrow, loginClick: this.loginClick, noDrop: (e) => e.preventDefault(), authHidden: String(!s.auth), authAria: reg ? 'Register for Innovision 2026' : am === 'login' ? 'Log in to Innovision' : 'Your boarding pass', authCols: s.narrow ? 'minmax(0,1fr)' : 'minmax(0,.9fr) minmax(0,1fr)', - authTitle: reg ? 'Claim your seat' : am === 'login' ? 'Welcome back' : "You're on board", + authTitle: reg ? 'Claim your seat' : am === 'login' ? 'Welcome back' : P.status === 'CONFIRMED' ? 'Your place in the odyssey' : P.status === 'REJECTED' ? 'Payment not approved' : 'Registration received', authSub: reg ? 'Three short stops to register for Innovision 2026 at NIT Rourkela.' - : am === 'login' ? 'Sign in using your Google account.' : 'Your boarding pass is ready. See you at NIT Rourkela.', + : am === 'login' ? 'Sign in or create your account with Google.' : P.status === 'CONFIRMED' ? 'Your payment is verified. Your INNO pass is always available here.' : P.status === 'REJECTED' ? 'Please contact the registration helpdesk for assistance.' : 'Your payment is under review by the registration team. Your pass appears here after approval.', railD: show(showRail && !s.narrow), hprogD: showRail && s.narrow ? 'grid' : 'none', prog: railSteps.map(([label, hint, short], k) => { const done = k < st, cur = k === st && reg, back = done && reg; @@ -2536,20 +2767,37 @@ export class Innovision extends Component { passName: P.name || '', passCollege: P.college || '', passCollegeD: P.college ? 'block' : 'none', passId: P.id || P.registration_id || '', passStatus: P.status ? P.status.toUpperCase() : 'PAYMENT UNDER REVIEW', // Mounted only while the pass is open, so the QR is fetched then and not on every page load. passQr: !!s.auth && am === 'pass' && !!s.user, + passUserId: s.user?.id, passNote: P.status === 'CONFIRMED' ? 'You are confirmed. Download your entry pass now and show the QR with your college ID at the registration desk, so entry at NIT Rourkela is quick.' : P.status === 'REJECTED' ? 'Your registration could not be approved. Please contact the helpdesk.' - : 'Your payment is being verified and your registration will be approved soon. Keep checking MY PASS: once approved, your entry QR appears here, ready to download.', + : 'Your payment is under review. Only the registration team can approve it. This page updates automatically while you are here.', // The registrant's own referral code, shared from the pass (not once the registration was rejected). refCode: String(P.status || '').toUpperCase() !== 'REJECTED' ? s.registration?.referral_code || '' : '', copyRefCode: this.copyReferral, refCodeLbl: s.refCopied ? 'COPIED' : 'COPY CODE', exploreFromPass: this.exploreFromPass, googleLogin: this.googleLogin, gBusy: s.gBusy, gErr: s.gErr, gLbl: s.gBusy ? 'Waiting for Google…' : 'Continue with Google', - gNote: reg && st === 0 && s.user ? 'Signed in as ' + s.user.email + (isInternal ? ' (NIT RKL Student)' : '') + '.' : '', + gNote: reg && st === 0 && s.user ? 'Signed in as ' + s.user.email + '.' : '', regVals, isInternal, user: s.user, + isDev: REGISTRATION_PREVIEW_ENABLED, + isPreviewUser: REGISTRATION_PREVIEW_ENABLED && s.user?.id === 'dev-preview-user', + previewPending: REGISTRATION_PREVIEW_ENABLED && s.user?.id === 'dev-preview-user' && s.registration?.status === 'pending', + previewPass: REGISTRATION_PREVIEW_ENABLED && s.user?.id === 'dev-preview-user' && s.registration ? { + registrationStatus: s.registration.status, + passStatus: s.registration.status === 'confirmed' ? 'active' : 'none', + registrationId: s.registration.registration_id, + name: s.registration.name, + college: s.registration.college, + checkedIn: false, + token: null, + } : undefined, + devApproveRegistration: this.devApproveRegistration, + devOpenPass: this.devOpenPass, + devOpenRegister: this.devOpenRegister, + devSkipToTicket: this.devSkipToTicket, }; } linkGo = (e: MouseEvent) => { @@ -2787,6 +3035,7 @@ export class Innovision extends Component { // reads the live values through LiveV). Small overlays render with every update. return (
+ {s.user && (s.auth || s.profileOpen) && } diff --git a/src/components/innovision/PassIssued.module.css b/src/components/innovision/PassIssued.module.css new file mode 100644 index 0000000..5a85233 --- /dev/null +++ b/src/components/innovision/PassIssued.module.css @@ -0,0 +1,651 @@ +/* ═══════════════════════════════════════════ + Pass Experience — Premium Dark Ticket +═══════════════════════════════════════════ */ +.experience { + --paper: #ece8df; + --ink: #141312; + --gold: #c9a24a; + --gold2: #f0d07a; + --muted: rgba(236,232,223,.5); + --surround: #0a0908; + color: var(--paper); + width: 100%; + max-width: 100%; + margin: 0 auto; + min-width: 0; + position: relative; +} + +.issueHeader { max-width:920px; margin:0 auto 22px; text-align:center; } +.issueHeader .issueEyebrow { margin:0 0 8px; color:var(--gold); font:600 10px/1.4 ui-monospace,monospace; letter-spacing:.18em; } +.issueHeader h2 { margin:0; font:400 clamp(30px,4vw,44px)/1.1 var(--font-display),serif; overflow-wrap:anywhere; } +.issueHeader p { margin:10px 0 0; color:#ece8dfaa; font-size:14px; line-height:1.5; } + +/* ─── Feed / Clean ticket wrapper ─── */ +.feed { + position: relative; + border-radius: 0; + background: transparent; + border: none; + box-shadow: none; + padding: 0; + overflow: visible; +} + +/* ─── Ticket eject animation ─── */ +.paper { + position: relative; + transform-origin: bottom center; +} + +.revealing .paper { + animation: ticketEject 0.85s cubic-bezier(0.16, 1, 0.3, 1) both; +} + +.settled .paper { + transform: none; + opacity: 1; +} + +@keyframes ticketEject { + 0% { opacity: 0; transform: translateY(60px) scale(0.96); filter: blur(4px); } + 35% { opacity: 1; filter: blur(0); } + 68% { transform: translateY(-5px) scale(1.004); } + 100% { transform: translateY(0) scale(1); opacity: 1; } +} + +/* ═══════════════════════════════════════════ + THE TICKET — dark, premium, space-themed +═══════════════════════════════════════════ */ +.ticket { + position: relative; + background: #0e0c0b; + border-radius: 7px; + overflow: hidden; + color: var(--paper); + box-shadow: + inset 0 0 0 1px rgba(201,162,74,0.22), + inset 0 1px 0 rgba(255,255,255,0.06); +} + +/* Starfield dots texture — pure CSS */ +.ticketBg { + position: absolute; + inset: 0; + background-image: + radial-gradient(1px 1px at 18% 22%, rgba(236,232,223,0.45) 0%, transparent 100%), + radial-gradient(1px 1px at 55% 8%, rgba(236,232,223,0.3) 0%, transparent 100%), + radial-gradient(1.5px 1.5px at 82% 15%, rgba(201,162,74,0.4) 0%, transparent 100%), + radial-gradient(1px 1px at 7% 55%, rgba(236,232,223,0.25) 0%, transparent 100%), + radial-gradient(1px 1px at 92% 48%, rgba(236,232,223,0.3) 0%, transparent 100%), + radial-gradient(1px 1px at 33% 72%, rgba(236,232,223,0.2) 0%, transparent 100%), + radial-gradient(1.5px 1.5px at 68% 80%, rgba(201,162,74,0.25) 0%, transparent 100%), + radial-gradient(1px 1px at 45% 40%, rgba(236,232,223,0.15) 0%, transparent 100%), + linear-gradient(135deg, rgba(201,162,74,0.06) 0%, transparent 50%, rgba(30,20,10,0.4) 100%); + pointer-events: none; + z-index: 0; +} + +/* Gold foil top stripe */ +.foilBar { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: linear-gradient(90deg, + transparent 0%, + rgba(201,162,74,0.6) 20%, + rgba(240,208,122,0.95) 50%, + rgba(201,162,74,0.6) 80%, + transparent 100% + ); + z-index: 2; +} + +/* ─── Header ─── */ +.ticketHeader { + position: relative; + z-index: 1; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; + padding: 16px 20px 12px; + border-bottom: 1px solid rgba(201,162,74,0.18); + background: rgba(201,162,74,0.04); +} + +.brandGroup { + display: flex; + flex-direction: column; + gap: 3px; +} + +.brandFest { + font: 700 14px/1.2 monospace; + letter-spacing: .18em; + color: var(--gold2); + text-shadow: 0 0 20px rgba(201,162,74,0.4); +} + +.brandSub { + font: 700 8px/1.3 monospace; + letter-spacing: .14em; + color: rgba(201,162,74,0.6); + text-transform: uppercase; +} + +.statusVerified { + font: 700 10px/1 monospace; + letter-spacing: .14em; + color: #4ade80; + background: rgba(74,222,128,0.08); + border: 1px solid rgba(74,222,128,0.3); + padding: 5px 10px; + border-radius: 3px; + white-space: nowrap; + text-shadow: 0 0 12px rgba(74,222,128,0.4); + flex-shrink: 0; +} + +/* ─── Face / Body ─── */ +.face { + position: relative; + z-index: 1; + padding: 18px 20px 16px; + display: flex; + flex-direction: column; + gap: 16px; +} + +.nameSection { + display: flex; + flex-direction: column; + gap: 3px; +} + +.nameLabel { + margin: 0; + font: 700 9px/1 monospace; + letter-spacing: .2em; + color: var(--gold); + opacity: 0.7; +} + +.name { + margin: 0; + font: 600 clamp(26px, 3vw, 34px)/1.1 var(--font-display); + letter-spacing: -.01em; + color: #fff; + text-shadow: 0 2px 20px rgba(201,162,74,0.18); + overflow-wrap: anywhere; + word-break: break-word; +} + +.metaGrid { + display: flex; + flex-direction: column; + gap: 12px; +} + +.metaRow2 { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; +} + +.metaCol { + display: flex; + flex-direction: column; + gap: 3px; +} + +.label { + font: 700 8.5px/1 monospace; + letter-spacing: .16em; + color: rgba(201,162,74,0.55); + text-transform: uppercase; + margin: 0; +} + +.value { + font-size: 13px; + font-weight: 500; + line-height: 1.4; + color: rgba(236,232,223,0.88); + margin: 0; + overflow-wrap: anywhere; + word-break: break-word; +} + +.valueMono { + font: 700 13px/1.4 monospace; + letter-spacing: .06em; + color: var(--gold2); + margin: 0; + overflow-wrap: anywhere; +} + +/* ─── Perforation ─── */ +.perforation { + position: relative; + z-index: 1; + height: 18px; + display: flex; + align-items: center; + justify-content: center; + background: transparent; +} + +.perforation::before, +.perforation::after { + content: ''; + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 18px; + height: 18px; + border-radius: 50%; + background: var(--surround); + box-shadow: 0 0 0 1px rgba(201,162,74,0.15); + z-index: 1; +} + +.perforation::before { left: -9px; } +.perforation::after { right: -9px; } + +.perforationLine { + width: calc(100% - 24px); + border-top: 1px dashed rgba(201, 162, 74, 0.3); +} + +/* ─── Stub ─── */ +.stub { + position: relative; + z-index: 1; + display: flex; + align-items: center; + justify-content: space-between; + gap: 14px; + padding: 12px 20px 16px; + background: rgba(201,162,74,0.03); + border-top: 0; +} + +.stubLeft { + display: flex; + flex-direction: column; + gap: 4px; + min-width: 0; +} + +.admitOne { + font: 700 10px/1 monospace; + letter-spacing: .22em; + color: var(--gold); + opacity: 0.8; +} + +.stubId { + font: 700 clamp(15px,2vw,18px)/1.2 monospace; + letter-spacing: .06em; + color: #fff; + overflow-wrap: anywhere; +} + +/* ─── QR thumbnail — SMALL, tappable ─── */ +.qrThumb { + flex: none; + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + padding: 5px; + border: 1px solid rgba(201,162,74,0.4); + border-radius: 4px; + background: #fff; + cursor: pointer; + transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s; + box-shadow: 0 2px 8px rgba(0,0,0,0.3); +} + +.qrThumb:hover { + transform: scale(1.08); + border-color: var(--gold2); + box-shadow: 0 4px 16px rgba(201,162,74,0.35); +} + +.qrThumb img { + display: block; + width: 56px; + height: 56px; +} + +.qrThumbHint { + font: 700 7px/1 monospace; + letter-spacing: .1em; + color: rgba(20,19,18,0.45); + text-transform: uppercase; + white-space: nowrap; +} + +/* QR placeholder (not yet available) */ +.qrPlaceholder { + flex: none; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 70px; + height: 70px; + border: 1px dashed rgba(201,162,74,0.3); + border-radius: 4px; + color: rgba(201,162,74,0.4); +} + +/* ═══════════════════════════════════════════ + QR Lightbox +═══════════════════════════════════════════ */ +.qrLightbox { + position: fixed; + inset: 0; + z-index: 200; + display: flex; + align-items: center; + justify-content: center; + background: rgba(7,6,5,0.85); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + animation: fadeIn 0.15s ease; + cursor: pointer; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.qrLightboxInner { + background: #fff; + padding: 20px; + border-radius: 10px; + box-shadow: + 0 0 0 1px rgba(201,162,74,0.5), + 0 40px 100px rgba(0,0,0,0.7); + animation: popIn 0.2s cubic-bezier(0.34,1.56,0.64,1); + cursor: default; + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; +} + +@keyframes popIn { + from { transform: scale(0.78); opacity: 0; } + to { transform: scale(1); opacity: 1; } +} + +.qrLightboxInner img { + display: block; + width: min(72vw, 280px); + height: auto; +} + +.qrLightboxHint { + margin: 0; + font: 700 10px/1.4 monospace; + letter-spacing: .14em; + color: rgba(20,19,18,0.45); + text-transform: uppercase; + text-align: center; +} + +/* ═══════════════════════════════════════════ + Below-ticket elements +═══════════════════════════════════════════ */ +.quietLine { + margin: 14px 0 0; + text-align: center; + font: 400 15px/1.4 var(--font-display); + color: rgba(236,232,223,0.75); + letter-spacing: .04em; +} + +.actions { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 12px; + margin-top: 16px; +} + +.primaryBtn { + min-height: 48px; + padding: 12px 20px; + border: 1px solid var(--gold); + background: rgba(201,162,74,0.1); + color: var(--gold2); + font-size: 13px; + font-weight: 700; + letter-spacing: .08em; + cursor: pointer; + transition: background-color 0.2s, color 0.2s; + display: inline-flex; + align-items: center; + justify-content: center; + text-align: center; + border-radius: 3px; +} +.primaryBtn:hover { background: rgba(201,162,74,0.2); } + +.secondaryBtn { + min-height: 48px; + padding: 12px 20px; + border: 1px solid rgba(236,232,223,0.25); + background: transparent; + color: rgba(236,232,223,0.8); + font-size: 13px; + font-weight: 700; + letter-spacing: .08em; + cursor: pointer; + transition: border-color 0.2s, background-color 0.2s; + display: inline-flex; + align-items: center; + justify-content: center; + text-align: center; + border-radius: 3px; +} +.secondaryBtn:hover { border-color: var(--gold); background: rgba(201,162,74,0.05); } +.secondaryBtn:disabled { opacity: 0.5; cursor: not-allowed; } + +/* WhatsApp */ +.whatsappCard { + width: 100%; + max-width: 640px; + margin: 22px auto 0; + padding: 16px 20px; + border-radius: 8px; + background: linear-gradient(145deg, rgba(37,211,102,0.1) 0%, rgba(18,140,126,0.04) 100%), rgba(10,9,8,0.85); + border: 1px solid rgba(37,211,102,0.3); + box-shadow: 0 8px 24px rgba(0,0,0,0.4); + display: flex; + flex-direction: column; + gap: 10px; +} + +.whatsappHeader { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; +} + +.whatsappBadge { + display: inline-flex; + align-items: center; + gap: 6px; + font: 700 9.5px monospace; + letter-spacing: .15em; + text-transform: uppercase; + color: #25d366; +} + +.whatsappBadgeDot { + width: 7px; + height: 7px; + border-radius: 50%; + background: #25d366; + box-shadow: 0 0 6px #25d366; + animation: none; +} + +@keyframes pulseDot { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.4; transform: scale(0.82); } +} + +.whatsappVenue { + font: 700 9px monospace; + letter-spacing: .12em; + color: rgba(236,232,223,0.45); +} + +.whatsappTitle { + margin: 0; + font: 500 16px/1.25 var(--font-display); + color: #ECE8DF; +} + +.whatsappDesc { + margin: 3px 0 0; + font-size: 13px; + line-height: 1.45; + color: rgba(236,232,223,0.65); +} + +.whatsappBtn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-height: 46px; + padding: 0 18px; + border-radius: 4px; + background: #25d366; + color: #0b1a10; + text-decoration: none; + font-weight: 700; + font-size: 13px; + letter-spacing: .08em; + box-shadow: 0 4px 14px rgba(37,211,102,0.28); + transition: background-color 0.2s, transform 0.15s; + cursor: pointer; +} +.whatsappBtn:hover { background: #2ee06f; transform: translateY(-1px); } + +/* Skip button during reveal */ +.skipBtn { + position: absolute; + top: 10px; + right: 10px; + z-index: 20; + padding: 5px 10px; + background: rgba(14,12,11,0.8); + border: 1px solid rgba(201,162,74,0.3); + border-radius: 3px; + color: rgba(201,162,74,0.9); + font: 700 10px/1 monospace; + letter-spacing: .12em; + cursor: pointer; + transition: opacity 0.2s; + opacity: 0.75; +} +.skipBtn:hover { opacity: 1; } + +/* Misc */ +.qrHint { + font-size: 12px; + color: rgba(236,232,223,0.5); + margin: 10px 0 0; + text-align: center; + letter-spacing: .02em; +} + +.hint { + font-size: 13px; + color: rgba(236,232,223,0.6); + margin: 12px 0; +} + +.errorText { + font-size: 13px; + color: #f87171; + margin: 10px 0 0; + padding: 8px 12px; + background: rgba(239,68,68,0.08); + border: 1px solid rgba(239,68,68,0.25); + border-radius: 3px; +} + +/* Status boxes */ +.statusBox { + padding: 22px 20px; + background: rgba(236,232,223,0.03); + border: 1px solid rgba(236,232,223,0.12); + border-radius: 6px; + color: var(--paper); + width: 100%; + max-width: 480px; + margin: 0 auto; +} +.statusTitle { margin: 0; font: 500 18px/1.2 var(--font-display); color: #ECE8DF; } +.statusDesc { margin: 6px 0 0; font-size: 13.5px; line-height: 1.5; color: rgba(236,232,223,0.7); } + +.statusBadgePending { + display: inline-flex; align-items: center; gap: 5px; + font: 700 10.5px monospace; letter-spacing: .12em; + color: #facc15; background: rgba(250,204,21,0.08); + padding: 4px 8px; border-radius: 3px; border: 1px solid rgba(250,204,21,0.25); +} +.statusBadgeDeclined { + display: inline-flex; align-items: center; gap: 5px; + font: 700 10.5px monospace; letter-spacing: .12em; + color: #f87171; background: rgba(239,68,68,0.08); + padding: 4px 8px; border-radius: 3px; border: 1px solid rgba(239,68,68,0.25); +} + +.experience button:focus-visible, +.experience a:focus-visible { + outline: 2px solid var(--gold); + outline-offset: 3px; +} + +/* Reduced motion */ +@media (prefers-reduced-motion: reduce) { + .revealing .paper { animation: none; } + .paper { transition: none; } + .whatsappBadgeDot { animation: none; } +} + +/* Mobile */ +@media(min-width:681px) { + .whatsappCard { max-width:920px; display:grid; grid-template-columns:minmax(0,1fr) auto; gap:10px 24px; padding:18px 22px; margin-top:24px; background:rgba(236,232,223,.025); border-color:rgba(236,232,223,.13); box-shadow:none; } + .whatsappHeader { grid-column:1/-1; } + .whatsappBtn { align-self:center; white-space:nowrap; background:#c9a24a; border:1px solid #e6c675; color:#141312; box-shadow:none; font-size:13px; letter-spacing:.02em; } + .whatsappBtn:hover { background:#e6c675; transform:none; } +} +@media(max-width:680px) { + .issueHeader { max-width:440px; margin-bottom:20px; text-align:left; } + .issueHeader h2 { font-size:34px; } + .issueHeader p { max-width:34ch; font-size:13px; } + .whatsappCard { max-width:440px; margin-top:20px; padding:18px; border-color:rgba(236,232,223,.14); background:rgba(236,232,223,.025); box-shadow:none; } + .whatsappHeader { flex-wrap:wrap; }.whatsappVenue { display:none; } + .whatsappBadge { font-size:9px; letter-spacing:.08em; } + .whatsappBtn { background:#c9a24a; border:1px solid #e6c675; color:#141312; box-shadow:none; letter-spacing:.02em; } + .whatsappBtn:hover { background:#e6c675; } +} +@media (max-width: 420px) { + .metaRow2 { grid-template-columns: 1fr; gap: 10px; } + .actions { grid-template-columns: 1fr; } + .stub { flex-wrap: wrap; } +} diff --git a/src/components/innovision/PassIssued.tsx b/src/components/innovision/PassIssued.tsx new file mode 100644 index 0000000..c06af6f --- /dev/null +++ b/src/components/innovision/PassIssued.tsx @@ -0,0 +1,210 @@ +'use client'; + +import { useCallback, useEffect, useRef, useState } from 'react'; +import type { ParticipantPass } from '@/lib/pass-experience'; +import { WHATSAPP_COMMUNITY_URL } from '@/config/site'; +import { REGISTRATION_PREVIEW_ENABLED } from '@/config/launch'; +import PassTicket from './PassTicket'; +import { passRequest } from './pass-client'; +import styles from './PassIssued.module.css'; + +// Share pending claims across Strict Mode mounts and ordinary route remounts. +const presented = new Map(); +const claims = new Map }>(); + +interface PassIssuedProps { + pass: ParticipantPass; + qr: string | null; + onContinue?: () => void; + preview?: boolean; +} + +export default function PassIssued({ pass, qr, preview = false }: PassIssuedProps) { + const id = pass.registrationId || 'unknown'; + const isPreview = REGISTRATION_PREVIEW_ENABLED && preview; + const [phase, setPhase] = useState<'waiting' | 'revealing' | 'settled' | 'unavailable'>('waiting'); + const root = useRef(null); + const ackBusy = useRef(false); + + const acknowledge = useCallback(async () => { + if (isPreview) return; + const entry = presented.get(id); + if (!entry?.displayed || entry.acknowledged || ackBusy.current) return; + ackBusy.current = true; + try { + const data = await passRequest('/api/pass/experience', { action: 'acknowledge', claim: entry.claim }); + if (data.result === true) { + entry.acknowledged = true; + claims.delete(id); + } + } catch { + // Preserve the claim and retry on focus/connection recovery or a later visit. + } finally { + ackBusy.current = false; + } + }, [id, isPreview]); + + useEffect(() => { + let cancelled = false; + let started = false; + let timer: ReturnType | undefined; + let firstFrame = 0; + let secondFrame = 0; + const reduced = matchMedia('(prefers-reduced-motion: reduce)'); + + const show = (animate: boolean) => { + const moving = animate && !reduced.matches; + setPhase(moving ? 'revealing' : 'settled'); + // Acknowledge only after the actual pass has painted, never during loading. + firstFrame = requestAnimationFrame(() => { + secondFrame = requestAnimationFrame(() => { + if (cancelled) return; + const entry = presented.get(id); + if (entry) entry.displayed = true; + if (!moving) void acknowledge(); + }); + }); + if (moving) timer = setTimeout(() => { + if (!cancelled) { setPhase('settled'); void acknowledge(); } + }, 2400); + }; + + const check = async () => { + if (cancelled || started || document.visibilityState !== 'visible') return; + started = true; + if (isPreview) { show(true); return; } + const existing = presented.get(id); + if (existing?.acknowledged || existing?.displayed) { show(false); return; } + let pending = claims.get(id); + if (!pending) { + const claim = crypto.randomUUID(); + pending = { claim, request: passRequest('/api/pass/experience', { action: 'claim', claim }) }; + claims.set(id, pending); + } + try { + const data = await pending.request; + if (cancelled) return; + if (data.result === 'ineligible') { + claims.delete(id); + setPhase('unavailable'); + } else if (data.result === 'claimed') { + if (!presented.has(id)) presented.set(id, { claim: pending.claim, acknowledged: false, displayed: false }); + show(true); + } else { + claims.delete(id); + show(false); // Server says seen, or another tab owns presentation. + } + } catch { + claims.delete(id); + if (!cancelled) show(false); // Access to the approved pass survives an acknowledgement outage. + } + }; + void check(); + const onVisibility = () => { + if (document.visibilityState === 'visible') { void check(); void acknowledge(); } + else if (presented.get(id)?.displayed) { setPhase('settled'); void acknowledge(); } + }; + const onReduced = () => { + if (reduced.matches) { setPhase('settled'); void acknowledge(); } + }; + const onOnline = () => { void acknowledge(); }; + document.addEventListener('visibilitychange', onVisibility); + window.addEventListener('online', onOnline); + window.addEventListener('focus', onOnline); + reduced.addEventListener('change', onReduced); + return () => { + cancelled = true; + clearTimeout(timer); + cancelAnimationFrame(firstFrame); + cancelAnimationFrame(secondFrame); + document.removeEventListener('visibilitychange', onVisibility); + window.removeEventListener('online', onOnline); + window.removeEventListener('focus', onOnline); + reduced.removeEventListener('change', onReduced); + void acknowledge(); + }; + }, [id, acknowledge, isPreview]); + if (phase === 'unavailable') { + return ( +
+

Registration Status Updated

+

+ Your registration status has been updated. Please refresh your dashboard to view the latest status. +

+
+ ); + } + + return ( +
+
+

YOUR INNO PASS, ISSUED.

+

You’re in, {pass.name?.trim().split(/\s+/)[0]}.

+

Your payment has been verified by the registration team.

+
+ {/* Skip reveal button — only during eject animation */} + {phase === 'revealing' && ( + + )} + + {phase === 'waiting' ? ( +

Preparing your pass…

+ ) : ( + <> +
+
+ +
+
+ + {/* WhatsApp Community Card */} +
+
+ + + OFFICIAL ATTENDEES GROUP + + NIT ROURKELA +
+
+

Stay in the loop.

+

+ Event updates, schedule changes, and help from the team — all in the official community. +

+
+ + + Join the community + +
+ + )} + +
+ ); +} diff --git a/src/components/innovision/PassKeepsake.module.css b/src/components/innovision/PassKeepsake.module.css new file mode 100644 index 0000000..0b07f9a --- /dev/null +++ b/src/components/innovision/PassKeepsake.module.css @@ -0,0 +1,69 @@ +.card { + --pass-ink: #141312; + --pass-muted: #625b50; + position: relative; + width: 100%; + overflow: hidden; + color: var(--pass-ink); + background: radial-gradient(ellipse at top left, #faf6ed, transparent 70%), #ece8df; + border: 1px solid #d5cbb5; + border-radius: 14px; + box-shadow: 0 16px 42px #0003; + text-align: left; + font-family: var(--font-sans), sans-serif; +} +.brand { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:24px; border-top:5px solid #c9a24a; border-bottom:1px solid #d5cbb5; } +.brand > div { min-width:0; } +.overline { display:block; font:600 10px/1.5 ui-monospace, monospace; letter-spacing:.13em; color:var(--pass-muted); } +.brand strong { display:block; margin-top:5px; font-size:clamp(17px,4.8vw,23px); letter-spacing:.025em; } +.brand strong span { font-weight:400; } +.seal { flex:none; padding:7px 9px; border:1px solid #937339; border-radius:3px; color:#73551e; font:700 9px/1.45 ui-monospace, monospace; letter-spacing:.07em; text-align:center; transform:rotate(-5deg); } +.main { padding:28px 24px 24px; } +.name { margin:12px 0 24px; font:400 clamp(30px,8vw,44px)/1.12 var(--font-display), serif; letter-spacing:-.025em; overflow-wrap:anywhere; } +.details { display:grid; gap:20px; margin:0 0 0 4px; padding-left:20px; border-left:1px dashed #b7a786; } +.details > div { position:relative; } +.details > div::before { content:''; position:absolute; width:7px; height:7px; left:-24px; top:4px; border:1px solid #937339; border-radius:50%; background:#ece8df; } +.destination dd { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; } +.destination dd strong { font:600 23px/1.2 ui-monospace,monospace; letter-spacing:.05em; } +.destination dd span { font-size:13px; color:var(--pass-muted); } +.details dt { font:600 10px/1.5 ui-monospace, monospace; text-transform:uppercase; letter-spacing:.13em; color:var(--pass-muted); } +.details dd { margin:4px 0 0; font-size:15px; line-height:1.5; overflow-wrap:anywhere; } +.perforation { position:relative; height:20px; margin:0 14px; background:linear-gradient(to right,#a99d86 45%,transparent 0) center/8px 1px repeat-x; } +.perforation::before,.perforation::after { content:''; position:absolute; top:0; width:20px; height:20px; border-radius:50%; background:#0c0b0a; } +.perforation::before { left:-25px; }.perforation::after { right:-25px; } +.stub { display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:22px; padding:20px 24px 24px; } +.registration { min-width:0; flex:1 1 130px; } +.registration strong { display:block; margin-top:8px; font:600 18px/1.4 ui-monospace, monospace; overflow-wrap:anywhere; } +.registration p { margin:12px 0 0; max-width:24ch; font-size:12px; line-height:1.5; color:var(--pass-muted); } +.qr { flex:0 0 132px; text-align:center; margin-inline:auto; } +.qr svg { display:block; width:132px; height:132px; max-width:100%; background:white; } +.qr span { display:block; margin-top:6px; font:600 9px/1.4 ui-monospace, monospace; letter-spacing:.1em; color:var(--pass-muted); } +.footer { padding:16px 24px; border-top:1px solid #d5cbb5; text-align:center; font:400 18px/1.3 var(--font-display), serif; } +.footer small { display:block; margin-top:8px; font:500 9px/1.4 ui-monospace,monospace; color:var(--pass-muted); letter-spacing:.08em; } +/* A single, restrained ink/write glitch; the final frame is always the real text. */ +.name,.details dd,.registration strong { animation:inkWrite 1.65s steps(24,end) .25s both; } +.details dd { animation-delay:.42s; }.registration strong { animation-delay:.55s; } +@keyframes inkWrite { + 0% { clip-path:inset(0 100% 0 0); transform:translateX(0); text-shadow:none; } + 25% { clip-path:inset(0 76% 0 0); transform:translateX(-1px); text-shadow:1px 0 #b6955866; } + 29% { transform:translateX(1px); } + 50% { clip-path:inset(0 48% 0 0); transform:translateX(0); text-shadow:none; } + 70% { clip-path:inset(0 24% 0 0); transform:translateX(-.5px); text-shadow:.5px 0 #b6955866; } + 92%,100% { clip-path:inset(0); transform:none; text-shadow:none; } +} +@media(prefers-reduced-motion:reduce) { .name,.details dd,.registration strong { animation:none; } } +@media(max-width:360px) { + .brand,.main,.stub { padding-left:19px; padding-right:19px; } + .brand { gap:8px; }.brand strong { font-size:16px; }.seal { font-size:8px; } + .qr { flex-basis:116px; }.qr svg { width:116px; height:116px; } +} +@media print { + .name,.details dd,.registration strong { animation:none!important; clip-path:none!important; transform:none!important; text-shadow:none!important; } + .card { border-radius:6mm; box-shadow:none; background:#f6f2e9; break-inside:avoid; -webkit-print-color-adjust:exact; print-color-adjust:exact; } + .brand { padding:9mm; border-top-width:2mm; }.brand strong { font-size:22pt; }.overline { font-size:8pt; } + .seal { font-size:9pt; padding:3mm; }.main { padding:10mm 9mm; }.name { font-size:32pt; margin:5mm 0 8mm; } + .details { gap:6mm; }.details dt { font-size:8pt; }.details dd { font-size:12pt; } + .perforation::before,.perforation::after { background:#fff; }.stub { padding:6mm 9mm 8mm; gap:8mm; } + .registration strong { font-size:16pt; }.registration p { font-size:9pt; }.qr { flex-basis:38mm; }.qr svg { width:38mm; height:38mm; } + .footer { padding:6mm; font-size:16pt; } +} diff --git a/src/components/innovision/PassKeepsake.tsx b/src/components/innovision/PassKeepsake.tsx new file mode 100644 index 0000000..3a86be3 --- /dev/null +++ b/src/components/innovision/PassKeepsake.tsx @@ -0,0 +1,37 @@ +import { QRCodeSVG } from 'qrcode.react'; +import type { ParticipantPass } from '@/lib/pass-experience'; +import { VENUE_CITY } from '@/config/site'; +import styles from './PassKeepsake.module.css'; + +/** The readable, flat version of the pass, shared by phones and paper. */ +export default function PassKeepsake({ pass }: { pass: ParticipantPass }) { + return ( +
+
+
NIT ROURKELA PRESENTSINNOVISION 2026
+ PAYMENT
VERIFIED
+
+
+ YOUR INNO PASS, ISSUED. +

{pass.name}

+
+
From / College
{pass.college}
+
To / Venue
NITNIT Rourkela
+
+
+
+ ); +} diff --git a/src/components/innovision/PassTicket.tsx b/src/components/innovision/PassTicket.tsx new file mode 100644 index 0000000..474668e --- /dev/null +++ b/src/components/innovision/PassTicket.tsx @@ -0,0 +1,73 @@ +'use client'; + +import { isApprovedPass, type ParticipantPass } from '@/lib/pass-experience'; +import ApprovedPassTicket from './ApprovedPassTicket'; +import styles from './PassIssued.module.css'; + +export default function PassTicket({ pass }: { + pass: ParticipantPass; + qr: string | null; + onQrClick?: () => void; +}) { + if (isApprovedPass(pass)) return ; + // Pending approval state + return ( +
+
+ ); +} diff --git a/src/components/innovision/ProfileOverlay.tsx b/src/components/innovision/ProfileOverlay.tsx index 382d404..a8eb158 100644 --- a/src/components/innovision/ProfileOverlay.tsx +++ b/src/components/innovision/ProfileOverlay.tsx @@ -1,8 +1,10 @@ 'use client'; -import React, { useState } from 'react'; +import React, { useRef, useState } from 'react'; +import { useDialogFocus } from './useDialogFocus'; import type { UserProfile, Registration } from '@/lib/supabase'; import EntryPassCard from './EntryPassCard'; +import { REGISTRATION_PREVIEW_ENABLED } from '@/config/launch'; interface ProfileOverlayProps { isOpen: boolean; @@ -27,6 +29,8 @@ export default function ProfileOverlay({ onLogout, onUpdatePhone, }: ProfileOverlayProps) { + const dialog = useRef(null); + useDialogFocus(isOpen, dialog, onClose); const [editingPhone, setEditingPhone] = useState(false); const [phoneVal, setPhoneVal] = useState(user?.phone || ''); const [phoneError, setPhoneError] = useState(''); @@ -59,6 +63,8 @@ export default function ProfileOverlay({ return (
- + {open &&
+ +
}
; +} +createRoot(document.getElementById('root')!).render(); diff --git a/tests/browser/loader.cjs b/tests/browser/loader.cjs new file mode 100644 index 0000000..4a06a24 --- /dev/null +++ b/tests/browser/loader.cjs @@ -0,0 +1,9 @@ +/* eslint-disable @typescript-eslint/no-require-imports -- webpack loaders use the CommonJS loader API */ +const ts = require('typescript'); +module.exports = function(source) { + if (this.resourcePath.endsWith('.css')) { + const names = [...source.matchAll(/\.([a-zA-Z_][\w-]*)/g)].map(match => match[1]); + return `const s=document.createElement('style');s.textContent=${JSON.stringify(source)};document.head.append(s);export default ${JSON.stringify(Object.fromEntries(names.map(n => [n,n])))};`; + } + return ts.transpileModule(source, { compilerOptions: { jsx: ts.JsxEmit.ReactJSX, target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText; +}; diff --git a/tests/browser/pass.spec.ts b/tests/browser/pass.spec.ts new file mode 100644 index 0000000..850a774 --- /dev/null +++ b/tests/browser/pass.spec.ts @@ -0,0 +1,118 @@ +import { test, expect, type Page, type BrowserContext } from '@playwright/test'; +import { readFile } from 'node:fs/promises'; + +const approved = { registrationStatus: 'confirmed', passStatus: 'active', registrationId: 'IV26-1024', name: 'Ananya Priyadarshini Subramanian', college: 'International Institute of Engineering, Technology and Advanced Interdisciplinary Studies', token: 'opaque-real-token-fixture', checkedIn: false }; +async function backend(context: BrowserContext, initial = approved) { + const state = { pass: initial, seen: false, claimed: false, claims: 0, acks: 0 }; + await context.route('**/api/pass', route => { + expect(route.request().method()).toBe('POST'); + return route.fulfill({ json: { pass: state.pass } }); + }); + await context.route('**/api/pass/experience', route => { + const body = route.request().postDataJSON(); + if (body.action === 'acknowledge') { state.seen = true; state.acks++; return route.fulfill({ json: { result: true } }); } + state.claims++; + const result = state.seen ? 'seen' : state.claimed ? 'busy' : 'claimed'; state.claimed = true; + return route.fulfill({ json: { result } }); + }); + return state; +} +async function open(page: Page) { await page.goto('/'); await page.getByRole('button', { name: 'My pass', exact: true }).click(); } + +test('pending/rejected never reveal; approved data is personalized and persists', async ({ page, context }) => { + const state = await backend(context, { ...approved, registrationStatus: 'pending', token: '' }); + await open(page); await expect(page.getByText('Payment under review.', { exact: false })).toBeVisible(); + expect(state.claims).toBe(0); + state.pass = { ...approved, registrationStatus: 'rejected', token: '' }; + await page.evaluate(() => window.dispatchEvent(new Event('focus'))); + await expect(page.getByText('Your payment was not approved.', { exact: false })).toBeVisible(); + expect(state.claims).toBe(0); + state.pass = approved; + await page.evaluate(() => window.dispatchEvent(new Event('focus'))); + await expect(page.getByRole('heading', { name: 'You’re in, Ananya.' })).toBeVisible(); + await expect(page.locator('[data-pass-phase]')).toHaveAttribute('data-pass-phase', 'settled'); + await expect(page.getByRole('heading', { name: approved.name })).toBeVisible(); + await expect(page.getByText(approved.college, { exact: true })).toBeVisible(); + await expect.poll(() => state.acks).toBe(1); + await page.reload(); await page.getByRole('button', { name: 'My pass', exact: true }).click(); + await expect(page.locator('[data-pass-phase]')).toHaveAttribute('data-pass-phase', 'settled'); + await expect(page.getByRole('button', { name: 'SKIP', exact: true })).toHaveCount(0); +}); + +test('keyboard skip, focus restoration and a real PDF download', async ({ page, context }, testInfo) => { + const state = await backend(context); + await open(page); + const skip = page.getByRole('button', { name: 'SKIP', exact: true }); + await expect(skip).toBeVisible(); await skip.focus(); await page.keyboard.press('Enter'); + await expect(page.locator('[data-pass-phase]')).toHaveAttribute('data-pass-phase', 'settled'); + const downloadEvent = page.waitForEvent('download'); + await page.getByRole('button', { name: 'Save PDF', exact: true }).click(); + const download = await downloadEvent; + expect(download.suggestedFilename()).toBe('INNOVISION-IV26-1024.pdf'); + await download.saveAs(testInfo.outputPath('downloaded-pass.pdf')); + const bytes = await readFile((await download.path())!); + expect(bytes.subarray(0, 5).toString()).toBe('%PDF-'); + expect(bytes.length).toBeGreaterThan(10000); + await page.keyboard.press('Escape'); + await expect(page.getByRole('dialog')).toHaveCount(0); + await expect(page.getByRole('button', { name: 'My pass', exact: true })).toBeFocused(); + await expect.poll(() => state.acks).toBe(1); +}); + +test('reduced motion and long/unbroken text remain readable without horizontal overflow', async ({ page, context }) => { + await page.emulateMedia({ reducedMotion: 'reduce' }); + const name = 'Ananya '.repeat(12).trim(); const college = 'Institute'.repeat(23); + const state = await backend(context, { ...approved, name, college }); + await open(page); + await expect(page.locator('[data-pass-phase]')).toHaveAttribute('data-pass-phase', 'settled'); + await expect(page.getByRole('heading', { name, exact: true })).toBeVisible(); + expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true); + expect(await page.locator('article h3, article dd').evaluateAll(els => els.every(el => el.scrollWidth <= el.clientWidth))).toBe(true); + await expect.poll(() => state.acks).toBe(1); +}); + +test('parallel tabs elect one reveal', async ({ page, context }) => { + await backend(context); const second = await context.newPage(); + await Promise.all([open(page), open(second)]); + await expect.poll(async () => (await page.getByRole('button', { name: 'SKIP', exact: true }).count()) + (await second.getByRole('button', { name: 'SKIP', exact: true }).count())).toBe(1); + await expect(page.getByRole('heading', { name: approved.name })).toBeAttached(); + await expect(second.getByRole('heading', { name: approved.name })).toBeAttached(); +}); + +test('desktop stub detaches with the keyboard and retains the pass', async ({ page, context }) => { + test.skip((page.viewportSize()?.width ?? 0) <= 680, 'Phone pass is an immediately readable vertical card.'); + await backend(context); await open(page); + await expect(page.locator('[data-pass-phase]')).toHaveAttribute('data-pass-phase', 'settled'); + const stub = page.getByRole('button', { name: 'Tear off the stub' }); + await stub.focus(); await page.keyboard.press('Enter'); + await expect(page.getByRole('button', { name: 'Reattach the stub' })).toHaveAttribute('aria-pressed', 'true'); + await expect(page.getByRole('heading', { name: approved.name })).toBeVisible(); +}); + +test('ordinary close/reopen does not replay', async ({ page, context }) => { + const state = await backend(context); await open(page); + await expect.poll(() => state.acks).toBe(1); + await page.keyboard.press('Escape'); await page.getByRole('button', { name: 'My pass', exact: true }).click(); + await expect(page.locator('[data-pass-phase]')).toHaveAttribute('data-pass-phase', 'settled'); + await expect(page.getByRole('button', { name: 'SKIP', exact: true })).toHaveCount(0); + expect(state.acks).toBe(1); +}); + +test('claim-service failure preserves a static pass and PDF without a fake QR', async ({ page, context }) => { + await backend(context, { ...approved, token: '' }); + await context.route('**/api/pass/experience', route => route.fulfill({ status: 503, json: { error: 'Unavailable' } })); + await open(page); + await expect(page.locator('[data-pass-phase]')).toHaveAttribute('data-pass-phase', 'settled'); + await expect(page.getByRole('heading', { name: approved.name })).toBeVisible(); + await expect(page.getByRole('button', { name: 'Save PDF', exact: true })).toBeVisible(); + await expect(page.getByRole('button', { name: 'View entry QR' })).toHaveCount(0); +}); + +test('revocation between pass fetch and claim never celebrates', async ({ page, context }) => { + await backend(context); + await context.route('**/api/pass/experience', route => route.fulfill({ json: { result: 'ineligible' } })); + await open(page); + await expect(page.getByText('Registration Status Updated', { exact: true })).toBeVisible(); + await expect(page.getByRole('article')).toHaveCount(0); + await expect(page.getByRole('button', { name: 'SKIP', exact: true })).toHaveCount(0); +}); \ No newline at end of file diff --git a/tests/browser/serve-pass.cjs b/tests/browser/serve-pass.cjs new file mode 100644 index 0000000..1c9531d --- /dev/null +++ b/tests/browser/serve-pass.cjs @@ -0,0 +1,45 @@ +/* eslint-disable @typescript-eslint/no-require-imports -- standalone CommonJS webpack test runner */ +// Isolated component harness; no fixture routes or fake identities enter the Next.js app. +const path = require('node:path'); +const fs = require('node:fs'); +const http = require('node:http'); +const { webpack } = require('next/dist/compiled/webpack/webpack'); +const root = path.resolve(__dirname, '../..'); +const output = path.join(root, '.pass-test'); +webpack({ + mode: 'development', devtool: false, entry: path.join(__dirname, 'harness.tsx'), + plugins: [new webpack.DefinePlugin({ 'process.env.NEXT_PUBLIC_SITE_URL': 'undefined', 'process.env.VERCEL_ENV': 'undefined' })], + output: { path: output, filename: 'bundle.js', publicPath: '/' }, + resolve: { extensions: ['.tsx', '.ts', '.js'], alias: { '@/lib/supabase$': path.join(__dirname, 'session.ts'), '@': path.join(root, 'src') } }, + module: { rules: [{ test: /\.(tsx?|css)$/, exclude: /node_modules/, use: path.join(__dirname, 'loader.cjs') }] }, +}, (error, stats) => { + if (error || stats.hasErrors()) { console.error(error || stats.toString('errors-only')); process.exit(1); } + http.createServer((req, res) => { + const url = new URL(req.url, 'http://127.0.0.1:3191'); + const preview = new URL(req.headers.referer || 'http://127.0.0.1:3191').searchParams.get('preview'); + if (preview && req.method === 'POST' && url.pathname.startsWith('/api/pass')) { + res.setHeader('Content-Type', 'application/json; charset=utf-8'); + res.setHeader('Cache-Control', 'no-store'); + if (url.pathname === '/api/pass/experience') { + let body = ''; req.on('data', data => { body += data; }); + req.on('end', () => res.end(JSON.stringify({ result: JSON.parse(body).action === 'claim' ? 'claimed' : true }))); + } else res.end(JSON.stringify({ pass: { + registrationStatus: preview === 'pending' ? 'pending' : preview === 'rejected' ? 'rejected' : 'confirmed', + passStatus: preview === 'pending' || preview === 'rejected' ? 'none' : 'active', + registrationId: 'PREVIEW-ONLY', name: 'Sample Participant', college: 'Sample College', checkedIn: false, token: null, + } })); + return; + } + if (req.url === '/__shutdown' && req.method === 'POST') { + res.end('closed', () => setImmediate(() => process.exit(0))); return; + } + if (url.pathname === '/') { + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + return res.end(`
`); + } + const name = (req.url || '').slice(1); + const file = name === 'font.ttf' ? path.join(root, 'src/assets/fonts/DMSerifDisplay-Regular.ttf') : /^[\w.-]+\.js$/.test(name) ? path.join(output, name) : null; + if (!file || !fs.existsSync(file)) { res.statusCode = 404; return res.end(); } + res.setHeader('Content-Type', name.endsWith('.js') ? 'text/javascript; charset=utf-8' : 'font/ttf'); fs.createReadStream(file).pipe(res); + }).listen(3191, '127.0.0.1', () => console.log('Pass harness listening on 3191')); +}); diff --git a/tests/browser/session.ts b/tests/browser/session.ts new file mode 100644 index 0000000..45545dc --- /dev/null +++ b/tests/browser/session.ts @@ -0,0 +1,2 @@ +// Test-only transport boundary. Production still uses the authenticated Supabase session. +export const getSupabase = () => ({ auth: { getSession: async () => ({ data: { session: null } }) } }); diff --git a/tests/browser/teardown.ts b/tests/browser/teardown.ts new file mode 100644 index 0000000..6b37f39 --- /dev/null +++ b/tests/browser/teardown.ts @@ -0,0 +1,4 @@ +/** Close the isolated server directly; Windows process-tree termination can stall in restricted shells. */ +export default async function teardown() { + await fetch('http://127.0.0.1:3191/__shutdown', { method: 'POST' }).catch(() => {}); +} diff --git a/tests/unit/pass-experience.test.mjs b/tests/unit/pass-experience.test.mjs new file mode 100644 index 0000000..9e1fb72 --- /dev/null +++ b/tests/unit/pass-experience.test.mjs @@ -0,0 +1,67 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { readFile } from 'node:fs/promises'; +import { PGlite } from '@electric-sql/pglite'; +import { isApprovedPass, passStatusMessage } from '../../src/lib/pass-experience.ts'; + +const pass = { registrationStatus: 'confirmed', passStatus: 'active', registrationId: 'IV26-1024', name: 'A real participant', college: 'Their own college', token: null, checkedIn: false }; +test('only a complete, server-confirmed active pass is eligible; QR is optional', () => { + assert.equal(isApprovedPass(pass), true); + for (const registrationStatus of ['none', 'pending', 'rejected']) { + assert.equal(isApprovedPass({ ...pass, registrationStatus }), false); + assert.doesNotMatch(passStatusMessage({ ...pass, registrationStatus }), /payment has been verified/i); + } + for (const passStatus of ['none', 'revoked']) assert.equal(isApprovedPass({ ...pass, passStatus }), false); + for (const field of ['name', 'college', 'registrationId']) assert.equal(isApprovedPass({ ...pass, [field]: null }), false); +}); + +test('real PostgreSQL acknowledgement lifecycle, ownership, RLS, contention and lease recovery', async () => { + const db = new PGlite(); + try { + await db.exec(` + CREATE ROLE anon; CREATE ROLE authenticated; + CREATE SCHEMA auth; + CREATE FUNCTION auth.uid() RETURNS uuid LANGUAGE sql AS $$ SELECT nullif(current_setting('request.jwt.claim.sub', true), '')::uuid $$; + GRANT USAGE ON SCHEMA auth TO authenticated; + CREATE TABLE registrations (id uuid PRIMARY KEY, user_id uuid, registration_id text, name text, college text, status text, created_at timestamptz default now()); + CREATE TABLE entry_passes (id uuid PRIMARY KEY, registration_id uuid REFERENCES registrations(id), status text); + INSERT INTO registrations VALUES ('10000000-0000-0000-0000-000000000001','20000000-0000-0000-0000-000000000001','IV26-1024','Participant One','College One','pending',now()); + INSERT INTO registrations VALUES ('10000000-0000-0000-0000-000000000002','20000000-0000-0000-0000-000000000002','IV26-2048','Participant Two','College Two','confirmed',now()); + INSERT INTO entry_passes VALUES ('30000000-0000-0000-0000-000000000001','10000000-0000-0000-0000-000000000001','active'); + INSERT INTO entry_passes VALUES ('30000000-0000-0000-0000-000000000002','10000000-0000-0000-0000-000000000002','active'); + `); + await db.exec(await readFile(new URL('../../supabase/manual/pass_experience.sql', import.meta.url), 'utf8')); + // Idempotent migration, safe to apply alongside schema.sql. + await db.exec(await readFile(new URL('../../supabase/manual/pass_experience.sql', import.meta.url), 'utf8')); + const user = async n => db.exec(`SET ROLE authenticated; SET request.jwt.claim.sub = '20000000-0000-0000-0000-00000000000${n}';`); + const call = async (fn, n) => (await db.query(`select ${fn}($1::uuid) as result`, [`40000000-0000-0000-0000-00000000000${n}`])).rows[0].result; + await user(1); + assert.equal(await call('claim_pass_experience', 1), 'ineligible'); + assert.equal(await call('acknowledge_pass_experience', 1), false); + await assert.rejects(db.query('SELECT * FROM pass_experiences'), /permission denied/); + await db.exec("RESET ROLE; UPDATE registrations SET status='rejected' WHERE registration_id='IV26-1024';"); + await user(1); assert.equal(await call('claim_pass_experience', 1), 'ineligible'); + await db.exec("RESET ROLE; UPDATE registrations SET status='confirmed' WHERE registration_id='IV26-1024';"); + await user(1); + const competing = await Promise.all([call('claim_pass_experience', 1), call('claim_pass_experience', 2)]); + assert.deepEqual(competing.sort(), ['busy', 'claimed']); + assert.equal(await call('claim_pass_experience', 1), 'busy'); + await db.exec('RESET ROLE'); + assert.equal((await db.query('select seen_at from pass_experiences')).rows[0].seen_at, null, 'claiming/loading is not acknowledgement'); + await user(2); + assert.equal(await call('acknowledge_pass_experience', 1), false, 'another account cannot acknowledge the first account'); + assert.equal(await call('claim_pass_experience', 3), 'claimed'); + await user(1); + assert.equal(await call('acknowledge_pass_experience', 9), false, 'wrong tab claim cannot acknowledge'); + assert.equal(await call('acknowledge_pass_experience', 1), true); + assert.equal(await call('acknowledge_pass_experience', 1), true, 'idempotent acknowledgement'); + assert.equal(await call('claim_pass_experience', 2), 'seen', 'refresh/revisit never replays'); + await db.exec("RESET ROLE; UPDATE pass_experiences SET claim_until=now()-interval '1 minute' WHERE registration_id='10000000-0000-0000-0000-000000000002';"); + await user(2); assert.equal(await call('claim_pass_experience', 4), 'claimed', 'abandoned unpresented lease is recoverable'); + assert.equal(await call('acknowledge_pass_experience', 3), false, 'expired claimant cannot acknowledge a replacement claim'); + await db.exec('RESET ROLE'); + assert.deepEqual((await db.query('select status from registrations order by registration_id')).rows.map(r => r.status), ['confirmed', 'confirmed'], 'acknowledgement never changes payment status'); + await db.exec("SET ROLE authenticated; SET request.jwt.claim.sub = '';"); + await assert.rejects(call('claim_pass_experience', 1), /Sign in required/); + } finally { await db.close(); } +}); diff --git a/tests/unit/pass-transport.test.mjs b/tests/unit/pass-transport.test.mjs new file mode 100644 index 0000000..b8a7eea --- /dev/null +++ b/tests/unit/pass-transport.test.mjs @@ -0,0 +1,21 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { passRequestInit } from '../../src/lib/pass-experience.ts'; + +test('pass access uses the token-minting POST contract and never caches participant data', () => { + const options = passRequestInit(undefined, 'fixture-session'); + assert.equal(options.method, 'POST'); + assert.equal(options.cache, 'no-store'); + assert.equal(options.headers.Authorization, 'Bearer fixture-session'); + assert.equal(options.body, undefined); + assert.equal(options.headers['Content-Type'], undefined); +}); + +test('only explicit acknowledgement/claim bodies use a keepalive POST', () => { + const body = { action: 'acknowledge', claim: 'fixture-claim' }; + const options = passRequestInit(body, 'fixture-session'); + assert.equal(options.method, 'POST'); + assert.equal(options.keepalive, true); + assert.equal(options.headers['Content-Type'], 'application/json'); + assert.deepEqual(JSON.parse(options.body), body); +}); diff --git a/tests/unit/registration-details.test.mjs b/tests/unit/registration-details.test.mjs new file mode 100644 index 0000000..3a38db8 --- /dev/null +++ b/tests/unit/registration-details.test.mjs @@ -0,0 +1,28 @@ +import assert from 'node:assert/strict'; +import { test } from 'node:test'; +import { validateRegistrationInput } from '../../src/lib/security.ts'; + +const ownerId = '20000000-0000-4000-8000-000000000001'; +const details = { + name: 'Ananya Rao', college: ' Example Institute of Technology ', + phone: '9876543210', gender: 'female', enrollment_no: ' CS/2026-42 ', + payment_proof_path: `${ownerId}/30000000-0000-4000-8000-000000000001.jpg`, + utr: '123456789012', +}; + +test('registration retains the entered college and roll number', () => { + const result = validateRegistrationInput(details, { ownerId }); + assert.equal(result.ok, true); + assert.equal(result.data.college, 'Example Institute of Technology'); + assert.equal(result.data.enrollment_no, 'CS/2026-42'); +}); + +test('every participant must provide a college and a roll number', () => { + for (const field of ['college', 'enrollment_no']) { + for (const value of ['', ' ', undefined]) { + const result = validateRegistrationInput({ ...details, [field]: value }, { ownerId }); + assert.equal(result.ok, false); + assert.equal(result.field, field); + } + } +}); diff --git a/tsconfig.json b/tsconfig.json index 71253ff..cb104a6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,10 @@ "paths": { "@/*": [ "./src/*" + ], + "@/components/ui/*": [ + "./src/components/ui/*", + "./components/ui/*" ] } }, From 53167d4752b7df8b4c87702cab99bce8d971fd3e Mon Sep 17 00:00:00 2001 From: Abhijeet Date: Thu, 22 Oct 2026 03:12:21 +0530 Subject: [PATCH 2/3] Polish personalized pass and artwork-first reveal --- components/ui/event-ticket.tsx | 54 ++++++++----- docs/pass-experience.md | 5 +- .../innovision/ApprovedPassTicket.module.css | 3 +- .../innovision/ApprovedPassTicket.tsx | 33 ++++---- .../innovision/AuthOverlay.module.css | 9 ++- src/components/innovision/AuthOverlay.tsx | 78 +++++++++---------- src/components/innovision/Innovision.tsx | 47 +---------- .../innovision/PassIssued.module.css | 68 ++++++++-------- src/components/innovision/PassIssued.tsx | 2 +- .../innovision/PassKeepsake.module.css | 28 +++---- src/components/innovision/PassKeepsake.tsx | 16 ++-- src/components/innovision/PassTicket.tsx | 8 +- src/components/innovision/download-pass.ts | 15 ++-- src/components/ui/decrypt-text.module.css | 7 ++ src/components/ui/decrypt-text.tsx | 44 +++++++++++ src/config/site.ts | 1 + src/lib/decrypt-text.ts | 10 +++ tests/browser/pass.spec.ts | 10 ++- tests/unit/decrypt-text.test.mjs | 19 +++++ 19 files changed, 263 insertions(+), 194 deletions(-) create mode 100644 src/components/ui/decrypt-text.module.css create mode 100644 src/components/ui/decrypt-text.tsx create mode 100644 src/lib/decrypt-text.ts create mode 100644 tests/unit/decrypt-text.test.mjs diff --git a/components/ui/event-ticket.tsx b/components/ui/event-ticket.tsx index 5643ebb..93c1005 100644 --- a/components/ui/event-ticket.tsx +++ b/components/ui/event-ticket.tsx @@ -1,6 +1,7 @@ "use client" import * as React from "react" +import DecryptText from "@/components/ui/decrypt-text" /** * Event ticket — a two-sided pass. @@ -230,6 +231,7 @@ export type EventTicketProps = { showCoordinates?: boolean /** Use actual participant/registration fields instead of the reference's flight fields. */ registrationPass?: boolean + animateInfo?: boolean seq?: string featuring?: string /** The big thin line on the back. */ @@ -325,18 +327,23 @@ const CSS = [ ".lbp-qrbox>svg,.lbp-qrbox>img,.lbp-qrbox>canvas{display:block;width:100%;height:100%;max-width:none}", ".lbp-qrbox.is-empty{background:transparent;border:1px dashed var(--lbp-rule);font-family:var(--lbp-cond);font-size:1.4cqw;letter-spacing:.2em;opacity:.7}", ".lbp-sf{margin-top:1.45cqw;min-width:0}", - ".lbp-details{display:grid;grid-template-columns:1.5fr 1fr;gap:1.3cqw 2cqw;padding:1.6cqw 0;border-bottom:1px solid var(--lbp-rule)}", - ".lbp-details>div{min-width:0}.lbp-details>div:first-child{grid-column:1/-1}", - ".lbp-details .lbp-m{white-space:normal;overflow:visible;overflow-wrap:anywhere;font-size:1.4cqw;line-height:1.35}", - ".lbp-person{margin:0;font-family:var(--lbp-disp);font-weight:400;font-size:3cqw;line-height:1.1;overflow-wrap:anywhere}", - ".lbp-registration .lbp-details>div:nth-child(2) .lbp-m{font-family:var(--lbp-cond);text-transform:none;letter-spacing:0;font-weight:500}", - ".lbp-registration .lbp-main::after{content:'';position:absolute;right:13%;bottom:-8cqw;width:18cqw;height:18cqw;border:1px solid #89672b18;border-radius:50%;box-shadow:0 0 0 1.2cqw #89672b06;pointer-events:none}", - ".lbp-registration-grid .lbp-traveler{grid-column:span 2}.lbp-registration-grid .lbp-person{font-size:2.5cqw}", - ".lbp-registration-grid .lbp-m{line-height:1.3}.lbp-registration-grid .lbp-origin{font-family:var(--lbp-cond);font-size:1.3cqw;text-transform:none;letter-spacing:0}", + ".lbp-person{margin:0;font-family:var(--lbp-cond);font-weight:700;font-size:3cqw;line-height:1.15;letter-spacing:-.045em;overflow-wrap:anywhere}", + ".lbp-registration .lbp-main::after{content:'';position:absolute;right:13%;bottom:-8cqw;width:18cqw;height:18cqw;border:1px solid #78634318;border-radius:50%;box-shadow:0 0 0 1.2cqw #78634306;pointer-events:none}", + ".lbp-registration-grid .lbp-traveler{grid-column:span 2}.lbp-registration-grid .lbp-person{font-size:2.9cqw;animation:none!important}", + ".lbp-registration-grid .lbp-m{font-family:var(--lbp-cond);line-height:1.4;letter-spacing:0;text-transform:none;font-weight:600}.lbp-registration-grid .lbp-origin{font-size:1.4cqw;font-weight:500}", + ".lbp-registration-grid>.lbp-cell:nth-child(2) .lbp-m{font-family:var(--lbp-mono);font-weight:500}", + ".lbp-registration .lbp-stub .lbp-m{font-family:var(--lbp-cond);text-transform:none;letter-spacing:0;font-weight:600;line-height:1.3}", ".lbp-registration-grid>:nth-child(4){border-left:1px solid var(--lbp-rule);padding-left:1.2cqw}", ".lbp-registration-grid>:nth-child(3){border-left:0;padding-left:0}", ".lbp-registration-grid>:nth-child(n+3){border-top:1px solid var(--lbp-rule)}", ".lbp-registration .lbp-m{white-space:normal;overflow:visible;overflow-wrap:anywhere}.lbp-registration .lbp-tw{animation:none}", + ".lbp-registration .lbp-l{font-family:var(--lbp-mono);font-size:max(.76cqw,8px);line-height:1.2;letter-spacing:.1em;opacity:.65}", + ".lbp-registration .lbp-title,.lbp-registration .lbp-d{font-family:var(--lbp-cond);font-weight:650;text-transform:none;letter-spacing:-.025em;line-height:1.15}", + ".lbp-registration .lbp-night .lbp-at.lbp-d{max-width:38%;white-space:normal}.lbp-registration .lbp-night .lbp-title{white-space:nowrap;font-weight:700;letter-spacing:.04em;font-size:2.35cqw!important}", + ".lbp-registration .lbp-head{align-items:center;padding-bottom:1.1cqw}.lbp-back-brand strong{display:block;font-family:var(--lbp-cond);font-size:2.25cqw;letter-spacing:.04em;line-height:1.1;font-weight:800}.lbp-back-brand small{display:block;font-family:var(--lbp-mono);font-size:.65cqw;letter-spacing:.12em;margin-top:.5cqw;opacity:.65}", + ".lbp-date{text-align:right}.lbp-date strong{font:600 1.4cqw/1.2 var(--lbp-cond)}", + ".lbp-registration .lbp-foot .lbp-d{font-size:2.1cqw!important}.lbp-registration .lbp-foot>.lbp-qr{margin-left:auto}", + ".lbp-registration.lbp-info-static .lbp-v{animation:none!important}", ".lbp-stamp{position:absolute;left:33%;top:52%;padding:.35cqw;border:.2cqw solid var(--lbp-stamp);border-radius:.45cqw;color:var(--lbp-stamp);", "opacity:0;transform:rotate(-9deg);pointer-events:none;mix-blend-mode:multiply}", ".lbp-stamp>span{display:block;padding:.45cqw 1.1cqw;border:.08cqw solid var(--lbp-stamp);border-radius:.25cqw;text-align:center}", @@ -347,9 +354,8 @@ const CSS = [ ".lbp-back.is-torn .lbp-hint{opacity:0}", ".lbp-printed .lbp-v{animation:lbp-type .8s steps(14,end) both}", "@keyframes lbp-type{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}", - ".lbp-registration .lbp-printed .lbp-v,.lbp-registration .lbp-person,.lbp-registration .lbp-details .lbp-m{animation:lbp-ink-write 1.7s steps(24,end) both;animation-delay:.55s!important}", - ".lbp-registration .lbp-person{animation-delay:.35s!important}", - "@keyframes lbp-ink-write{0%{clip-path:inset(0 100% 0 0);transform:translateX(0);text-shadow:none}25%{clip-path:inset(0 76% 0 0);transform:translateX(-1px);text-shadow:1px 0 #b6955866}29%{transform:translateX(1px)}50%{clip-path:inset(0 48% 0 0);transform:translateX(0);text-shadow:none}70%{clip-path:inset(0 24% 0 0);transform:translateX(-.5px);text-shadow:.5px 0 #b6955866}92%,100%{clip-path:inset(0);transform:none;text-shadow:none}}", + ".lbp-registration .lbp-printed .lbp-v{animation:lbp-ink-write 1.7s steps(24,end) both;animation-delay:.55s!important}", + "@keyframes lbp-ink-write{0%{clip-path:inset(0 100% 0 0);transform:translateX(0);text-shadow:none}25%{clip-path:inset(0 76% 0 0);transform:translateX(-1px);text-shadow:1px 0 #c8b17a55}29%{transform:translateX(1px)}50%{clip-path:inset(0 48% 0 0);transform:translateX(0);text-shadow:none}70%{clip-path:inset(0 24% 0 0);transform:translateX(-.5px);text-shadow:.5px 0 #c8b17a55}92%,100%{clip-path:inset(0);transform:none;text-shadow:none}}", ".lbp-tw{animation:lbp-tw 3.4s ease-in-out infinite}", "@keyframes lbp-tw{0%,100%{opacity:1}50%{opacity:.2}}", ".lbp-ship{transition:transform .9s cubic-bezier(.2,.8,.2,1)}", @@ -363,7 +369,7 @@ const CSS = [ ".lbp-body{transform-box:fill-box;transform-origin:85% 50%;transition:transform .5s}", ".lbp-clarinet:hover .lbp-body{transform:rotate(-1.2deg)}", "@media (prefers-reduced-motion: reduce){.lbp-tilt,.lbp-flip,.lbp-stub,.lbp-ship,.lbp-body{transition-duration:.01ms}", - ".lbp-tw,.lbp-flame,.lbp-v,.lbp-stamp,.lbp-note,.lbp-person,.lbp-details .lbp-m{animation:none!important}.lbp-rocket:hover .lbp-flame{transform:none}}", + ".lbp-tw,.lbp-flame,.lbp-v,.lbp-stamp,.lbp-note,.lbp-person{animation:none!important}.lbp-rocket:hover .lbp-flame{transform:none}}", ].join("") function Star({ size }: { size: string }) { @@ -550,6 +556,7 @@ export default function EventTicket({ lon = 23.47314, showCoordinates = true, registrationPass = false, + animateInfo = true, seq = "SEQ 060 MFDBAN 974294U89", featuring = "Featuring all stars crew", headline = "Space Jazz", @@ -832,7 +839,7 @@ export default function EventTicket({ const at = (x: number, y: number): React.CSSProperties => ({ left: x / 10 + "%", top: (y / VIEW_H) * 100 + "%" }) return ( -
+
{title}
-
+
{date}
@@ -903,15 +910,20 @@ export default function EventTicket({
+ {registrationPass ? <> +
{title}PERSONAL EVENT PASS
+
Event date{date}
+ : <> {registrationPass ? "INNO PASS" : "Boarding pass"} {title} {tier} + }
{registrationPass ?
-
Passenger / Participant

{passenger}

+
Issued to

-
From / College
{from}
-
+
From · College
{from}
+
:
@@ -938,7 +950,7 @@ export default function EventTicket({
}
- {registrationPass ? "Arrival / Venue" : "Landing site"} + {registrationPass ? "Destination" : "Landing site"}
{site}
{showCoordinates &&
{dec}
} {seq} @@ -978,11 +990,11 @@ export default function EventTicket({ - {registrationPass ? "YOUR INNO PASS" : "Boarding pass"} + {registrationPass ? "INNOVISION 2026" : "Boarding pass"} {registrationPass ? <> - - + + diff --git a/docs/pass-experience.md b/docs/pass-experience.md index d1178c4..94476e7 100644 --- a/docs/pass-experience.md +++ b/docs/pass-experience.md @@ -27,7 +27,8 @@ The existing entry-pass tables/functions and a valid `ENTRY_PASS_ENCRYPTION_KEY` - Acknowledgement happens after the pass has painted, or an explicit skip. Navigation cleanup acknowledges only a presented pass. Failed acknowledgements retain the claim and retry on focus/connection recovery. No local-storage value is the source of truth. - Subsequent acknowledged visits show the static pass. Failure of the celebration service preserves access to the approved pass. - Phones receive a separate vertical card. Desktop retains the illustrated two-sided ticket. Long details use the flexible card when necessary. The real college is distinct from the NIT Rourkela venue. -- The text writes in once and settles in approximately 2.2 seconds. Reduced motion disables the effect. The registration ticket has no idle canvas rendering loop. +- Ticket details write in once; the participant's name briefly decrypts into its exact original text. The screen-reader name is always unchanged. Reduced motion disables both effects, and acknowledged revisits are static. The registration ticket has no idle canvas rendering loop. +- Desktop opens on the black artwork. The first switch to **Your pass** triggers its text reveal; it does not loop on later flips. Phones retain the vertical card. Registration accents use softened champagne-gold derived from the existing palette. Manrope carries the pass name and body details; monospace is reserved for labels and identifiers. The event date is 13 November 2026, with a clearly separated college-to-NIT route and venue-city coordinates. - **Save PDF** directly downloads a personalized PDF. PDF/QR export libraries are loaded only on click. Text is drawn with browser brand fonts before embedding, preserving Unicode names. The QR is included only when the backend supplies a token. The existing PNG export helper is retained for older callers. - Keyboard controls, visible focus and QR-dialog focus restoration remain available. Font license notices are retained. @@ -35,4 +36,4 @@ The existing entry-pass tables/functions and a valid `ENTRY_PASS_ENCRYPTION_KEY` `npm run typecheck`, focused ESLint checks, `npm test`, and `npm run build` verify types, compilation, registration validation, the POST transport contract, and real PostgreSQL approval/acknowledgement ownership, contention and lease recovery. -The optional `npm run test:pass` browser harness is separate from production and mocks only transport. Browser checks are not run when reviewing code without Chrome. These checks do not constitute a 1,000-user load test; production capacity depends on the deployed application and Supabase configuration. \ No newline at end of file +The optional `npm run test:pass` browser harness is separate from production and mocks only transport. Browser checks are not run when reviewing code without Chrome. These checks do not constitute a 1,000-user load test; production capacity depends on the deployed application and Supabase configuration. diff --git a/src/components/innovision/ApprovedPassTicket.module.css b/src/components/innovision/ApprovedPassTicket.module.css index 488f9a2..754ebe1 100644 --- a/src/components/innovision/ApprovedPassTicket.module.css +++ b/src/components/innovision/ApprovedPassTicket.module.css @@ -1,9 +1,10 @@ .root { width:100%; max-width:920px; margin-inline:auto; min-width:0; } +.preparing { aspect-ratio:1000/330; min-height:180px; } .root > article { max-width:560px; margin-inline:auto; } .actions { display:flex; justify-content:center; flex-wrap:wrap; gap:10px; margin-top:22px; } .actions button { min-height:46px; padding:12px 22px; border:1px solid #ece8df40; border-radius:6px; background:transparent; color:#ece8df; font:600 13px/1.4 var(--font-sans),sans-serif; cursor:pointer; transition:background-color .2s; } .actions button:hover { background:#ece8df10; }.actions .print { background:#ece8df; border-color:#ece8df; color:#141312; }.actions .print:hover { background:#fff8eb; } -.actions button:focus-visible { outline:2px solid #c9a24a; outline-offset:4px; }.actions button:disabled { opacity:.6; cursor:wait; } +.actions button:focus-visible { outline:2px solid #c8b17a; outline-offset:4px; }.actions button:disabled { opacity:.6; cursor:wait; } .note { margin:12px 0 0; text-align:center; font-size:12px; line-height:1.5; color:#ece8df99; } .dialog { width:calc(100% - 32px); max-width:380px; padding:26px; border:1px solid #ece8df30; background:#100f0e; color:#ece8df; border-radius:12px; } .largeQr { margin:8px auto; width:min(100%,280px); }.largeQr svg { display:block; width:100%; height:auto; }.qrName { margin:0; text-align:center; overflow-wrap:anywhere; font-size:16px; }.qrName span { display:inline-block; margin-top:6px; font:12px ui-monospace,monospace; color:#ece8df99; } diff --git a/src/components/innovision/ApprovedPassTicket.tsx b/src/components/innovision/ApprovedPassTicket.tsx index ca0d744..629fa64 100644 --- a/src/components/innovision/ApprovedPassTicket.tsx +++ b/src/components/innovision/ApprovedPassTicket.tsx @@ -6,18 +6,19 @@ import { QRCodeSVG } from 'qrcode.react'; import EventTicket from '@/components/ui/event-ticket'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'; import type { ParticipantPass } from '@/lib/pass-experience'; -import { VENUE_CITY } from '@/config/site'; +import { EVENT_DATE, VENUE_CITY } from '@/config/site'; import PassKeepsake from './PassKeepsake'; import styles from './ApprovedPassTicket.module.css'; -export default function ApprovedPassTicket({ pass }: { pass: ParticipantPass }) { +export default function ApprovedPassTicket({ pass, animate = false }: { pass: ParticipantPass; animate?: boolean }) { const [compact, setCompact] = useState(null); const [qrOpen, setQrOpen] = useState(false); const [saving, setSaving] = useState(false); const [saveError, setSaveError] = useState(''); + const [infoOpened, setInfoOpened] = useState(false); const qrButton = useRef(null); useEffect(() => { - const media = matchMedia('(max-width: 680px)'); + const media = matchMedia('(max-width: 900px)'); const update = () => setCompact(media.matches); update(); media.addEventListener('change', update); @@ -41,20 +42,20 @@ export default function ApprovedPassTicket({ pass }: { pass: ParticipantPass }) return (
{/* Only mount the illustrated canvas ticket on larger screens. */} - {compact !== false || (pass.name?.length ?? 0) > 70 || (pass.college?.length ?? 0) > 90 ? : ( + {compact === null ? - OPEN UPI APP + OPEN UPI APP
    -
  1. 1Scan the code with any UPI app.
  2. -
  3. 2Pay exactly ₹{v.fee}.
  4. -
  5. 3Screenshot the success screen. You'll upload it next.
  6. +
  7. 1Scan the code with any UPI app.
  8. +
  9. 2Pay exactly ₹{v.fee}.
  10. +
  11. 3Screenshot the success screen. You'll upload it next.
{v.isPreviewUser &&

Preview only: don’t make a payment. Continue to try the screenshot upload and 12-digit UTR fields.

}
@@ -223,19 +223,19 @@ export default function AuthOverlay({ v }: { v: V }) {
PAYMENT SCREENSHOT -
@@ -285,7 +285,7 @@ export default function AuthOverlay({ v }: { v: V }) { {v.isDev ? (
- REGISTRATION PREVIEW + REGISTRATION PREVIEW
@@ -369,7 +369,7 @@ export default function AuthOverlay({ v }: { v: V }) { clipPath: "polygon(12px 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,0 100%,0 12px)", transition: "background-color .4s,opacity .3s,color .3s", }} - style-hover="background:oklch(0.8 0.12 85)" + style-hover="background:oklch(0.78 0.075 85)" style-active="transform:scale(.98)" > {v.submitLbl} @@ -407,7 +407,7 @@ export default function AuthOverlay({ v }: { v: V }) { style={{ position: "relative", padding: "16px", background: "#ECE8DF", borderRadius: "10px", cursor: "default", - boxShadow: "0 0 0 2px oklch(0.8 0.12 85), 0 40px 100px rgba(0,0,0,0.7)", + boxShadow: "0 0 0 2px oklch(0.78 0.075 85), 0 40px 100px rgba(0,0,0,0.7)", animation: "popInLb .22s cubic-bezier(.34,1.56,.64,1)", display: "flex", flexDirection: "column", alignItems: "center", gap: "12px", }} diff --git a/src/components/innovision/Innovision.tsx b/src/components/innovision/Innovision.tsx index fc2dc9c..8ebbe50 100644 --- a/src/components/innovision/Innovision.tsx +++ b/src/components/innovision/Innovision.tsx @@ -2549,50 +2549,6 @@ export class Innovision extends Component { this.animPane(1, true); } // @ts-ignore - devSkipToTicket = () => { - if (!REGISTRATION_PREVIEW_ENABLED || this.state.user?.id !== 'dev-preview-user') return; - const r = this.reg || {}; - const regId = 'IV26-' + Math.floor(1000 + Math.random() * 9000); - this.pass = { - name: r.name || 'Alex Explorer', - college: r.college || '', - id: regId, - email: (this.state.user as any)?.email || 'alex@nitrkl.ac.in', - status: 'CONFIRMED', - utr: '987654321098', - }; - const mockReg = { - id: 'dev-reg-temp', - registration_id: regId, - user_id: 'dev-preview-user', - name: this.pass!.name, - email: this.pass!.email, - college: this.pass!.college, - phone: r.phone || '9876543210', - enrollment_no: r.enrollment_no || '122MN0999', - gender: r.gender || 'Male', - student_type: 'internal' as const, - payment_proof_path: 'mock/proof.png', - utr: '987654321098', - amount: 999, - status: 'confirmed' as const, - referral_code: 'INNO-' + Math.floor(1000 + Math.random() * 9000), - created_at: new Date().toISOString(), - updated_at: new Date().toISOString(), - }; - this.wait('SUBMITTING', 800).then(() => { - this.setState( - { - authMode: 'pass', - step: 4, - registration: mockReg as Registration, - busyLbl: '', - }, - () => this.passReveal() - ); - }); - }; - // @ts-ignore devOpenPass = async () => { if (!REGISTRATION_PREVIEW_ENABLED) return; const mockUser: any = { @@ -2698,7 +2654,7 @@ export class Innovision extends Component { // @ts-ignore authVals(s) { // @ts-ignore - const am = s.authMode, st = s.step, reg = am === 'register', show = (b) => (b ? 'flex' : 'none'), gold = 'oklch(0.8 0.12 85)', cream = '#ECE8DF', bad = 'oklch(0.74 0.15 35)'; + const am = s.authMode, st = s.step, reg = am === 'register', show = (b) => (b ? 'flex' : 'none'), gold = 'oklch(0.78 0.075 85)', cream = '#ECE8DF', bad = 'oklch(0.74 0.15 35)'; const E = Object.assign({ name: '', gender: '', college: '', email: '', phone: '', enrollment_no: '', referred_by_code: '', payfile: '', utr: '', lemail: '', lid: '', form: '' }, s.err); const bc = {}, inv = {}; // @ts-ignore @@ -2797,7 +2753,6 @@ export class Innovision extends Component { devApproveRegistration: this.devApproveRegistration, devOpenPass: this.devOpenPass, devOpenRegister: this.devOpenRegister, - devSkipToTicket: this.devSkipToTicket, }; } linkGo = (e: MouseEvent) => { diff --git a/src/components/innovision/PassIssued.module.css b/src/components/innovision/PassIssued.module.css index 5a85233..34e5c33 100644 --- a/src/components/innovision/PassIssued.module.css +++ b/src/components/innovision/PassIssued.module.css @@ -4,8 +4,8 @@ .experience { --paper: #ece8df; --ink: #141312; - --gold: #c9a24a; - --gold2: #f0d07a; + --gold: #c8b17a; + --gold2: #e4d3a4; --muted: rgba(236,232,223,.5); --surround: #0a0908; color: var(--paper); @@ -64,7 +64,7 @@ overflow: hidden; color: var(--paper); box-shadow: - inset 0 0 0 1px rgba(201,162,74,0.22), + inset 0 0 0 1px rgba(200,177,122,0.22), inset 0 1px 0 rgba(255,255,255,0.06); } @@ -75,13 +75,13 @@ background-image: radial-gradient(1px 1px at 18% 22%, rgba(236,232,223,0.45) 0%, transparent 100%), radial-gradient(1px 1px at 55% 8%, rgba(236,232,223,0.3) 0%, transparent 100%), - radial-gradient(1.5px 1.5px at 82% 15%, rgba(201,162,74,0.4) 0%, transparent 100%), + radial-gradient(1.5px 1.5px at 82% 15%, rgba(200,177,122,0.4) 0%, transparent 100%), radial-gradient(1px 1px at 7% 55%, rgba(236,232,223,0.25) 0%, transparent 100%), radial-gradient(1px 1px at 92% 48%, rgba(236,232,223,0.3) 0%, transparent 100%), radial-gradient(1px 1px at 33% 72%, rgba(236,232,223,0.2) 0%, transparent 100%), - radial-gradient(1.5px 1.5px at 68% 80%, rgba(201,162,74,0.25) 0%, transparent 100%), + radial-gradient(1.5px 1.5px at 68% 80%, rgba(200,177,122,0.25) 0%, transparent 100%), radial-gradient(1px 1px at 45% 40%, rgba(236,232,223,0.15) 0%, transparent 100%), - linear-gradient(135deg, rgba(201,162,74,0.06) 0%, transparent 50%, rgba(30,20,10,0.4) 100%); + linear-gradient(135deg, rgba(200,177,122,0.06) 0%, transparent 50%, rgba(30,20,10,0.4) 100%); pointer-events: none; z-index: 0; } @@ -95,9 +95,9 @@ height: 3px; background: linear-gradient(90deg, transparent 0%, - rgba(201,162,74,0.6) 20%, - rgba(240,208,122,0.95) 50%, - rgba(201,162,74,0.6) 80%, + rgba(200,177,122,0.6) 20%, + rgba(228,211,164,0.95) 50%, + rgba(200,177,122,0.6) 80%, transparent 100% ); z-index: 2; @@ -112,8 +112,8 @@ justify-content: space-between; gap: 12px; padding: 16px 20px 12px; - border-bottom: 1px solid rgba(201,162,74,0.18); - background: rgba(201,162,74,0.04); + border-bottom: 1px solid rgba(200,177,122,0.18); + background: rgba(200,177,122,0.04); } .brandGroup { @@ -126,13 +126,13 @@ font: 700 14px/1.2 monospace; letter-spacing: .18em; color: var(--gold2); - text-shadow: 0 0 20px rgba(201,162,74,0.4); + text-shadow: 0 0 20px rgba(200,177,122,0.4); } .brandSub { font: 700 8px/1.3 monospace; letter-spacing: .14em; - color: rgba(201,162,74,0.6); + color: rgba(200,177,122,0.6); text-transform: uppercase; } @@ -178,7 +178,7 @@ font: 600 clamp(26px, 3vw, 34px)/1.1 var(--font-display); letter-spacing: -.01em; color: #fff; - text-shadow: 0 2px 20px rgba(201,162,74,0.18); + text-shadow: 0 2px 20px rgba(200,177,122,0.18); overflow-wrap: anywhere; word-break: break-word; } @@ -204,7 +204,7 @@ .label { font: 700 8.5px/1 monospace; letter-spacing: .16em; - color: rgba(201,162,74,0.55); + color: rgba(200,177,122,0.55); text-transform: uppercase; margin: 0; } @@ -248,7 +248,7 @@ height: 18px; border-radius: 50%; background: var(--surround); - box-shadow: 0 0 0 1px rgba(201,162,74,0.15); + box-shadow: 0 0 0 1px rgba(200,177,122,0.15); z-index: 1; } @@ -257,7 +257,7 @@ .perforationLine { width: calc(100% - 24px); - border-top: 1px dashed rgba(201, 162, 74, 0.3); + border-top: 1px dashed rgba(200, 177, 122, 0.3); } /* ─── Stub ─── */ @@ -269,7 +269,7 @@ justify-content: space-between; gap: 14px; padding: 12px 20px 16px; - background: rgba(201,162,74,0.03); + background: rgba(200,177,122,0.03); border-top: 0; } @@ -302,7 +302,7 @@ align-items: center; gap: 4px; padding: 5px; - border: 1px solid rgba(201,162,74,0.4); + border: 1px solid rgba(200,177,122,0.4); border-radius: 4px; background: #fff; cursor: pointer; @@ -313,7 +313,7 @@ .qrThumb:hover { transform: scale(1.08); border-color: var(--gold2); - box-shadow: 0 4px 16px rgba(201,162,74,0.35); + box-shadow: 0 4px 16px rgba(200,177,122,0.35); } .qrThumb img { @@ -339,9 +339,9 @@ justify-content: center; width: 70px; height: 70px; - border: 1px dashed rgba(201,162,74,0.3); + border: 1px dashed rgba(200,177,122,0.3); border-radius: 4px; - color: rgba(201,162,74,0.4); + color: rgba(200,177,122,0.4); } /* ═══════════════════════════════════════════ @@ -371,7 +371,7 @@ padding: 20px; border-radius: 10px; box-shadow: - 0 0 0 1px rgba(201,162,74,0.5), + 0 0 0 1px rgba(200,177,122,0.5), 0 40px 100px rgba(0,0,0,0.7); animation: popIn 0.2s cubic-bezier(0.34,1.56,0.64,1); cursor: default; @@ -423,7 +423,7 @@ min-height: 48px; padding: 12px 20px; border: 1px solid var(--gold); - background: rgba(201,162,74,0.1); + background: rgba(200,177,122,0.1); color: var(--gold2); font-size: 13px; font-weight: 700; @@ -436,7 +436,7 @@ text-align: center; border-radius: 3px; } -.primaryBtn:hover { background: rgba(201,162,74,0.2); } +.primaryBtn:hover { background: rgba(200,177,122,0.2); } .secondaryBtn { min-height: 48px; @@ -455,7 +455,7 @@ text-align: center; border-radius: 3px; } -.secondaryBtn:hover { border-color: var(--gold); background: rgba(201,162,74,0.05); } +.secondaryBtn:hover { border-color: var(--gold); background: rgba(200,177,122,0.05); } .secondaryBtn:disabled { opacity: 0.5; cursor: not-allowed; } /* WhatsApp */ @@ -551,9 +551,9 @@ z-index: 20; padding: 5px 10px; background: rgba(14,12,11,0.8); - border: 1px solid rgba(201,162,74,0.3); + border: 1px solid rgba(200,177,122,0.3); border-radius: 3px; - color: rgba(201,162,74,0.9); + color: rgba(200,177,122,0.9); font: 700 10px/1 monospace; letter-spacing: .12em; cursor: pointer; @@ -604,8 +604,8 @@ .statusBadgePending { display: inline-flex; align-items: center; gap: 5px; font: 700 10.5px monospace; letter-spacing: .12em; - color: #facc15; background: rgba(250,204,21,0.08); - padding: 4px 8px; border-radius: 3px; border: 1px solid rgba(250,204,21,0.25); + color: #c8b17a; background: rgba(200,177,122,0.08); + padding: 4px 8px; border-radius: 3px; border: 1px solid rgba(200,177,122,0.25); } .statusBadgeDeclined { display: inline-flex; align-items: center; gap: 5px; @@ -631,8 +631,8 @@ @media(min-width:681px) { .whatsappCard { max-width:920px; display:grid; grid-template-columns:minmax(0,1fr) auto; gap:10px 24px; padding:18px 22px; margin-top:24px; background:rgba(236,232,223,.025); border-color:rgba(236,232,223,.13); box-shadow:none; } .whatsappHeader { grid-column:1/-1; } - .whatsappBtn { align-self:center; white-space:nowrap; background:#c9a24a; border:1px solid #e6c675; color:#141312; box-shadow:none; font-size:13px; letter-spacing:.02em; } - .whatsappBtn:hover { background:#e6c675; transform:none; } + .whatsappBtn { align-self:center; white-space:nowrap; background:#c8b17a; border:1px solid #e4d3a4; color:#141312; box-shadow:none; font-size:13px; letter-spacing:.02em; } + .whatsappBtn:hover { background:#e4d3a4; transform:none; } } @media(max-width:680px) { .issueHeader { max-width:440px; margin-bottom:20px; text-align:left; } @@ -641,8 +641,8 @@ .whatsappCard { max-width:440px; margin-top:20px; padding:18px; border-color:rgba(236,232,223,.14); background:rgba(236,232,223,.025); box-shadow:none; } .whatsappHeader { flex-wrap:wrap; }.whatsappVenue { display:none; } .whatsappBadge { font-size:9px; letter-spacing:.08em; } - .whatsappBtn { background:#c9a24a; border:1px solid #e6c675; color:#141312; box-shadow:none; letter-spacing:.02em; } - .whatsappBtn:hover { background:#e6c675; } + .whatsappBtn { background:#c8b17a; border:1px solid #e4d3a4; color:#141312; box-shadow:none; letter-spacing:.02em; } + .whatsappBtn:hover { background:#e4d3a4; } } @media (max-width: 420px) { .metaRow2 { grid-template-columns: 1fr; gap: 10px; } diff --git a/src/components/innovision/PassIssued.tsx b/src/components/innovision/PassIssued.tsx index c06af6f..4717a55 100644 --- a/src/components/innovision/PassIssued.tsx +++ b/src/components/innovision/PassIssued.tsx @@ -171,7 +171,7 @@ export default function PassIssued({ pass, qr, preview = false }: PassIssuedProp <>
- +
diff --git a/src/components/innovision/PassKeepsake.module.css b/src/components/innovision/PassKeepsake.module.css index 0b07f9a..1b3c774 100644 --- a/src/components/innovision/PassKeepsake.module.css +++ b/src/components/innovision/PassKeepsake.module.css @@ -1,28 +1,30 @@ .card { --pass-ink: #141312; - --pass-muted: #625b50; + --pass-muted: #655d50; position: relative; width: 100%; overflow: hidden; color: var(--pass-ink); - background: radial-gradient(ellipse at top left, #faf6ed, transparent 70%), #ece8df; - border: 1px solid #d5cbb5; + background: radial-gradient(ellipse at top left, #f7f8f8, transparent 70%), #eeede7; + border: 1px solid #d5cdbd; border-radius: 14px; box-shadow: 0 16px 42px #0003; text-align: left; font-family: var(--font-sans), sans-serif; } -.brand { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:24px; border-top:5px solid #c9a24a; border-bottom:1px solid #d5cbb5; } +.brand { display:flex; align-items:center; justify-content:space-between; gap:14px; padding:24px; border-top:5px solid #c8b17a; border-bottom:1px solid #d5cdbd; } .brand > div { min-width:0; } .overline { display:block; font:600 10px/1.5 ui-monospace, monospace; letter-spacing:.13em; color:var(--pass-muted); } .brand strong { display:block; margin-top:5px; font-size:clamp(17px,4.8vw,23px); letter-spacing:.025em; } .brand strong span { font-weight:400; } -.seal { flex:none; padding:7px 9px; border:1px solid #937339; border-radius:3px; color:#73551e; font:700 9px/1.45 ui-monospace, monospace; letter-spacing:.07em; text-align:center; transform:rotate(-5deg); } +.seal { flex:none; padding:7px 9px; border:1px solid #9b8660; border-radius:3px; color:#786343; font:700 9px/1.45 ui-monospace, monospace; letter-spacing:.07em; text-align:center; transform:rotate(-5deg); } .main { padding:28px 24px 24px; } -.name { margin:12px 0 24px; font:400 clamp(30px,8vw,44px)/1.12 var(--font-display), serif; letter-spacing:-.025em; overflow-wrap:anywhere; } -.details { display:grid; gap:20px; margin:0 0 0 4px; padding-left:20px; border-left:1px dashed #b7a786; } +.name { margin:10px 0 24px; font:700 clamp(29px,7.8vw,40px)/1.14 var(--font-sans), sans-serif; letter-spacing:-.045em; overflow-wrap:anywhere; } +.dateRow { display:flex; align-items:baseline; justify-content:space-between; gap:12px; padding:12px 24px; border-bottom:1px solid #d5cdbd; } +.dateRow span { font:500 9px/1.4 ui-monospace,monospace; letter-spacing:.12em; color:var(--pass-muted); }.dateRow strong { font-size:12px; font-weight:700; } +.details { display:grid; gap:20px; margin:0 0 0 4px; padding-left:20px; border-left:1px dashed #b5a78d; } .details > div { position:relative; } -.details > div::before { content:''; position:absolute; width:7px; height:7px; left:-24px; top:4px; border:1px solid #937339; border-radius:50%; background:#ece8df; } +.details > div::before { content:''; position:absolute; width:7px; height:7px; left:-24px; top:4px; border:1px solid #9b8660; border-radius:50%; background:#eeede7; } .destination dd { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; } .destination dd strong { font:600 23px/1.2 ui-monospace,monospace; letter-spacing:.05em; } .destination dd span { font-size:13px; color:var(--pass-muted); } @@ -38,20 +40,20 @@ .qr { flex:0 0 132px; text-align:center; margin-inline:auto; } .qr svg { display:block; width:132px; height:132px; max-width:100%; background:white; } .qr span { display:block; margin-top:6px; font:600 9px/1.4 ui-monospace, monospace; letter-spacing:.1em; color:var(--pass-muted); } -.footer { padding:16px 24px; border-top:1px solid #d5cbb5; text-align:center; font:400 18px/1.3 var(--font-display), serif; } +.footer { padding:16px 24px; border-top:1px solid #d5cdbd; text-align:center; font:600 15px/1.4 var(--font-sans), sans-serif; } .footer small { display:block; margin-top:8px; font:500 9px/1.4 ui-monospace,monospace; color:var(--pass-muted); letter-spacing:.08em; } /* A single, restrained ink/write glitch; the final frame is always the real text. */ -.name,.details dd,.registration strong { animation:inkWrite 1.65s steps(24,end) .25s both; } +.card[data-animate="true"] .details dd,.card[data-animate="true"] .registration strong { animation:inkWrite 1.65s steps(24,end) .25s both; } .details dd { animation-delay:.42s; }.registration strong { animation-delay:.55s; } @keyframes inkWrite { 0% { clip-path:inset(0 100% 0 0); transform:translateX(0); text-shadow:none; } - 25% { clip-path:inset(0 76% 0 0); transform:translateX(-1px); text-shadow:1px 0 #b6955866; } + 25% { clip-path:inset(0 76% 0 0); transform:translateX(-1px); text-shadow:1px 0 #c8b17a55; } 29% { transform:translateX(1px); } 50% { clip-path:inset(0 48% 0 0); transform:translateX(0); text-shadow:none; } - 70% { clip-path:inset(0 24% 0 0); transform:translateX(-.5px); text-shadow:.5px 0 #b6955866; } + 70% { clip-path:inset(0 24% 0 0); transform:translateX(-.5px); text-shadow:.5px 0 #c8b17a55; } 92%,100% { clip-path:inset(0); transform:none; text-shadow:none; } } -@media(prefers-reduced-motion:reduce) { .name,.details dd,.registration strong { animation:none; } } +@media(prefers-reduced-motion:reduce) { .name,.details dd,.registration strong { animation:none!important; } } @media(max-width:360px) { .brand,.main,.stub { padding-left:19px; padding-right:19px; } .brand { gap:8px; }.brand strong { font-size:16px; }.seal { font-size:8px; } diff --git a/src/components/innovision/PassKeepsake.tsx b/src/components/innovision/PassKeepsake.tsx index 3a86be3..5fb98f3 100644 --- a/src/components/innovision/PassKeepsake.tsx +++ b/src/components/innovision/PassKeepsake.tsx @@ -1,22 +1,24 @@ import { QRCodeSVG } from 'qrcode.react'; import type { ParticipantPass } from '@/lib/pass-experience'; -import { VENUE_CITY } from '@/config/site'; +import { EVENT_DATE, VENUE_CITY } from '@/config/site'; +import DecryptText from '@/components/ui/decrypt-text'; import styles from './PassKeepsake.module.css'; /** The readable, flat version of the pass, shared by phones and paper. */ -export default function PassKeepsake({ pass }: { pass: ParticipantPass }) { +export default function PassKeepsake({ pass, animate = false }: { pass: ParticipantPass; animate?: boolean }) { return ( -
+
NIT ROURKELA PRESENTSINNOVISION 2026
PAYMENT
VERIFIED
+
EVENT DATE{EVENT_DATE.label}
- YOUR INNO PASS, ISSUED. -

{pass.name}

+ ISSUED TO +

-
From / College
{pass.college}
-
To / Venue
NITNIT Rourkela
+
From · College
{pass.college}
+
To · Venue
NITNIT Rourkela