feat: free-tier credit system + Syttende Mai access for Google users
- FreeTier.php: credit check/deduct/reset engine with hourly rate limit - bootstrap.php: dbnmDb() singleton, dbnToolsIsFreeTier(), credit gate helpers - index.php: store tier=free|approved in session from SSO JWT - All 7 API endpoints: credit gate (402/429) + X-Credits-Remaining header - layout.php: credit meta tag, JS balance var, Syttende Mai banner (05-17 only) - tools.js: credit badge in topbar, 402 modal, 429 toast, dbnUpdateCredits() - barnevernet.js + deep-research.js: wire 402/429 handling for NDJSON streams - tools.css: styles for credit badge, no-credits modal, rate-limit toast Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4313,3 +4313,114 @@ body {
|
||||
.site-footer__inner { grid-template-columns: 1fr; }
|
||||
.site-footer__bottom { flex-direction: column; }
|
||||
}
|
||||
|
||||
/* ── Syttende Mai banner ──────────────────────────────────────────────────── */
|
||||
.syttende-mai-banner {
|
||||
background: #ba0c2f;
|
||||
color: #fff;
|
||||
padding: 9px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.01em;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
}
|
||||
.syttende-mai-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: rgba(255,255,255,0.75);
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
line-height: 1;
|
||||
padding: 0 4px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
.syttende-mai-close:hover { color: #fff; }
|
||||
|
||||
/* ── Free-tier credit badge ──────────────────────────────────────────────── */
|
||||
.credit-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 20px;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
background: var(--soft-teal);
|
||||
color: var(--teal-dark);
|
||||
border: 1px solid rgba(15, 118, 110, 0.25);
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
.credit-badge.is-low {
|
||||
background: #fff7ed;
|
||||
color: #92400e;
|
||||
border-color: rgba(183, 121, 31, 0.3);
|
||||
}
|
||||
.credit-badge.is-empty {
|
||||
background: #fff0e8;
|
||||
color: #c2410c;
|
||||
border-color: rgba(194, 65, 12, 0.3);
|
||||
}
|
||||
|
||||
/* ── Credit-empty modal ───────────────────────────────────────────────────── */
|
||||
.credit-modal-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(22, 19, 15, 0.55);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 500;
|
||||
}
|
||||
.credit-modal {
|
||||
background: var(--panel);
|
||||
border-radius: 12px;
|
||||
padding: 32px 28px 24px;
|
||||
max-width: 380px;
|
||||
width: calc(100% - 40px);
|
||||
box-shadow: var(--shadow);
|
||||
text-align: center;
|
||||
}
|
||||
.credit-modal__icon { font-size: 2.5rem; margin-bottom: 12px; }
|
||||
.credit-modal h3 { margin: 0 0 8px; font-size: 1.15rem; color: var(--ink); }
|
||||
.credit-modal p { color: var(--muted); font-size: 0.9rem; margin: 0 0 20px; line-height: 1.55; }
|
||||
.credit-modal__actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
|
||||
.credit-modal__actions a {
|
||||
padding: 8px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
.credit-modal__cta { background: var(--teal); color: #fff; }
|
||||
.credit-modal__cta:hover { background: var(--teal-dark); }
|
||||
.credit-modal__dismiss { background: var(--line); color: var(--ink); }
|
||||
.credit-modal__dismiss:hover { background: #c8cdd8; }
|
||||
|
||||
/* ── Rate-limit toast ────────────────────────────────────────────────────── */
|
||||
.credit-toast {
|
||||
position: fixed;
|
||||
bottom: 24px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #1b2330;
|
||||
color: #fff;
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.875rem;
|
||||
z-index: 500;
|
||||
white-space: nowrap;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.25);
|
||||
animation: toastIn 0.2s ease;
|
||||
}
|
||||
@keyframes toastIn {
|
||||
from { opacity: 0; transform: translateX(-50%) translateY(8px); }
|
||||
to { opacity: 1; transform: translateX(-50%) translateY(0); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user