@@ -766,7 +768,20 @@ function renderFpp(groups) {
${panelHeader("FPP catalog", "Filter blocks and list cards on mobile, richer panel on desktop.")}
${["All", ...mockFppGroups.map((item) => item.group)]
- .map((item) => `
${escapeHtml(item)}`)
+ .map(
+ (item) => `
+
+ `,
+ )
.join("")}
@@ -916,12 +931,21 @@ function loginPage({ error = "" } = {}) {
DocLink rebuild ยท responsive shell
-
Clinical workflow that works on desktop and mobile.
-
The old app behavior is preserved in a cleaner layout with dashboard, orders, results, FPP, and settings routes.
+
Clinical workflow that stays fast on desktop and mobile.
+
The rebuilt shell keeps the old app's workflows intact, but removes the cramped mobile-only feel.
+
+ Built for doctors who move between screens
+ Orders, results, FPP, and account actions stay one click away.
+
-
Route structureLogin, dashboard, order flow, result flow, and account pages.
Responsive shellPersistent sidebar on desktop, bottom nav on mobile.
-
Clean interaction modelHTMX fragments plus server-rendered templates.
+
HTMX fragmentsDetail panels update without leaving the page.
+
API adapterLogin, orders, results, and save flows proxy upstream.
+
+
+
5 routesPublic + shell
+
3 flowsMost used actions
+
1 sessionCookie-backed auth
@@ -958,12 +983,20 @@ function splashPage() {
Starting DocLink
Loading workspace...
-
Checking session and routing into the right entry point.
+
Checking session state, then routing into the right clinical entry point.
+
+ Fast redirect
+ Users land on dashboard, login, or the error screen without extra clicks.
+
@@ -982,7 +1015,11 @@ function problemLoginPage() {
Login problem
Access needs attention.
-
Use this page when auth state is broken or a session expires.
+
Use this page when auth state is broken, expired, or the upstream login rejects credentials.
+
+ What to do
+ Re-enter credentials or wait for the upstream service to recover.
+
diff --git a/styles.css b/styles.css
index b4caa0f..7d6fc74 100644
--- a/styles.css
+++ b/styles.css
@@ -734,6 +734,52 @@ tr:last-child td {
gap: 18px;
}
+.auth-highlight {
+ display: grid;
+ gap: 6px;
+ margin-top: 18px;
+ padding: 16px 18px;
+ border-radius: 18px;
+ color: #effaf8;
+ background: rgba(255, 255, 255, 0.12);
+ border: 1px solid rgba(255, 255, 255, 0.14);
+}
+
+.auth-highlight strong {
+ font-size: 1rem;
+}
+
+.auth-highlight span {
+ line-height: 1.55;
+ opacity: 0.94;
+}
+
+.auth-mini-grid {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 12px;
+ margin-top: 18px;
+}
+
+.auth-mini-card {
+ padding: 14px 15px;
+ border-radius: 18px;
+ background: rgba(255, 255, 255, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.12);
+}
+
+.auth-mini-card strong {
+ display: block;
+ font-size: 1.05rem;
+}
+
+.auth-mini-card span {
+ display: block;
+ margin-top: 4px;
+ opacity: 0.86;
+ font-size: 0.88rem;
+}
+
.auth-form h2 {
margin: 0;
font-size: 1.9rem;
@@ -823,6 +869,10 @@ tr:last-child td {
box-shadow: var(--shadow-lg);
}
+.modal-card .panel-header {
+ margin-bottom: 18px;
+}
+
.desktop-only {
display: block;
}
@@ -908,6 +958,10 @@ tr:last-child td {
max-height: 100vh;
border-radius: 0;
}
+
+ .auth-mini-grid {
+ grid-template-columns: 1fr;
+ }
}
@media (max-width: 620px) {