@import url("https://fonts.googleapis.com/css2?family=Urbanist:wght@400;500;600;700;800&display=swap");

/*
 * Portal/Admin design system — ported from klepon-marketing's confirmed
 * 2026 rebrand (see ../klepon-marketing/DESIGN.md and src/styles/global.css,
 * source: Klepon_2026_Huisstijl_v02A.pdf, confirmed 2026-08-28). This app
 * previously ran its own invented look (indigo/Inter, loosely modeled on a
 * third-party extension's UI); that's retired in favor of the real,
 * confirmed brand — navy ink + one signal green, Urbanist, pill buttons,
 * soft rounded cards. Token values below are copied from the marketing
 * repo's tokens, not re-derived — if that palette ever changes, re-copy
 * from there rather than hand-tuning here.
 *
 * The app-shell (sidebar/top bar) components at the bottom are this app's
 * own addition — the marketing site has no dashboard to draw that pattern
 * from — but they read from the same tokens as everything else in this
 * file.
 */
:root {
  --color-bg: #f2f2f2;
  --color-surface: #e9e9ea;
  --color-text: #002e3a;
  --color-text-muted: color-mix(in srgb, var(--color-text) 55%, transparent);
  --color-divider: color-mix(in srgb, #002e3a 14%, transparent);

  --color-accent: #11a46e;
  --color-accent-100: #e6f8ef;
  --color-accent-200: #c2eeda;
  --color-accent-300: #8fdfb9;
  --color-accent-400: #55cb92;
  --color-accent-500: #2bb87a;
  --color-accent-600: #11a46e;
  --color-accent-700: #0c7d55;
  --color-accent-800: #095e40;
  --color-accent-900: #06432d;

  /* Not part of the brand palette — klepon-marketing's DESIGN.md is explicit that its secondary
     orange/amber are general-purpose accents, not semantic warning/error colors, so severity
     badges here use their own independent red/amber rather than borrowing those tokens. */
  --color-warning: #b45309;
  --color-warning-bg: #fef6e7;
  --color-danger: #dc2626;
  --color-danger-bg: #fdecec;

  --font-sans: "Urbanist", system-ui, sans-serif;
  --font-heading: "Urbanist", system-ui, sans-serif;

  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 7px;
  --radius-2xl: 16px;
  --radius-3xl: 22px;
  --radius-full: 9999px;

  --shadow-elev-sm: 0 1px 2px color-mix(in srgb, #002e3a 10%, transparent);
  --shadow-elev-md: 0 3px 10px color-mix(in srgb, #002e3a 12%, transparent);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: 16px;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.01em;
  margin: 0 0 0.5rem;
}

h1 { font-size: 1.875rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.0625rem; }

a {
  color: var(--color-accent-700);
  text-decoration: none;
}

a:hover {
  color: var(--color-accent-900);
}

:focus {
  outline: none;
}

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

::selection {
  background: color-mix(in srgb, var(--color-accent) 30%, transparent);
}

/* Eyebrow — the one place uppercase survives in this system: a small kicker line preceding a
   heading, or naming a stat-card's category. */
.eyebrow {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  margin-bottom: 0.35rem;
}

/* Card — white surface, generously rounded, resting shadow (not a hover-only state). Still
   named .blueprint so every page that already uses it picks up the new look with no markup
   changes; the old square-corner/hairline-border/corner-mark system it originally named is
   gone, same as on the marketing site. */
.blueprint {
  position: relative;
  border: none;
  border-radius: var(--radius-3xl);
  background: white;
  box-shadow: var(--shadow-elev-sm);
}

/* Corner registration marks — no equivalent in this system. Markup still emits the four .corner
   spans on every card (harmless, kept rather than touching every page) — this hides them. */
.corner {
  display: none;
}

/* Buttons — pill-shaped, always. .btn alone is the neutral/secondary action; .btn-primary is
   the one solid brand-green action; .btn-danger is reserved for the genuinely destructive one
   (Portal/DeleteAccount) — not part of the brand system, kept as this app's own addition. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  cursor: pointer;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.2;
  border-radius: var(--radius-full);
  border: 1px solid transparent;
  padding: 0.85rem 1.7rem;
  background: var(--color-surface);
  color: var(--color-text);
}

.btn:hover {
  background: color-mix(in srgb, var(--color-text) 7%, transparent);
  text-decoration: none;
}

/* Primary text is white, matching klepon-marketing's corrected convention (2026-08-31: an
   earlier version of that repo's DESIGN.md documented navy as the accessible default, but by
   then nearly every real button on the site already overrode it back to white to match the
   brand PDF's own swatch — white was the live convention, navy was the outlier. Ported here to
   match. The ~3.2:1 contrast at button-text size is a known, accepted tradeoff, not an
   oversight — see klepon-marketing/DESIGN.md's Buttons section before changing this back.) */
.btn-primary {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: white;
}

.btn-primary:hover {
  background: var(--color-accent-500);
  border-color: var(--color-accent-500);
  color: white;
}

.btn-primary:active {
  background: var(--color-accent-600);
  border-color: var(--color-accent-600);
}

.btn-sm {
  font-size: 0.875rem;
  padding: 0.6375rem 1.275rem;
}

.btn-danger {
  background: var(--color-danger);
  border-color: var(--color-danger);
  color: #fff;
}

.btn-danger:hover {
  background: color-mix(in srgb, var(--color-danger) 85%, black);
  border-color: color-mix(in srgb, var(--color-danger) 85%, black);
  color: #fff;
}

/* Inputs */
label {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8125rem;
  color: var(--color-text);
  margin-bottom: 0.35rem;
}

input[type="text"], input[type="email"], input[type="password"], input[type="date"], select {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  color: var(--color-text);
  background: white;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  padding: 0.65rem 0.85rem;
}

input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus,
input[type="date"]:focus, select:focus {
  border-color: var(--color-accent);
}

input[type="checkbox"] {
  accent-color: var(--color-accent);
  margin-right: 0.35rem;
}

/* Notice bars — expiry warnings, pending-request status. Sit above the stat grid. */
.notice-bar {
  border-radius: var(--radius-3xl);
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
  font-size: 0.9375rem;
  background: var(--color-warning-bg);
}

.notice-bar-flat {
  border: none;
  background: var(--color-accent-100);
}

/* Stat cards (dashboard) */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.25rem;
  margin: 1.5rem 0 2rem;
}

.stat-card {
  padding: 1.5rem;
}

.stat-value {
  font-family: var(--font-heading);
  font-size: 2.25rem;
  font-weight: 800;
  color: var(--color-text);
  line-height: 1;
}

.stat-value-muted {
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--color-text-muted);
}

.stat-label {
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* Tables — rendered as a card in their own right: white surface, rounded, shadowed, no internal
   vertical rules, a tinted header row, and a hover highlight per row. border-collapse:separate
   (rather than the usual collapse) is what lets border-radius/overflow actually clip the header
   and last row's corners. */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: white;
  border-radius: var(--radius-3xl);
  overflow: hidden;
  box-shadow: var(--shadow-elev-sm);
}

th, td {
  text-align: left;
  padding: 0.9rem 1.1rem;
  border-bottom: 1px solid var(--color-divider);
  font-size: 0.9375rem;
}

th {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
  background: var(--color-surface);
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr:hover td {
  background: var(--color-bg);
}

/* Badges — small compact chips (16px rounding, per DESIGN.md's chip radius — distinct from the
   full-pill radius reserved for buttons), colored by severity/state. */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.7rem;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 0.75rem;
  border-radius: var(--radius-2xl);
  border: none;
}

.badge-active, .badge-ok { background: var(--color-accent-100); color: var(--color-accent-700); }
.badge-suspended { background: var(--color-warning-bg); color: var(--color-warning); }
.badge-revoked, .badge-locked { background: var(--color-danger-bg); color: var(--color-danger); }

/* Utilization bar — seats in use vs total, for offering/stat cards. Fill color signals how close
   to capacity: brand green, amber warning, red once no seat is left at all. */
.util-bar {
  margin-top: 0.6rem;
  height: 8px;
  width: 100%;
  background: var(--color-surface);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.util-bar-fill {
  height: 100%;
  border-radius: var(--radius-full);
}

.util-bar-fill-ok { background: var(--color-accent); }
.util-bar-fill-warn { background: var(--color-warning); }
.util-bar-fill-full { background: var(--color-danger); }

/* Needs-attention panel (Admin dashboard) — a stack of compact, linkable rows grouped under a
   heading, each capped short with a "N more" link rather than repeating the full table. */
.attention-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.25rem;
  margin: 1.5rem 0 2rem;
}

.attention-panel {
  padding: 1.375rem;
}

.attention-panel h3 {
  font-size: 0.9375rem;
  margin: 0 0 0.7rem;
}

.attention-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.attention-list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.875rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--color-divider);
}

.attention-list li:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

.attention-more {
  display: block;
  margin-top: 0.7rem;
  font-size: 0.8125rem;
}

.error {
  color: var(--color-danger);
  font-size: 0.875rem;
}

/* ============================================================
   App shell — sidebar + top bar chrome. This app's own addition
   (the marketing site has no dashboard to draw the pattern from);
   reads from the same tokens as everything else above.
   ============================================================ */
.app-shell {
  display: flex;
  min-height: 100vh;
  background: var(--color-bg);
}

.app-sidebar {
  width: 260px;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  padding: 1.5rem 1rem;
  background: white;
  border-right: 1px solid var(--color-divider);
}

.app-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0 0.5rem;
  margin-bottom: 1.75rem;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 1.0625rem;
  color: var(--color-text);
}

.app-brand:hover {
  color: var(--color-text);
  text-decoration: none;
}

.app-brand img {
  width: 24px;
  height: 24px;
}

/* Distinguishes the internal Admin area from the customer-facing Portal at a glance — also used
   standalone on the Admin login/access-denied cards (outside the sidebar). */
.wordmark-tag {
  font-family: var(--font-heading);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-accent-700);
  background: var(--color-accent-100);
  padding: 0.15rem 0.55rem;
  border-radius: var(--radius-2xl);
}

.app-nav {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.app-nav-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 0.7rem;
  border-radius: var(--radius-2xl);
  font-family: var(--font-sans);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--color-text-muted);
}

.app-nav-item:hover {
  background: var(--color-bg);
  color: var(--color-text);
  text-decoration: none;
}

.app-nav-item.active {
  background: var(--color-accent-100);
  color: var(--color-accent-700);
}

.app-nav-item svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.app-nav-badge {
  margin-left: auto;
  font-family: var(--font-sans);
  font-size: 0.625rem;
  font-weight: 700;
  color: #fff;
  background: var(--color-accent);
  padding: 0.1rem 0.45rem;
  border-radius: var(--radius-full);
}

.app-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.app-topbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1rem;
  padding: 1rem 2rem;
  background: white;
  box-shadow: var(--shadow-elev-sm);
  position: relative;
  z-index: 1;
}

.app-identity {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.app-identity-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--radius-full);
  background: var(--color-accent);
  color: var(--color-text);
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 0.8125rem;
  flex-shrink: 0;
}

.app-identity-value {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text);
}

/* Portal's identity menu — a native <details>/<summary> disclosure (identity-menu.js only
   handles closing it on outside click/Escape, since <details> doesn't do that natively). Needs
   its own positioning: .app-identity-dropdown is absolutely placed off the wrapping <details>,
   not inline in the topbar's flex flow, or it just falls into the page below the topbar as
   plain text — which is what it did before this rule existed. */
.app-identity-menu {
  position: relative;
}

.app-identity-menu summary {
  list-style: none;
  cursor: pointer;
}

.app-identity-menu summary::-webkit-details-marker {
  display: none;
}

.app-identity-dropdown {
  position: absolute;
  top: calc(100% + 0.75rem);
  right: 0;
  z-index: 20;
  min-width: 240px;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1rem;
  background: white;
  border-radius: var(--radius-2xl);
  box-shadow: var(--shadow-elev-md);
}

.app-identity-dropdown-header {
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--color-divider);
}

.app-identity-dropdown-email {
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--color-text);
  word-break: break-all;
}

.app-identity-dropdown-role {
  margin-top: 0.15rem;
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.app-identity-dropdown a {
  font-size: 0.875rem;
  font-weight: 600;
}

.app-identity-dropdown .app-logout {
  width: 100%;
}

/* Notification bell — same <details>/<summary> + .app-identity-dropdown pattern as the identity
   menu right next to it, just its own trigger icon and dropdown content. */
.app-notification-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-full);
  color: var(--color-text);
}

.app-notification-bell:hover,
.app-identity-menu[open] > summary.app-notification-bell {
  background: color-mix(in srgb, var(--color-text) 6%, transparent);
}

.app-notification-dot {
  position: absolute;
  top: 6px;
  right: 7px;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--color-danger);
  border: 1.5px solid white;
}

.app-notification-dropdown {
  width: 320px;
  max-height: 380px;
  overflow-y: auto;
  padding: 0;
  gap: 0;
}

.app-notification-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--color-divider);
}

.app-notification-header-title {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.app-notification-mark-read button {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--color-accent-700);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  font-family: var(--font-sans);
}

.app-notification-empty {
  padding: 1.25rem 0.9rem;
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

.app-notification-item {
  display: block;
  padding: 0.65rem 0.9rem;
  text-decoration: none;
  border-bottom: 1px solid var(--color-divider);
}

.app-notification-item:last-child {
  border-bottom: none;
}

.app-notification-item:hover {
  background: color-mix(in srgb, var(--color-text) 4%, transparent);
}

.app-notification-item.unread {
  background: var(--color-accent-100);
}

.app-notification-message {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 0.15rem;
}

.app-notification-time {
  display: block;
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.app-logout {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.8125rem;
  border-radius: var(--radius-full);
  border: 1px solid color-mix(in srgb, var(--color-text) 15%, transparent);
  background: transparent;
  color: var(--color-text);
  padding: 0.45rem 0.9rem;
  cursor: pointer;
}

.app-logout:hover {
  background: color-mix(in srgb, var(--color-text) 5%, transparent);
}

.app-main {
  flex: 1;
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  padding: 2.5rem 2rem;
}

/* Login / signup / access-denied cards */
.auth-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg);
}

.auth-card {
  width: 340px;
  padding: 2.25rem 2rem;
}

.auth-card form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-top: 1.25rem;
}

.auth-card button[type="submit"] {
  margin-top: 0.5rem;
}
