diff --git a/src/app/field-guide/page.test.tsx b/src/app/field-guide/page.test.tsx
index b73f819..9351e3e 100644
--- a/src/app/field-guide/page.test.tsx
+++ b/src/app/field-guide/page.test.tsx
@@ -88,13 +88,13 @@ describe("FieldGuidePage", () => {
).toBeInTheDocument();
expect(
- within(previewSection).getByText(/required/i),
+ within(previewSection).getByRole("heading", { name: /^required$/i }),
).toBeInTheDocument();
expect(
- within(previewSection).getByText(/verify on site/i),
+ within(previewSection).getByRole("heading", { name: /^verify on site$/i }),
).toBeInTheDocument();
expect(
- within(previewSection).getByText(/recommended/i),
+ within(previewSection).getByRole("heading", { name: /^recommended$/i }),
).toBeInTheDocument();
expect(
@@ -133,9 +133,9 @@ describe("FieldGuidePage", () => {
within(previewSection).queryByText(/dock seal integrity audit/i),
).not.toBeInTheDocument();
- expect(
- within(previewSection).getByText(/FG-201/),
- ).toBeInTheDocument();
+ expect(within(previewSection).getAllByText(/FG-201/).length).toBeGreaterThan(
+ 0,
+ );
});
it("supports search-driven narrowing and empty-state feedback", async () => {
diff --git a/src/app/globals.css b/src/app/globals.css
index c23933d..d75cb45 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -9,6 +9,10 @@
--nav-height: 3.5rem;
--ops-accent: #0e7490;
--ops-accent-light: rgba(14, 116, 144, 0.08);
+ --reserve-accent: #0f766e;
+ --reserve-accent-light: rgba(15, 118, 110, 0.12);
+ --reserve-accent-soft: rgba(45, 212, 191, 0.09);
+ --reserve-ink: #134e4a;
--navigator-accent: #0891b2;
--navigator-accent-light: rgba(8, 145, 178, 0.12);
--navigator-accent-soft: rgba(34, 211, 238, 0.08);
@@ -68,6 +72,7 @@ body {
background-image:
radial-gradient(circle at top, rgba(251, 191, 36, 0.18), transparent 32%),
radial-gradient(circle at right 18%, rgba(8, 145, 178, 0.14), transparent 26%),
+ radial-gradient(circle at left 14%, rgba(15, 118, 110, 0.12), transparent 24%),
linear-gradient(180deg, #fcf8ef 0%, #f4efe7 52%, #ebe5d9 100%);
font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif;
}
@@ -130,9 +135,12 @@ a {
gap: 1rem;
min-height: var(--nav-height);
padding: 0.875rem 1.5rem;
- background: rgba(255, 251, 240, 0.86);
+ background:
+ linear-gradient(180deg, rgba(255, 251, 240, 0.92), rgba(255, 251, 240, 0.86)),
+ rgba(255, 251, 240, 0.86);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--line);
+ box-shadow: 0 10px 32px rgba(15, 23, 42, 0.05);
}
.app-nav__cluster {
@@ -147,7 +155,7 @@ a {
font-weight: 700;
letter-spacing: 0.24em;
text-transform: uppercase;
- color: rgba(8, 145, 178, 0.75);
+ color: rgba(15, 118, 110, 0.82);
}
.app-nav__brand {
@@ -184,14 +192,14 @@ a {
.app-nav__meta {
border-radius: 9999px;
- border: 1px solid rgba(8, 145, 178, 0.18);
+ border: 1px solid rgba(15, 118, 110, 0.18);
background: rgba(255, 255, 255, 0.58);
padding: 0.4rem 0.8rem;
font-size: 0.6875rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
- color: var(--navigator-ink);
+ color: var(--reserve-ink);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85);
}
@@ -275,6 +283,158 @@ a {
box-shadow: 0 8px 30px rgba(15, 23, 42, 0.12);
}
+/* ── Reserve-grid shared shell styles ─────────────────────── */
+
+.reserve-grid-shell {
+ position: relative;
+}
+
+.reserve-grid-callout,
+.reserve-grid-hero,
+.reserve-grid-panel {
+ position: relative;
+ isolation: isolate;
+}
+
+.reserve-grid-hero::before {
+ content: "";
+ position: absolute;
+ inset: auto auto 18% -8%;
+ width: 16rem;
+ height: 16rem;
+ border-radius: 9999px;
+ background: radial-gradient(circle, rgba(15, 118, 110, 0.16), transparent 68%);
+ filter: blur(8px);
+}
+
+.reserve-grid-hero::after {
+ content: "";
+ position: absolute;
+ inset: auto -4% -16% auto;
+ width: 18rem;
+ height: 18rem;
+ border-radius: 9999px;
+ background: radial-gradient(circle, rgba(251, 191, 36, 0.12), transparent 70%);
+}
+
+.reserve-grid-badge,
+.reserve-grid-pulse {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.45rem;
+ border-radius: 9999px;
+ padding: 0.4rem 0.85rem;
+ font-size: 0.6875rem;
+ font-weight: 700;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+}
+
+.reserve-grid-badge {
+ border: 1px solid rgba(15, 118, 110, 0.18);
+ background: rgba(255, 255, 255, 0.8);
+ color: var(--reserve-ink);
+}
+
+.reserve-grid-pulse {
+ border: 1px solid rgba(15, 118, 110, 0.18);
+ background: var(--reserve-accent-light);
+ color: var(--reserve-ink);
+}
+
+.reserve-grid-pulse::before {
+ content: "";
+ width: 0.45rem;
+ height: 0.45rem;
+ border-radius: 9999px;
+ background: var(--reserve-accent);
+ box-shadow: 0 0 0 0 rgba(15, 118, 110, 0.24);
+ animation: reserve-grid-pulse 2s ease-in-out infinite;
+}
+
+.reserve-grid-panel::after {
+ content: "";
+ position: absolute;
+ inset: auto 0 0 0;
+ height: 3px;
+ background: linear-gradient(
+ 90deg,
+ rgba(15, 118, 110, 0.75) 0%,
+ rgba(34, 211, 238, 0.38) 52%,
+ rgba(251, 191, 36, 0.55) 100%
+ );
+ opacity: 0.72;
+}
+
+.reserve-grid-zone-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+}
+
+.reserve-grid-zone-tab {
+ display: flex;
+ min-width: 10.5rem;
+ flex-direction: column;
+ border-radius: 1rem;
+ border: 1px solid rgba(148, 163, 184, 0.28);
+ background: rgba(255, 255, 255, 0.78);
+ padding: 0.9rem 1rem;
+ transition:
+ transform 0.2s ease,
+ border-color 0.2s ease,
+ box-shadow 0.2s ease,
+ background-color 0.2s ease;
+}
+
+.reserve-grid-zone-tab:hover {
+ transform: translateY(-1px);
+ border-color: rgba(15, 118, 110, 0.24);
+ box-shadow: 0 12px 28px rgba(15, 23, 42, 0.06);
+}
+
+.reserve-grid-zone-tab--active {
+ border-color: rgba(15, 118, 110, 0.26);
+ background: linear-gradient(180deg, rgba(240, 253, 250, 0.92), rgba(255, 255, 255, 0.88));
+ box-shadow: 0 14px 32px rgba(15, 118, 110, 0.08);
+}
+
+.reserve-grid-slot {
+ transition:
+ transform 0.2s ease,
+ border-color 0.2s ease,
+ box-shadow 0.2s ease;
+}
+
+.reserve-grid-slot:hover {
+ transform: translateY(-2px);
+ border-color: rgba(15, 118, 110, 0.24);
+ box-shadow: 0 18px 34px rgba(15, 118, 110, 0.1);
+}
+
+.reserve-grid-slot--active {
+ border-left: 3px solid rgba(15, 118, 110, 0.32);
+}
+
+.reserve-grid-status {
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.72);
+}
+
+.reserve-grid-ledger,
+.reserve-grid-signal {
+ border-left: 3px solid rgba(15, 118, 110, 0.24);
+}
+
+@keyframes reserve-grid-pulse {
+ 0%, 100% {
+ box-shadow: 0 0 0 0 rgba(15, 118, 110, 0.22);
+ }
+
+ 50% {
+ box-shadow: 0 0 0 0.35rem rgba(15, 118, 110, 0);
+ }
+}
+
/* ── Navigator-hub shared shell styles ────────────────────── */
.navigator-shell-card {
@@ -389,6 +549,16 @@ a {
.app-nav__meta {
display: none;
}
+
+ .reserve-grid-zone-list {
+ flex-wrap: nowrap;
+ overflow-x: auto;
+ padding-bottom: 0.15rem;
+ }
+
+ .reserve-grid-zone-tab {
+ min-width: 12rem;
+ }
}
/* ── Queue-monitor & parcel-hub shared styles ────────────── */
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index a2dd03d..6aaf7a1 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -19,11 +19,12 @@ export const metadata: Metadata = {
template: "%s | Archive Signals",
},
description:
- "Operational dashboards, navigator handoff surfaces, experiment registries, and field guides for archive-driven teams.",
+ "Operational dashboards, reserve-grid overlaps, navigator handoff surfaces, experiment registries, and field guides for archive-driven teams.",
};
const navLinks = [
{ href: "/", label: "Home" },
+ { href: "/reserve-grid", label: "Reserve Grid" },
{ href: "/navigator-hub", label: "Navigator Hub" },
{ href: "/team-directory", label: "Team Directory" },
{ href: "/archive-browser", label: "Archive" },
@@ -49,7 +50,7 @@ export default function RootLayout({