/* --- LOGIN SCREEN STYLES --- */
.gm-login-wrapper { padding: 0 15px; }
.gm-login-card { max-width: 450px; margin: 80px auto; padding: 40px; background: #ffffff; border-radius: 24px; box-shadow: 0 20px 50px rgba(0,0,0,0.06); border: 1px solid rgba(0,0,0,0.03); text-align:center; font-family: 'Inter', system-ui, sans-serif; box-sizing: border-box; }
.gm-login-card p { text-align: left; margin-bottom: 15px; }
.gm-login-card label { font-weight: 700; color: #4a5568; font-size: 0.95rem; margin-bottom: 8px; display: block; text-align: left; }
.gm-login-card .input { width: 100%; padding: 14px 20px; border-radius: 12px; border: 2px solid var(--gma-field-border); background-color: #f7fafc; font-size: 1.05rem; color: #2d3748; transition: all 0.2s ease; box-sizing: border-box; }
.gm-login-card .input:focus { background-color: #ffffff; border-color: #00b783; box-shadow: 0 0 0 4px rgba(0, 183, 131, 0.15); outline: none;}
.gm-login-card .login-remember { font-size: 0.9rem; color: #718096; display:flex; align-items:center; gap: 8px; justify-content: flex-start;}
.gm-login-card .login-submit { margin-top: 10px; }
.gm-login-card .button-primary { width: 100%; background-color: #00b783; background-image: linear-gradient(135deg, #00b783 0%, #00b783 100%); border: none; border-radius: 12px; padding: 16px; font-size: 1.15rem; font-weight: 700; color: white; transition: all 0.3s ease; box-shadow: 0 10px 20px rgba(0, 183, 131, 0.2); cursor: pointer; }
.gm-login-card .button-primary:hover { transform: translateY(-3px); box-shadow: 0 15px 25px rgba(0, 183, 131, 0.3); }

/* --- ADMIN DASHBOARD STYLES --- */
.gm-admin-wrapper { font-family: 'Inter', system-ui, sans-serif; max-width: 1100px; margin: 2rem auto 8rem auto; padding: 0 15px; box-sizing: border-box; }
.gm-admin-card { background: #ffffff; border-radius: 24px; padding: 2.5rem; box-shadow: 0 12px 40px rgba(0,0,0,0.04); border: 1px solid rgba(0,0,0,0.02); margin-bottom: 2rem; box-sizing: border-box;}
.gm-admin-header { font-weight: 800; font-size: 2rem; color: #1a202c; letter-spacing: -0.5px; margin-top: 0;}
.gm-admin-label { font-weight: 700; color: #4a5568; font-size: 0.9rem; margin-bottom: 6px; display: block; }

.btn-gm-primary { background: linear-gradient(135deg, #00b783 0%, #00b783 100%); border: none; border-radius: 12px; padding: 10px 24px; font-size: 1rem; font-weight: 700; color: white; transition: all 0.3s ease; box-shadow: 0 8px 15px rgba(0, 183, 131, 0.2); cursor: pointer; display: flex; align-items: center; justify-content: center;}
.btn-gm-primary:hover { transform: translateY(-2px); box-shadow: 0 12px 20px rgba(0, 183, 131, 0.3); color: white; }
.btn-gm-secondary { background: #f1f5f9; border: none; border-radius: 12px; padding: 10px 24px; font-size: 1rem; font-weight: 700; color: #64748b; transition: all 0.2s ease; cursor: pointer; display: flex; align-items: center; justify-content: center;}
.btn-gm-secondary:hover { background: #e2e8f0; color: #475569; transform: translateY(-2px); }
.btn-gm-danger { background: #fff5f5; border: 1px solid #fed7d7; color: #e53e3e; border-radius: 10px; padding: 6px 12px; font-weight: 600; transition: all 0.2s; cursor: pointer; display: flex; align-items: center; justify-content: center;}
.btn-gm-danger:hover { background: #e53e3e; color: white; transform: translateY(-2px); box-shadow: 0 5px 10px rgba(229, 62, 62, 0.2); }

.gm-action-grid-desktop { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; width: 220px; margin-left: auto; }
.btn-gm-action { background: #ffffff; border: 1px solid #edf2f7; color: #4a5568; border-radius: 8px; padding: 6px 10px; font-weight: 600; transition: all 0.2s; cursor: pointer; display: flex; align-items: center; justify-content: center; text-align: center; width: 100%; font-size: 0.85rem; box-shadow: 0 1px 2px rgba(0,0,0,0.02);}
.btn-gm-action:hover { background: #00b783; color: white; border-color: #00b783; transform: translateY(-1px); box-shadow: 0 5px 10px rgba(0, 183, 131, 0.15); }

.btn-header-action { border-radius: 8px; font-weight: 700; font-size: 0.9rem; padding: 8px 16px; display: inline-flex; align-items: center; justify-content: center; transition: all 0.2s; border: 1px solid transparent; cursor: pointer; background: #fff; height: 100%;}
.btn-header-csv { background: #f0fdf4; border-color: #ccf1e6; color: #00b783; }
.btn-header-csv:hover { background: #e0f6f0; color: #00b783; }
.btn-header-msg { background: #eff6ff; border-color: #bfdbfe; color: #2563eb; }
.btn-header-msg:hover { background: #dbeafe; color: #1d4ed8; }
.gm-stats-badge { background: #f8fafc; border: 1px solid #e2e8f0; color: #475569; font-weight: 800; font-size: 0.9rem; border-radius: 8px; padding: 8px 16px; display: inline-flex; align-items: center; justify-content: center; white-space: nowrap; height: 100%;}

.gm-status-badge { display: inline-flex; align-items: center; padding: 6px 12px; border-radius: 8px; font-size: 0.8rem; font-weight: 700; white-space: nowrap; }
.gm-status-open { background: #e0f6f0; color: #00b783; border: 1px solid #ccf1e6; }
.gm-status-upcoming { background: #f1f5f9; color: #64748b; border: 1px solid #e2e8f0; }
.gm-status-auto { background: #eff6ff; color: #2563eb; border: 1px solid #bfdbfe; }

.btn-action-sm { border-radius: 8px; padding: 6px 10px; font-size: 0.85rem; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; transition: all 0.2s; border: 1px solid transparent; cursor: pointer; background: #fff; }
.btn-action-sm-primary { color: #2563eb; border-color: #bfdbfe; background: #eff6ff; }
.btn-action-sm-primary:hover { background: #dbeafe; }
.btn-action-sm-warning { color: #d97706; border-color: #fde68a; background: #fffbeb; }
.btn-action-sm-warning:hover { background: #fef3c7; }
.btn-action-sm-danger { color: #dc2626; border-color: #fecaca; background: #fef2f2; }
.btn-action-sm-danger:hover { background: #fee2e2; }

.gm-dash-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 2rem; }
.gm-metric-card { background: #fff; border-radius: 20px; padding: 25px; box-shadow: 0 10px 30px rgba(0,0,0,0.03); border: 1px solid #edf2f7; display: flex; align-items: center; gap: 20px; }
.gm-metric-icon { width: 60px; height: 60px; border-radius: 16px; background: #f1f5f9; color: #00b783; display: flex; align-items: center; justify-content: center; font-size: 1.8rem; }
.gm-metric-val { font-size: 2rem; font-weight: 800; color: #1a202c; line-height: 1; }
.gm-metric-lbl { font-size: 0.85rem; font-weight: 700; color: #a0aec0; text-transform: uppercase; letter-spacing: 0.5px; margin-top: 5px; }

.gm-table-wrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 10px; box-sizing: border-box;}
.gm-table { border-collapse: separate; border-spacing: 0 10px; width: 100%; min-width: 850px; box-sizing: border-box;}
.gm-table.gm-table-compact { min-width: 100% !important; }
.gm-table th { border: none; color: #a0aec0; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 1px; padding: 0 20px 5px 20px; font-weight: 700; }
.gm-table th.sortable { cursor: pointer; transition: color 0.2s; user-select: none; }
.gm-table th.sortable:hover { color: #00b783; }
.gm-table td { background: #ffffff; padding: 18px 20px; border-top: 1px solid #edf2f7; border-bottom: 1px solid #edf2f7; vertical-align: middle; color: #2d3748; }
.gm-table tr td:first-child { border-left: 1px solid #edf2f7; border-radius: 16px 0 0 16px; font-weight: 600; }
.gm-table tr td:last-child { border-right: 1px solid #edf2f7; border-radius: 0 16px 16px 0; }
.gm-table tr { transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.01); }
.gm-table tr:hover { transform: translateY(-2px); box-shadow: 0 10px 20px rgba(0,0,0,0.04); position: relative; z-index: 10; }

.gm-tabs { display: inline-flex; background: #f1f5f9; padding: 6px; border-radius: 16px; gap: 5px; margin-bottom: 0; }
.gm-tab { border: none; background: transparent; padding: 10px 24px; border-radius: 12px; font-weight: 700; color: #64748b; transition: all 0.2s ease; cursor: pointer; font-size: 0.95rem; }
.gm-tab.active { background: #ffffff; color: #00b783; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }

.ql-editor { min-height: 100%; }

.gm-toast-container { position: fixed; bottom: 30px; right: 30px; z-index: 99999; pointer-events: none; }
.gm-toast { background: #ffffff; border-radius: 16px; padding: 16px 24px; box-shadow: 0 20px 40px rgba(0,0,0,0.12); display: flex; align-items: center; gap: 15px; transform: translateY(100px) scale(0.9); opacity: 0; transition: all 0.5s cubic-bezier(0.2, 1.2, 0.3, 1); pointer-events: auto; cursor: pointer; border-left: 6px solid #00b783; }
.gm-toast.show { transform: translateY(0) scale(1); opacity: 1; }
.gm-toast.error { border-left-color: #e53e3e; }
.gm-toast-icon { font-size: 1.5rem; display: flex; align-items: center;}
.gm-toast:not(.error) .gm-toast-icon { color: #00b783; }
.gm-toast.error .gm-toast-icon { color: #e53e3e; }
.gm-toast-body { font-family: 'Inter', sans-serif; font-weight: 700; color: #1a202c; font-size: 1.05rem; margin: 0; }

.gm-cf-row { background: #fcfdfd; border: 1px solid #edf2f7; border-radius: 12px; padding: 12px; margin-bottom: 10px; display: flex; gap: 10px; align-items: center; }
/* .checkin-btn is defined with the other buttons, near the end of this file. */

#qr-reader { border: none !important; border-radius: 12px; overflow: hidden; background: #ffffff; }

/* =========================================================
   MOBILE OPTIMIZATIONS - FULL WIDTH BREAKOUT
   ========================================================= */
@media (max-width: 768px) {
    .gm-login-wrapper { margin-left: calc(50% - 50vw) !important; margin-right: calc(50% - 50vw) !important; width: 100vw !important; max-width: 100vw !important; padding: 0 !important; box-sizing: border-box; margin-top: 1rem; }
    .gm-login-card { margin: 0; padding: 40px 20px; width: 100%; max-width: 100%; border-radius: 0; border-left: none; border-right: none; box-shadow: none; border-top: 1px solid #edf2f7; border-bottom: 1px solid #edf2f7; }
    .gm-admin-wrapper { margin-left: calc(50% - 50vw) !important; margin-right: calc(50% - 50vw) !important; width: 100vw !important; max-width: 100vw !important; padding: 0 !important; margin-top: 1rem; margin-bottom: 5rem; box-sizing: border-box; overflow-x: hidden; }
    .gm-header-flex, .gm-tabs, .gm-dash-metrics, #newEventForm, #manualAddBox { padding-left: 15px !important; padding-right: 15px !important; box-sizing: border-box; }
    .gm-admin-card { padding: 1.5rem 15px; border-radius: 0; border-left: none; border-right: none; margin-bottom: 1.5rem; width: 100%; box-sizing: border-box;}
    .gm-admin-header { font-size: 1.8rem; margin-bottom: 0.5rem; }
    .gm-header-flex { flex-direction: column !important; align-items: flex-start !important; gap: 1rem; }
    .gm-header-flex > button, .gm-header-flex > div.w-100-mob { width: 100%; justify-content: center; }
    .gm-manage-actions { width: 100%; flex-direction: column; gap: 10px; height: auto !important; min-height: unset !important; }
    .gm-manage-actions button, .gm-manage-actions .gm-stats-badge { width: 100%; justify-content: center; }
    .gm-tabs { width: 100%; display: flex; box-sizing: border-box;}
    .gm-tab { flex: 1; text-align: center; padding: 10px 5px; font-size: 0.85rem;}
    .gm-toast-container { bottom: 20px; right: 20px; left: 20px; }
    .gm-toast { padding: 12px 16px; }
    .gm-cf-row { flex-direction: column; align-items: stretch; }
    .gm-table-wrap { overflow-x: visible; min-width: 100%; width: 100%; padding: 0; margin: 0; box-sizing: border-box;}
    .gm-table { min-width: 100%; width: 100%; display: block; box-sizing: border-box;}
    .gm-table thead { display: none; }
    .gm-table tbody { display: block; width: 100%; box-sizing: border-box; padding: 0 15px;}
    .gm-table tr { display: block; width: 100%; margin-left: 0; margin-right: 0; margin-bottom: 1rem; background: #ffffff; border-radius: 16px; box-shadow: 0 8px 24px rgba(0,0,0,0.06); padding: 0; border: 1px solid #edf2f7; box-sizing: border-box; overflow:hidden;}
    .gm-table td { display: flex; justify-content: space-between; align-items: center; text-align: right; padding: 14px 16px !important; border: none !important; border-bottom: 1px solid #f8fafc !important; border-radius: 0 !important; width: 100%; box-sizing: border-box; gap: 10px; }
    .gm-table td:last-child { border-bottom: none !important; display: flex !important; justify-content: space-between !important; align-items: center !important; text-align: right !important; padding-top: 15px; padding-bottom: 15px; background: #fcfdfd; }
    .gm-table td::before { content: attr(data-label); font-weight: 700; color: #a0aec0; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap; flex-shrink: 0; }
    .gm-table td span, .gm-table td a, .gm-table td div { word-break: break-word; text-align: right; }
    .btn-gm-action { padding: 8px 5px; font-size: 0.8rem; }
    .gm-action-grid-desktop { display: grid !important; grid-template-columns: repeat(2, 1fr); gap: 8px !important; width: 100% !important;}
    .table-scroll-mobile-y { max-height: 400px; overflow-y: auto; }
}

/* Scroll to top */
.gm-scroll-top { position: fixed; bottom: 30px; right: 30px; width: 55px; height: 55px; border-radius: 50%; background: #00b783; color: white; border: none; box-shadow: 0 10px 25px rgba(0, 183, 131, 0.4); font-size: 1.5rem; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 9999; opacity: 0; pointer-events: none; transform: translateY(20px); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); }
.gm-scroll-top.show { opacity: 1; pointer-events: auto; transform: translateY(0); }
.gm-scroll-top:hover { background: #00b783; transform: translateY(-5px) scale(1.05); box-shadow: 0 15px 30px rgba(0, 183, 131, 0.5); color: white; }
@media (max-width: 768px) { .gm-scroll-top { bottom: 20px; right: 20px; width: 48px; height: 48px; font-size: 1.3rem; } }
/* Animation for the refresh button */
@keyframes gm-spin-sync { 100% { transform: rotate(360deg); } }
.gm-icon-spin { animation: gm-spin-sync 0.8s linear infinite; display: inline-block; }

/* Force proper stacking for analytics headers on mobile */
@media (max-width: 768px) {
    .gm-analytics-header { flex-direction: column !important; align-items: stretch !important; gap: 15px !important; }
    .gm-analytics-header h5 { margin-bottom: 5px !important; }
    .gm-analytics-header select, .gm-analytics-header button { width: 100% !important; justify-content: center; }
}
/* =========================================================
   FULL-SCREEN SCANNER KIOSK (LIGHT MODE)
   ========================================================= */
.gm-scanner-kiosk { position: fixed; top: 0; right: 0; bottom: 0; left: 0; height: 100%; background: #f8fafc; z-index: 999999 !important; display: flex; flex-direction: column; overflow: hidden; font-family: 'Inter', sans-serif; }
.gm-kiosk-header { background: #ffffff; padding: 15px 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #e2e8f0; box-shadow: 0 2px 4px rgba(0,0,0,0.02); }
.gm-kiosk-close { background: #f1f5f9; color: #475569; border: none; width: 40px; height: 40px; border-radius: 50%; font-size: 1.5rem; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: 0.2s; }
.gm-kiosk-close:hover { background: #e2e8f0; color: #1e293b; }
.gm-kiosk-stats { color: #475569; font-weight: 800; font-size: 1.1rem; display: flex; align-items: center; gap: 10px; }
.gm-kiosk-stats span { background: #00b783; color: #fff; padding: 4px 12px; border-radius: 20px; font-size: 1rem; }

.gm-kiosk-body { flex-grow: 1; display: flex; flex-direction: column; align-items: center; padding: 20px; position: relative; overflow-y: auto; }
.gm-kiosk-camera-wrap { width: 100%; max-width: 500px; background: #000; border-radius: 20px; overflow: hidden; position: relative; border: 4px solid #ffffff; box-shadow: 0 10px 25px rgba(0,0,0,0.08); flex-shrink: 0; /* <-- This stops the squishing! */ }#qr-reader { width: 100%; border: none !important; }
#qr-reader__scan_region { background: #000; }
#qr-reader__dashboard_section_csr span { color: #fff !important; }

.gm-kiosk-controls { display: flex; gap: 15px; margin-top: 20px; }
.gm-kiosk-btn { background: #ffffff; border: 1px solid #cbd5e1; color: #334155; border-radius: 50px; padding: 12px 25px; font-weight: 700; cursor: pointer; display: flex; align-items: center; gap: 8px; transition: all 0.2s; font-size: 1rem; box-shadow: 0 2px 4px rgba(0,0,0,0.02); }
.gm-kiosk-btn:hover { background: #f1f5f9; border-color: #94a3b8; color: #0f172a; }

.gm-kiosk-search { width: 100%; max-width: 500px; margin-top: 30px; background: #ffffff; padding: 20px; border-radius: 16px; border: 1px solid #e2e8f0; box-shadow: 0 4px 6px rgba(0,0,0,0.02); }
.gm-kiosk-search input { background: #f8fafc; border: 1px solid var(--gma-field-border); color: #1e293b; padding: 15px; border-radius: 12px; width: 100%; font-size: 1.1rem; transition: 0.2s; }
.gm-kiosk-search input:focus { border-color: #00b783; outline: none; background: #ffffff; box-shadow: 0 0 0 3px rgba(0, 183, 131, 0.2); }

/* THE MASSIVE FLASH OVERLAY */
.gm-flash-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 10; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; opacity: 0; pointer-events: none; transition: opacity 0.1s; padding: 20px; }
.gm-flash-overlay.show { opacity: 1; pointer-events: auto; }
.gm-flash-overlay.success { background: #00b783; color: white; }
.gm-flash-overlay.warning { background: #f59e0b; color: white; }
.gm-flash-overlay.error { background: #ef4444; color: white; }
.gm-flash-icon { font-size: 6rem; line-height: 1; margin-bottom: 10px; filter: drop-shadow(0 10px 10px rgba(0,0,0,0.2)); }
.gm-flash-title { font-size: 2.5rem; font-weight: 900; margin: 0; line-height: 1.2; text-transform: uppercase; }
.gm-flash-msg { font-size: 1.5rem; font-weight: 700; margin-top: 10px; opacity: 0.9; }


/* =========================================================================
   APPLE-GRADE DESIGN LAYER (ADMIN)
   =========================================================================
   Same approach as public.css: presentational only, no new class names, no
   markup changes, appended last so the cascade resolves in its favour.
   Deleting this block restores the previous look exactly.

   The dashboard is a working tool, so this leans further into clarity than
   decoration: quieter chrome, a real type scale, tabular figures in tables,
   and hover feedback that does not move rows around under the cursor.
   ========================================================================= */

:root {
    --gma-font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display",
                "Helvetica Neue", "Segoe UI", Roboto, system-ui, sans-serif;
    --gma-ink:        #1d1d1f;
    --gma-ink-2:      #6e6e73;
    /* Apple ships #86868b for tertiary text, but it is only 3.62:1 on white
       and 3.33:1 on the #f5f5f7 panels -- and every use of this token here is
       real text (.gm-table th, .gm-metric-lbl, the mobile td::before labels).
       Darkened to the lightest grey that still clears 4.5:1 on #f5f5f7. */
    --gma-ink-3:  #6e6e73;
    --gma-surface:    #ffffff;
    --gma-surface-2:  #f5f5f7;
    --gma-hairline:   rgba(0,0,0,.08);
    --gma-hairline-2: rgba(0,0,0,.12);
    --gma-accent:      #00b783;
    --gma-accent-ink:  #00835d;
    --gma-accent-wash: rgba(0, 183, 131,.10);
    --gma-accent-ring: rgba(0, 183, 131,.28);
    /* #0071e3 is Apple's link blue, but on the rgba(0,113,227,.10) tints used
       by .btn-header-msg / .btn-action-sm-primary / .gm-status-auto it only
       reaches 4.10:1 -- worse than the #2563eb it replaced. This is the same
       value public.css uses on the identical tint. */
    --gma-blue:   #0063c9;
    --gma-danger: #d70015;
    --gma-danger-ring: rgba(215, 0, 21,.32);
    --gma-warn:   #b25000;
    --gma-green:  #00835d;
    --gma-r-sm: 8px;
    --gma-r-md: 12px;
    --gma-r-lg: 16px;
    --gma-r-xl: 20px;
    --gma-shadow-sm: 0 1px 2px rgba(0,0,0,.04), 0 1px 1px rgba(0,0,0,.03);
    --gma-shadow-md: 0 4px 12px rgba(0,0,0,.06), 0 1px 3px rgba(0,0,0,.04);
    --gma-shadow-lg: 0 12px 32px rgba(0,0,0,.08), 0 2px 8px rgba(0,0,0,.04);
    --gma-ease: cubic-bezier(.32,.72,0,1);
}

.gm-admin-wrapper,
.gm-login-card,
.gm-scanner-kiosk,
.gm-toast-body,
.ql-container {
    font-family: var(--gma-font);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.gm-admin-wrapper { color: var(--gma-ink); }

/* ---------- Shells ---------- */

.gm-admin-card,
.gm-login-card {
    background: var(--gma-surface);
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-xl);
    box-shadow: var(--gma-shadow-lg);
}

.gm-admin-card { padding: 2rem; }

.gm-admin-header {
    font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.125rem);
    font-weight: 700;
    letter-spacing: -0.022em;
    line-height: 1.1;
    color: var(--gma-ink);
}

/* ---------- Fields ---------- */

.gm-admin-label {
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: -0.006em;
    color: var(--gma-ink);
    margin-bottom: 8px;
}

.gm-admin-wrapper .form-control,
.gm-admin-wrapper .form-select,
.gm-login-card .input {
    min-height: 44px;
    padding: 12px 15px;
    font-size: 1rem;
    border: 1px solid var(--gma-field-border);
    border-radius: var(--gma-r-md);
    background-color: var(--gma-surface);
    color: var(--gma-ink);
    transition: border-color .2s var(--gma-ease), box-shadow .2s var(--gma-ease);
}

.gm-admin-wrapper .form-control:focus,
.gm-admin-wrapper .form-select:focus,
.gm-login-card .input:focus {
    background-color: var(--gma-surface);
    border-color: var(--gma-accent);
    box-shadow: 0 0 0 4px var(--gma-accent-ring);
    outline: none;
}

/* ---------- Buttons: press in, do not jump up ---------- */

.btn-gm-primary,
.gm-login-card .button-primary {
    background: var(--gma-accent);
    background-image: none;
    border: none;
    border-radius: var(--gma-r-md);
    font-weight: 600;
    font-size: 1rem;
    letter-spacing: -0.01em;
    color: #fff;
    box-shadow: var(--gma-shadow-sm);
    transition: background-color .2s var(--gma-ease), box-shadow .2s var(--gma-ease), transform .2s var(--gma-ease);
}

.btn-gm-primary:hover,
.gm-login-card .button-primary:hover {
    background: #00b783;
    transform: none;
    box-shadow: var(--gma-shadow-md);
    color: #fff;
}

.btn-gm-primary:active,
.gm-login-card .button-primary:active { transform: scale(.975); }

.btn-gm-secondary {
    background: var(--gma-surface-2);
    border-radius: var(--gma-r-md);
    font-weight: 600;
    color: var(--gma-ink-2);
    transition: background-color .2s var(--gma-ease), color .2s var(--gma-ease), transform .2s var(--gma-ease);
}
.btn-gm-secondary:hover { background: #ebebed; color: var(--gma-ink); transform: none; }
.btn-gm-secondary:active { transform: scale(.975); }

.btn-gm-danger {
    background: rgba(255,59,48,.08);
    border: 1px solid transparent;
    color: var(--gma-danger);
    border-radius: var(--gma-r-sm);
    font-weight: 600;
    transition: background-color .2s var(--gma-ease), color .2s var(--gma-ease), transform .2s var(--gma-ease);
}
.btn-gm-danger:hover { background: var(--gma-danger); color: #fff; transform: none; box-shadow: none; }
.btn-gm-danger:active { transform: scale(.96); }

.btn-gm-action {
    background: var(--gma-surface);
    border: 1px solid var(--gma-hairline-2);
    color: var(--gma-ink-2);
    border-radius: var(--gma-r-sm);
    font-weight: 600;
    box-shadow: none;
    transition: background-color .2s var(--gma-ease), color .2s var(--gma-ease), border-color .2s var(--gma-ease), transform .2s var(--gma-ease);
}
.btn-gm-action:hover {
    background: var(--gma-accent-wash);
    border-color: transparent;
    color: var(--gma-accent-ink);
    transform: none;
    box-shadow: none;
}
.btn-gm-action:active { transform: scale(.96); }

.btn-header-action,
.btn-action-sm { border-radius: var(--gma-r-sm); font-weight: 600; border: 1px solid transparent; }
.btn-header-csv       { background: rgba(0, 183, 131,.10);  border-color: transparent; color: var(--gma-green); }
.btn-header-csv:hover { background: rgba(0, 183, 131,.18);  color: var(--gma-green); }
.btn-header-msg       { background: rgba(0,113,227,.10);  border-color: transparent; color: var(--gma-blue); }
.btn-header-msg:hover { background: rgba(0,113,227,.18);  color: var(--gma-blue); }
.btn-action-sm-primary { background: rgba(0,113,227,.10); border-color: transparent; color: var(--gma-blue); }
.btn-action-sm-warning { background: rgba(255,149,0,.12); border-color: transparent; color: var(--gma-warn); }
.btn-action-sm-danger  { background: rgba(255,59,48,.10); border-color: transparent; color: var(--gma-danger); }

.gm-stats-badge,
.gm-status-badge {
    border-radius: var(--gma-r-sm);
    font-weight: 600;
    font-size: 0.8125rem;
    letter-spacing: -0.004em;
    border: 1px solid transparent;
}
.gm-stats-badge     { background: var(--gma-surface-2); color: var(--gma-ink-2); }
.gm-status-open     { background: rgba(0, 183, 131,.12);  color: var(--gma-green); }
.gm-status-upcoming { background: var(--gma-surface-2);  color: var(--gma-ink-2); }
.gm-status-auto     { background: rgba(0,113,227,.10);  color: var(--gma-blue); }

/* ---------- Tabs: a segmented control ---------- */

.gm-tabs {
    background: rgba(118,118,128,.12);
    padding: 3px;
    border-radius: var(--gma-r-md);
    gap: 2px;
}
.gm-tab {
    border-radius: 9px;
    font-weight: 600;
    font-size: 0.9375rem;
    letter-spacing: -0.008em;
    color: var(--gma-ink-2);
    transition: background-color .2s var(--gma-ease), color .2s var(--gma-ease);
}
.gm-tab.active {
    background: var(--gma-surface);
    color: var(--gma-ink);
    box-shadow: 0 3px 8px rgba(0,0,0,.08), 0 1px 1px rgba(0,0,0,.04);
}

/* ---------- Metrics ---------- */

.gm-metric-card {
    background: var(--gma-surface);
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-lg);
    box-shadow: var(--gma-shadow-sm);
}
.gm-metric-icon {
    width: 52px; height: 52px;
    border-radius: 14px;
    background: var(--gma-accent-wash);
    color: var(--gma-accent-ink);
    font-size: 1.5rem;
}
.gm-metric-val {
    font-size: 2rem;
    font-weight: 600;
    letter-spacing: -0.028em;
    font-variant-numeric: tabular-nums;
    color: var(--gma-ink);
}
.gm-metric-lbl {
    font-size: 0.8125rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    color: var(--gma-ink-3);
}

/* ---------- Tables ----------
   Rows no longer lift on hover: shifting a row under the pointer makes a
   dense table feel unsteady and can slide the click target away. A quiet
   background tint reads better and costs no layout. */

.gm-table th {
    color: var(--gma-ink-3);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}
.gm-table td {
    border-top: 1px solid var(--gma-hairline);
    border-bottom: 1px solid var(--gma-hairline);
    color: var(--gma-ink);
    font-variant-numeric: tabular-nums;
}
.gm-table tr td:first-child { border-left: 1px solid var(--gma-hairline); border-radius: var(--gma-r-md) 0 0 var(--gma-r-md); font-weight: 500; }
.gm-table tr td:last-child  { border-right: 1px solid var(--gma-hairline); border-radius: 0 var(--gma-r-md) var(--gma-r-md) 0; }
.gm-table tr { box-shadow: none; }
.gm-table tr:hover { transform: none; box-shadow: none; }
/* The transition has to sit on the cell, not the row: the row never changes
   background (the original rule paints td), and a transition on a property the
   element never animates does nothing. */
.gm-table td { transition: background-color .18s var(--gma-ease); }
.gm-table tr:hover td { background: #fafafc; }
.gm-table th.sortable:hover { color: var(--gma-accent-ink); }

/* ---------- Toast ---------- */

/* The border shorthand below is what removes the original 6px accent bar --
   it resets all four sides to one hairline. */
.gm-toast {
    border-radius: var(--gma-r-lg);
    background: rgba(255,255,255,.86);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
    border: 1px solid var(--gma-hairline);
    box-shadow: var(--gma-shadow-lg);
    transition: transform .45s var(--gma-ease), opacity .3s var(--gma-ease);
}
/* The 6px coloured bar is gone, so the error state has to be carried another
   way -- a tint plus the red icon. An admin saving event data needs failure to
   be unmistakable, so this is not left to the icon alone. */
.gm-toast.error {
    background: rgba(255,59,48,.12);
    border-color: rgba(255,59,48,.22);
}
.gm-toast-body { font-weight: 600; font-size: 1rem; letter-spacing: -0.008em; color: var(--gma-ink); }
.gm-toast:not(.error) .gm-toast-icon { color: var(--gma-accent-ink); }
.gm-toast.error .gm-toast-icon { color: var(--gma-danger); }

/* ---------- Misc chrome ---------- */

.gm-cf-row { background: var(--gma-surface-2); border: 1px solid transparent; border-radius: var(--gma-r-md); }

.gm-scroll-top {
    width: 44px; height: 44px; font-size: 1.15rem;
    background: rgba(255,255,255,.72);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
    border: 1px solid var(--gma-hairline);
    color: var(--gma-ink);
    box-shadow: var(--gma-shadow-md);
}
.gm-scroll-top:hover { background: #fff; color: var(--gma-ink); transform: none; box-shadow: var(--gma-shadow-lg); }
.gm-scroll-top:active { transform: scale(.94); }


/* ---------- Scanner kiosk ----------
   Deliberately left loud. This is read at arm's length in a noisy doorway,
   so the flash colours stay fully saturated and the type stays huge. */

.gm-scanner-kiosk  { background: var(--gma-surface-2); }
.gm-kiosk-header   { background: rgba(255,255,255,.86); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px); border-bottom: 1px solid var(--gma-hairline); box-shadow: none; }
.gm-kiosk-close    { background: rgba(118,118,128,.12); color: var(--gma-ink-2); transition: background-color .2s var(--gma-ease), transform .2s var(--gma-ease); }
.gm-kiosk-close:hover  { background: rgba(118,118,128,.20); color: var(--gma-ink); }
.gm-kiosk-close:active { transform: scale(.94); }
.gm-kiosk-stats    { color: var(--gma-ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.gm-kiosk-stats span { background: var(--gma-accent); border-radius: 50px; font-weight: 600; }
.gm-kiosk-btn      { border: 1px solid var(--gma-hairline-2); color: var(--gma-ink); font-weight: 600; box-shadow: var(--gma-shadow-sm); transition: background-color .2s var(--gma-ease), transform .2s var(--gma-ease); }
.gm-kiosk-btn:hover  { background: var(--gma-surface-2); border-color: var(--gma-hairline-2); color: var(--gma-ink); }
.gm-kiosk-btn:active { transform: scale(.97); }
.gm-kiosk-search   { border: 1px solid var(--gma-hairline); border-radius: var(--gma-r-lg); box-shadow: var(--gma-shadow-sm); }
/* The door-scanner search box. It was on --gma-hairline-2 (rgba(0,0,0,.12)),
   which is 1.31:1 on white -- the exact "where is the field?" defect, in the
   one place it hurts most: staff searching for an attendee at the door, on a
   phone, in whatever light the venue has. */
.gm-kiosk-search input { background: var(--gma-surface); border: 1px solid var(--gma-field-border); border-radius: var(--gma-r-md); color: var(--gma-ink); }
.gm-kiosk-search input:focus { border-color: var(--gma-accent); box-shadow: 0 0 0 4px var(--gma-accent-ring); }
.gm-flash-title { letter-spacing: -0.02em; }

/* ---------- Keyboard focus ---------- */

.gm-admin-wrapper a:focus-visible,
.gm-admin-wrapper button:focus-visible,
.gm-admin-wrapper input:focus-visible,
.gm-admin-wrapper select:focus-visible,
.gm-admin-wrapper textarea:focus-visible,
.gm-scanner-kiosk button:focus-visible,
.gm-scanner-kiosk input:focus-visible,
.gm-login-card input:focus-visible,
.gm-login-card button:focus-visible,
/* These three are NOT redundant with the element selectors above. The original
   rules at lines 7 and 18 (and the restyle at ~282) are of the form
   ".gm-admin-wrapper .form-control:focus" = (0,3,0), which beats
   ".gm-admin-wrapper input:focus-visible" = (0,2,1). Without a matching
   (0,3,0) selector landing later in the file, their outline:none would keep
   winning and every text field in the dashboard would still focus invisibly. */
.gm-admin-wrapper .form-control:focus-visible,
.gm-admin-wrapper .form-select:focus-visible,
.gm-login-card .input:focus-visible {
    /* Same reasoning as public.css: the soft ring alone is ~1.2:1 and would
       fail WCAG 2.2 SC 1.4.11, so the outline stays. No border-radius here --
       this selector outranks .gm-admin-wrapper .form-control and would snap
       inputs from 12px to 8px corners at the moment they receive focus. */
    outline: 2px solid var(--gma-accent);
    outline-offset: 2px;
    box-shadow: 0 0 0 4px var(--gma-accent-ring);
}

@media (max-width: 768px) {
    /* Both cards are exactly 100vw wide here (the wrapper is width:100vw and
       the card width:100%), so the rounded corners, side borders and the large
       shadow re-introduced by the desktop rules above must all be undone.
       Media queries add no specificity, so the earlier mobile block at lines
       98-126 cannot win on its own -- these have to be restated. */
    .gm-admin-card {
        padding: 1.5rem 15px;
        border-radius: 0;
        border-left: none;
        border-right: none;
        /* The original left a shadow on this card even full-bleed, and the new
           --gma-shadow-lg is twice as dark, which reads as a grey band across
           a square edge-to-edge card. The login card and the public glass card
           both drop it at this width; match them. */
        box-shadow: none;
        border-top: 1px solid var(--gma-hairline);
        border-bottom: 1px solid var(--gma-hairline);
    }
    .gm-login-card {
        border-radius: 0;
        border-left: none;
        border-right: none;
        box-shadow: none;
    }
    /* Up to five tabs share one row at flex:1 with 5px of side padding, so the
       desktop size has to shrink again or the labels wrap. */
    .gm-tab { font-size: 0.85rem; }
    .gm-table tr {
        border: 1px solid var(--gma-hairline);
        border-radius: var(--gma-r-lg);
        box-shadow: var(--gma-shadow-sm);
    }
    .gm-table td { border-bottom: 1px solid var(--gma-hairline) !important; }
    .gm-table td::before { color: var(--gma-ink-3); font-weight: 600; letter-spacing: .02em; }
    .gm-table tr:hover td { background: transparent; }
}

@media (prefers-reduced-motion: reduce) {
    .gm-admin-wrapper *,
    .gm-scanner-kiosk *,
    .gm-toast,
    .gm-scroll-top {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
    .btn-gm-primary:active,
    .btn-gm-secondary:active,
    .btn-gm-danger:active,
    .btn-gm-action:active,
    .gm-kiosk-btn:active,
    .gm-kiosk-close:active,
    .gm-scroll-top:active,
    .checkin-btn:hover { transform: none; }
}

/* Re-assert the icon font last, mirroring the guard public.css already
   carries. The rules above set font-family on the wrapper and everything
   inherits from it, so this has to come after to win. */
.gm-admin-wrapper i.bi,
.gm-admin-wrapper .bi::before,
.gm-scanner-kiosk i.bi,
.gm-scanner-kiosk .bi::before,
.gm-login-card i.bi,
.gm-login-card .bi::before,
.gm-toast i.bi,
.gm-toast .bi::before {
    font-family: "bootstrap-icons" !important;
    font-weight: normal !important;
    letter-spacing: normal !important;
}
/* ---------- Tier pricing notice ----------
   Replaces the Standaard Prijs input when ticket tiers exist, so the form
   never shows two competing prices. Toggled by syncStandardPriceVisibility(). */
.gm-tier-price-note {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-top: 1.9rem;
    padding: 12px 14px;
    font-size: .8125rem;
    line-height: 1.45;
    color: var(--gma-ink-2);
    background-color: var(--gma-accent-wash);
    border: 1px solid rgba(0, 183, 131, 0.22);
    border-radius: var(--gma-r-sm);
}
.gm-tier-price-note > i {
    flex: none;
    margin-top: 1px;
    color: var(--gma-accent-ink);
    font-size: .95rem;
}
.gm-tier-price-note strong { color: var(--gma-ink); font-weight: 600; }
/* ============================================================
   ANALYTICS + ACTIVITY LOG
   Both tabs previously used a different accent colour per card
   (purple / blue / amber / red), which read as six unrelated widgets.
   They now share one neutral surface with a single green accent.
   ============================================================ */

.gm-ana-card, .gm-logs-card { padding: 30px 32px 32px; }
.gm-ana-section { border-top: none !important; }

.gm-logs-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    margin-bottom: 22px;
}
.gm-logs-headline h4 {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 0 0 4px;
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--gma-ink);
}
.gm-logs-headline h4 > i { color: var(--gma-accent-ink); font-size: 1.1rem; }
.gm-logs-headline p { margin: 0; font-size: .875rem; color: var(--gma-ink-2); max-width: 60ch; }
.gm-ana-head { margin-bottom: 24px; }

/* ---------- KPI rail ---------- */
.gm-kpi-rail {
    display: grid;
    grid-template-columns: 1.4fr repeat(4, 1fr);
    gap: 1px;
    background: var(--gma-hairline, rgba(0,0,0,.08));
    border: 1px solid var(--gma-hairline, rgba(0,0,0,.08));
    border-radius: var(--gma-r-md, 14px);
    overflow: hidden;
}
.gm-kpi {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 20px 18px;
    background: #fff;
}
.gm-kpi-hero { background: var(--gma-accent-wash); }
.gm-kpi-label {
    font-size: .6875rem;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--gma-ink-2);
}
.gm-kpi-value {
    font-size: 1.85rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.03em;
    color: var(--gma-ink);
    font-variant-numeric: tabular-nums;
}
.gm-kpi-hero .gm-kpi-value { color: var(--gma-accent-ink); font-size: 2.1rem; }
.gm-kpi-foot {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: .75rem;
    color: var(--gma-ink-2);
}
.gm-kpi-pos { color: var(--gma-accent-ink); }
.gm-kpi-neg { color: #c0392b; }

@media (max-width: 1100px) { .gm-kpi-rail { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 680px)  { .gm-kpi-rail { grid-template-columns: repeat(2, 1fr); }
                             .gm-kpi-value { font-size: 1.5rem; }
                             .gm-kpi-hero .gm-kpi-value { font-size: 1.7rem; } }

/* ---------- log toolbar ---------- */
.gm-logs-tools { display: flex; align-items: center; gap: 10px; }
.gm-logs-search { position: relative; display: flex; align-items: center; }
.gm-logs-search > i {
    position: absolute;
    left: 13px;
    font-size: .85rem;
    color: var(--gma-ink-3, #86868b);
    pointer-events: none;
}
.gm-logs-search input {
    width: 290px;
    max-width: 48vw;
    padding: 9px 34px 9px 34px;
    font: inherit;
    font-size: .875rem;
    color: var(--gma-ink);
    background: var(--gma-surface);
    border: 1px solid var(--gma-field-border);
    border-radius: 999px;
    transition: border-color .18s ease, background .18s ease;
}
.gm-logs-search input::-webkit-search-cancel-button { display: none; }
.gm-logs-search input:focus {
    outline: none;
    background: #fff;
    border-color: var(--gma-accent);
}
.gm-logs-clear {
    position: absolute;
    right: 8px;
    width: 20px; height: 20px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1rem; line-height: 1;
    color: var(--gma-ink-2);
    background: rgba(0,0,0,.07);
    border: 0; border-radius: 50%;
    cursor: pointer;
}
.gm-logs-refresh {
    width: 38px; height: 38px;
    display: flex; align-items: center; justify-content: center;
    color: var(--gma-ink-2);
    background: #fff;
    border: 1px solid var(--gma-hairline, rgba(0,0,0,.08));
    border-radius: 50%;
    cursor: pointer;
    transition: color .18s ease, border-color .18s ease;
}
.gm-logs-refresh:hover { color: var(--gma-accent-ink); border-color: var(--gma-accent); }
.gm-logs-refresh.is-spinning > i { animation: gmSpin .8s linear infinite; }
@keyframes gmSpin { to { transform: rotate(360deg); } }

/* ---------- summary numbers ---------- */
.gm-logs-stats { display: flex; gap: 26px; margin-bottom: 18px; flex-wrap: wrap; }
.gm-logs-stat {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-size: .75rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--gma-ink-2);
}
.gm-logs-stat > span {
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -.02em;
    text-transform: none;
    color: var(--gma-ink);
    font-variant-numeric: tabular-nums;
}

/* ---------- filter chips ---------- */
.gm-log-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 20px; }
.gm-log-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    font: inherit;
    font-size: .78rem;
    font-weight: 600;
    color: var(--gma-ink-2);
    background: #fff;
    border: 1px solid var(--gma-hairline, rgba(0,0,0,.08));
    border-radius: 999px;
    cursor: pointer;
    transition: color .16s ease, border-color .16s ease, background .16s ease;
}
.gm-log-chip > i { font-size: .8rem; }
.gm-log-chip > span {
    padding: 1px 6px;
    font-size: .7rem;
    font-weight: 700;
    color: var(--gma-ink-2);
    background: var(--gma-surface-2, #f5f5f7);
    border-radius: 999px;
    font-variant-numeric: tabular-nums;
}
.gm-log-chip:hover { border-color: var(--gma-ink-3, #86868b); color: var(--gma-ink); }
.gm-log-chip.is-on {
    color: #fff;
    background: var(--gma-accent);
    border-color: var(--gma-accent);
}
.gm-log-chip.is-on > span { color: #fff; background: rgba(255,255,255,.25); }

/* ---------- the feed ---------- */
.gm-log-feed { list-style: none; margin: 0; padding: 0; }
.gm-log-item {
    position: relative;
    display: flex;
    gap: 14px;
    padding: 16px 4px 16px 0;
    border-bottom: 1px solid var(--gma-hairline, rgba(0,0,0,.08));
}
.gm-log-item:last-child { border-bottom: 0; }

/* Connector line joining consecutive entries into one timeline. */
.gm-log-item::before {
    content: "";
    position: absolute;
    left: 17px;
    top: 48px;
    bottom: -1px;
    width: 1px;
    background: var(--gma-hairline, rgba(0,0,0,.08));
}
.gm-log-item:last-child::before { display: none; }

.gm-log-dot {
    position: relative;
    z-index: 1;
    flex: none;
    width: 35px; height: 35px;
    display: flex; align-items: center; justify-content: center;
    font-size: .9rem;
    border-radius: 50%;
    background: var(--gma-surface-2, #f5f5f7);
    color: var(--gma-ink-2);
}
.gm-tone-ok   .gm-log-dot { background: var(--gma-accent-wash); color: var(--gma-accent-ink); }
.gm-tone-info .gm-log-dot { background: #eef2f7; color: #4a5568; }
.gm-tone-warn .gm-log-dot { background: #fff4e5; color: #b25000; }
.gm-tone-bad  .gm-log-dot { background: #fdecea; color: #c0392b; }

.gm-log-main { flex: 1 1 auto; min-width: 0; }
.gm-log-top { display: flex; align-items: baseline; gap: 10px; justify-content: space-between; }
.gm-log-type {
    font-size: .875rem;
    font-weight: 650;
    color: var(--gma-ink);
    letter-spacing: -.01em;
}
.gm-log-time { flex: none; font-size: .75rem; color: var(--gma-ink-3, #86868b); white-space: nowrap; }
.gm-log-details {
    margin: 3px 0 7px;
    font-size: .8125rem;
    line-height: 1.5;
    color: var(--gma-ink-2);
    overflow-wrap: anywhere;
}
.gm-log-who {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: .75rem;
    color: var(--gma-ink-3, #86868b);
}
.gm-log-avatar {
    width: 19px; height: 19px;
    display: flex; align-items: center; justify-content: center;
    font-size: .625rem;
    font-weight: 700;
    color: #fff;
    background: var(--gma-accent);
    border-radius: 50%;
}
.gm-log-feed mark {
    padding: 0 2px;
    color: inherit;
    background: rgba(0,183,131,.22);
    border-radius: 3px;
}

/* ---------- empty + loading ---------- */
.gm-log-empty {
    padding: 54px 20px;
    text-align: center;
    color: var(--gma-ink-2);
}
.gm-log-empty > i { font-size: 2rem; color: var(--gma-ink-3, #86868b); opacity: .55; }
.gm-log-empty > p { margin: 12px 0 2px; font-size: .95rem; font-weight: 600; color: var(--gma-ink); }
.gm-log-empty > small { font-size: .8125rem; }

.gm-log-skeleton {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 18px 0;
    border-bottom: 1px solid var(--gma-hairline, rgba(0,0,0,.08));
}
.gm-log-skeleton > span {
    height: 11px;
    border-radius: 6px;
    background: linear-gradient(90deg, #f0f0f2 25%, #e6e6e9 37%, #f0f0f2 63%);
    background-size: 400% 100%;
    animation: gmShimmer 1.3s ease infinite;
}
.gm-log-skeleton > span:nth-child(1) { flex: none; width: 35px; height: 35px; border-radius: 50%; }
.gm-log-skeleton > span:nth-child(2) { width: 28%; }
.gm-log-skeleton > span:nth-child(3) { flex: 1; }
@keyframes gmShimmer { from { background-position: 100% 50%; } to { background-position: 0 50%; } }

/* ---------- footer ---------- */
.gm-logs-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-top: 20px;
    padding-top: 18px;
    border-top: 1px solid var(--gma-hairline, rgba(0,0,0,.08));
}
.gm-logs-foot[hidden] { display: none; }
.gm-logs-foot-left, .gm-logs-foot-right { display: flex; align-items: center; gap: 10px; }
.gm-logs-foot label, .gm-logs-count, #logsPageInfo {
    font-size: .8125rem;
    color: var(--gma-ink-2);
}
.gm-logs-foot select {
    padding: 5px 9px;
    font: inherit;
    font-size: .8125rem;
    color: var(--gma-ink);
    background: #fff;
    border: 1px solid var(--gma-field-border);
    border-radius: 8px;
    cursor: pointer;
}
.gm-logs-foot-right button {
    width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    color: var(--gma-ink-2);
    background: #fff;
    border: 1px solid var(--gma-hairline, rgba(0,0,0,.08));
    border-radius: 8px;
    cursor: pointer;
}
.gm-logs-foot-right button:disabled { opacity: .35; cursor: default; }
.gm-logs-foot-right button:not(:disabled):hover { color: var(--gma-accent-ink); border-color: var(--gma-accent); }

@media (max-width: 620px) {
    .gm-ana-card, .gm-logs-card { padding: 22px 18px 24px; }
    .gm-logs-head { flex-direction: column; }
    .gm-logs-tools { width: 100%; }
    .gm-logs-search { flex: 1; }
    .gm-logs-search input { width: 100%; max-width: none; }
    .gm-log-top { flex-direction: column; gap: 2px; }
}

@media (prefers-reduced-motion: reduce) {
    .gm-log-skeleton > span, .gm-logs-refresh.is-spinning > i { animation: none; }
}
/* =========================================================================
   GM DESIGN SYSTEM  --  shared primitives
   =========================================================================
   Distilled from the activity-log tab. Every panel, table, form and toolbar
   in the admin consumes these, so the whole plugin moves together instead of
   each tab inventing its own look out of raw Bootstrap utilities.

   Appended last on purpose: admin.css is ORIGINAL + APPENDED layers, and
   media queries add no specificity, so anything that must win has to be
   physically last in the file.
   ========================================================================= */

/* ---------- PANEL ---------- */
.gm-panel {
    background: var(--gma-surface);
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-xl);
    box-shadow: var(--gma-shadow-sm);
    padding: 1.75rem 1.75rem 1.5rem;
    margin-bottom: 1.25rem;
    font-family: var(--gma-font);
    box-sizing: border-box;
}
.gm-panel + .gm-panel { margin-top: 1.25rem; }

.gm-panel-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1.25rem;
}
.gm-panel-headline { min-width: 0; flex: 1 1 320px; }
.gm-panel-headline h4,
.gm-panel-headline h5 {
    display: flex;
    align-items: center;
    gap: .55rem;
    font-size: 1.0625rem;
    font-weight: 650;
    letter-spacing: -.012em;
    color: var(--gma-ink);
    margin: 0 0 .3rem;
    line-height: 1.3;
}
.gm-panel-headline h4 > i,
.gm-panel-headline h5 > i {
    font-size: 1rem;
    color: var(--gma-accent-ink);
    flex: none;
}
.gm-panel-headline p {
    font-size: .8125rem;
    line-height: 1.45;
    color: var(--gma-ink-2);
    margin: 0;
    max-width: 62ch;
}
.gm-panel-headline p strong { color: var(--gma-ink); font-weight: 600; }
.gm-panel-tools {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    flex: none;
}

/* Section divider inside a panel */
.gm-panel-rule {
    height: 1px;
    background: var(--gma-hairline);
    border: 0;
    margin: 1.25rem 0;
}

/* ---------- BUTTONS ---------- */
.gm-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .45rem;
    font-family: var(--gma-font);
    font-size: .8125rem;
    font-weight: 600;
    letter-spacing: -.005em;
    line-height: 1;
    padding: .55rem 1rem;
    border-radius: 980px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--gma-ink);
    cursor: pointer;
    white-space: nowrap;
    transition: background-color .18s var(--gma-ease), border-color .18s var(--gma-ease),
                color .18s var(--gma-ease), filter .18s var(--gma-ease), transform .18s var(--gma-ease);
}
.gm-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px var(--gma-accent-ring);
}
.gm-btn:disabled, .gm-btn[disabled] { opacity: .45; cursor: not-allowed; }
.gm-btn > i { font-size: .9em; }

.gm-btn-primary { background: var(--gma-accent); color: #fff; }
.gm-btn-primary:hover:not(:disabled) { filter: brightness(.92); color: #fff; }
.gm-btn-primary:active:not(:disabled) { filter: brightness(.86); }

.gm-btn-ghost {
    background: var(--gma-surface);
    border-color: var(--gma-hairline-2);
    color: var(--gma-ink);
}
.gm-btn-ghost:hover:not(:disabled) { background: var(--gma-surface-2); color: var(--gma-ink); }

.gm-btn-quiet { background: var(--gma-surface-2); color: var(--gma-ink); }
.gm-btn-quiet:hover:not(:disabled) { filter: brightness(.96); }

.gm-btn-accent {
    background: var(--gma-accent-wash);
    color: var(--gma-accent-ink);
    border-color: transparent;
}
.gm-btn-accent:hover:not(:disabled) { background: var(--gma-accent-ring); color: var(--gma-accent-ink); }

.gm-btn-danger { background: rgba(215,0,21,.08); color: var(--gma-danger); }
.gm-btn-danger:hover:not(:disabled) { background: rgba(215,0,21,.14); color: var(--gma-danger); }

.gm-btn-sm { font-size: .75rem; padding: .4rem .75rem; }
.gm-btn-icon {
    width: 34px; height: 34px; padding: 0; flex: none;
    border-radius: 50%;
    background: var(--gma-surface-2);
    color: var(--gma-ink-2);
}
.gm-btn-icon:hover:not(:disabled) { background: var(--gma-accent-wash); color: var(--gma-accent-ink); }
.gm-btn-icon > i { font-size: .95rem; }
.gm-btn-icon.is-spinning > i { animation: gmSpin .7s linear infinite; }
@keyframes gmSpin { to { transform: rotate(360deg); } }

/* ---------- FORM CONTROLS ---------- */
.gm-field { margin-bottom: 1rem; }
.gm-field-label {
    display: block;
    font-size: .75rem;
    font-weight: 650;
    letter-spacing: .005em;
    color: var(--gma-ink);
    margin-bottom: .4rem;
}
.gm-field-label .gm-req { color: var(--gma-danger); margin-left: .15rem; }
.gm-field-help {
    display: block;
    font-size: .75rem;
    line-height: 1.45;
    color: var(--gma-ink-2);
    margin-top: .4rem;
}

.gm-input, .gm-select, .gm-textarea {
    width: 100%;
    font-family: var(--gma-font);
    font-size: .875rem;
    font-weight: 500;
    color: var(--gma-ink);
    background: var(--gma-surface);
    border: 1px solid var(--gma-field-border);
    border-radius: var(--gma-r-md);
    padding: .625rem .875rem;
    box-sizing: border-box;
    transition: background-color .18s var(--gma-ease), border-color .18s var(--gma-ease),
                box-shadow .18s var(--gma-ease);
}
.gm-textarea { min-height: 96px; resize: vertical; line-height: 1.5; }
.gm-input::placeholder, .gm-textarea::placeholder { color: var(--gma-ink-3); }
.gm-input:focus, .gm-select:focus, .gm-textarea:focus {
    outline: none;
    background: var(--gma-surface);
    border-color: var(--gma-accent);
    box-shadow: 0 0 0 4px var(--gma-accent-ring);
}
.gm-select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 2.25rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' fill='none' stroke='%236e6e73' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .75rem center;
    cursor: pointer;
}
.gm-select-auto { width: auto; min-width: 150px; }
.gm-input-sm, .gm-select-sm { font-size: .8125rem; padding: .45rem .7rem; }
.gm-select-sm { padding-right: 2rem; background-position: right .6rem center; }

/* Search box (the pattern the log tab uses) */
.gm-search {
    position: relative;
    display: flex;
    align-items: center;
    flex: 1 1 240px;
    min-width: 0;
    max-width: 340px;
}
.gm-search > i {
    position: absolute;
    left: .8rem;
    font-size: .8125rem;
    color: var(--gma-ink-3);
    pointer-events: none;
}
.gm-search input {
    width: 100%;
    font-family: var(--gma-font);
    font-size: .8125rem;
    font-weight: 500;
    color: var(--gma-ink);
    background: var(--gma-surface);
    border: 1px solid var(--gma-field-border);
    border-radius: 980px;
    padding: .5rem 2rem .5rem 2.1rem;
    box-sizing: border-box;
    transition: background-color .18s var(--gma-ease), border-color .18s var(--gma-ease),
                box-shadow .18s var(--gma-ease);
}
.gm-search input::-webkit-search-cancel-button { display: none; }
.gm-search input:focus {
    outline: none;
    background: var(--gma-surface);
    border-color: var(--gma-accent);
    box-shadow: 0 0 0 4px var(--gma-accent-ring);
}
.gm-search-clear {
    position: absolute;
    right: .45rem;
    width: 20px; height: 20px;
    display: grid; place-items: center;
    border: 0; padding: 0;
    border-radius: 50%;
    background: var(--gma-hairline);
    color: var(--gma-ink-2);
    font-size: .8rem; line-height: 1;
    cursor: pointer;
}
.gm-search-clear:hover { background: var(--gma-hairline-2); color: var(--gma-ink); }

/* Toolbar strip (filters) */
.gm-toolbar {
    display: flex;
    align-items: center;
    gap: .6rem;
    flex-wrap: wrap;
    padding: .7rem .85rem;
    background: var(--gma-surface-2);
    border-radius: var(--gma-r-lg);
    margin-bottom: 1.1rem;
}
.gm-toolbar-label {
    font-size: .75rem;
    font-weight: 650;
    color: var(--gma-ink-2);
    letter-spacing: .005em;
    flex: none;
}
.gm-toolbar .gm-select { background: var(--gma-surface); }
.gm-toolbar-end { margin-left: auto; display: flex; align-items: center; gap: .5rem; }
.gm-toolbar-total {
    font-size: .8125rem;
    font-weight: 600;
    color: var(--gma-ink-2);
}
.gm-toolbar-total b {
    font-weight: 700;
    color: var(--gma-ink);
    font-variant-numeric: tabular-nums;
    font-size: 1rem;
    margin-left: .25rem;
}

/* ---------- BADGES / TONES ---------- */
.gm-badge {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .6875rem;
    font-weight: 650;
    letter-spacing: .01em;
    line-height: 1;
    padding: .32rem .6rem;
    border-radius: 980px;
    background: var(--gma-surface-2);
    color: var(--gma-ink-2);
    white-space: nowrap;
}
.gm-badge > i { font-size: .85em; }
.gm-badge-ok    { background: var(--gma-accent-wash); color: var(--gma-accent-ink); }
.gm-badge-info  { background: rgba(0,99,201,.10);    color: var(--gma-blue); }
.gm-badge-warn  { background: rgba(178,80,0,.10);    color: var(--gma-warn); }
.gm-badge-bad   { background: rgba(215,0,21,.09);    color: var(--gma-danger); }
.gm-badge-dot::before {
    content: ''; width: 6px; height: 6px; border-radius: 50%;
    background: currentColor; flex: none;
}

/* ---------- DATA TABLE ---------- */
.gm-dt {
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-lg);
    overflow: hidden;
    background: var(--gma-surface);
}
.gm-dt-scroll { max-height: 460px; overflow-y: auto; }
.gm-dt table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--gma-font);
    margin: 0;
}
.gm-dt thead th {
    position: sticky; top: 0; z-index: 1;
    background: var(--gma-surface-2);
    font-size: .6875rem;
    font-weight: 650;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--gma-ink-2);
    text-align: left;
    padding: .7rem .9rem;
    border-bottom: 1px solid var(--gma-hairline);
    white-space: nowrap;
}
.gm-dt tbody td {
    font-size: .8125rem;
    color: var(--gma-ink);
    padding: .75rem .9rem;
    border-bottom: 1px solid var(--gma-hairline);
    vertical-align: middle;
}
.gm-dt tbody tr:last-child td { border-bottom: 0; }
.gm-dt tbody tr { transition: background-color .15s var(--gma-ease); }
.gm-dt tbody tr:hover { background: rgba(0,0,0,.015); }
.gm-dt .gm-dt-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-weight: 600;
}
.gm-dt .gm-dt-center { text-align: center; }
.gm-dt .gm-dt-strong { font-weight: 600; }
.gm-dt .gm-dt-muted { color: var(--gma-ink-2); }
.gm-dt-name { display: flex; align-items: center; gap: .55rem; min-width: 0; }
.gm-dt-name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Avatar initials, same device the log feed uses */
.gm-avatar {
    width: 28px; height: 28px; flex: none;
    border-radius: 50%;
    display: grid; place-items: center;
    background: var(--gma-accent-wash);
    color: var(--gma-accent-ink);
    font-size: .6875rem;
    font-weight: 700;
    letter-spacing: .01em;
    text-transform: uppercase;
}
.gm-avatar-muted { background: var(--gma-surface-2); color: var(--gma-ink-2); }

/* ---------- EMPTY STATE ---------- */
.gm-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: .5rem;
    padding: 2.75rem 1.5rem;
    color: var(--gma-ink-2);
}
.gm-empty-icon {
    width: 44px; height: 44px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: var(--gma-surface-2);
    color: var(--gma-ink-3);
    font-size: 1.15rem;
    margin-bottom: .15rem;
}
.gm-empty-title {
    font-size: .9375rem;
    font-weight: 650;
    color: var(--gma-ink);
    letter-spacing: -.01em;
}
.gm-empty-text { font-size: .8125rem; line-height: 1.5; max-width: 42ch; margin: 0; }
td > .gm-empty, th > .gm-empty { padding: 2.25rem 1rem; }

/* ---------- SKELETON ---------- */
.gm-skel {
    display: block;
    height: 11px;
    border-radius: 6px;
    background: linear-gradient(90deg, var(--gma-surface-2) 25%, rgba(0,0,0,.05) 37%, var(--gma-surface-2) 63%);
    background-size: 400% 100%;
    animation: gmSkel 1.4s ease infinite;
}
@keyframes gmSkel { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.gm-dt-skel td { padding: .85rem .9rem; }

/* ---------- PAGER ---------- */
.gm-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: .85rem .25rem 0;
    margin-top: .25rem;
    border-top: 1px solid var(--gma-hairline);
}
.gm-pager-left, .gm-pager-right { display: flex; align-items: center; gap: .55rem; }
.gm-pager label { font-size: .75rem; font-weight: 600; color: var(--gma-ink-2); margin: 0; }
.gm-pager .gm-select { width: auto; min-width: 72px; background: var(--gma-surface); }
.gm-pager-count { font-size: .75rem; color: var(--gma-ink-2); font-weight: 600; }
.gm-pager-count b { color: var(--gma-ink); font-variant-numeric: tabular-nums; }
.gm-pager-info {
    font-size: .75rem; font-weight: 600; color: var(--gma-ink-2);
    font-variant-numeric: tabular-nums; min-width: 104px; text-align: center;
}
.gm-pager button {
    width: 32px; height: 32px; padding: 0;
    display: grid; place-items: center;
    border: 1px solid var(--gma-hairline-2);
    border-radius: 50%;
    background: var(--gma-surface);
    color: var(--gma-ink);
    cursor: pointer;
    transition: background-color .18s var(--gma-ease), opacity .18s var(--gma-ease);
}
.gm-pager button:hover:not(:disabled) { background: var(--gma-surface-2); }
.gm-pager button:disabled { opacity: .35; cursor: not-allowed; }

/* ---------- SEGMENTED CONTROL (sub-tabs inside a panel) ---------- */
.gm-seg {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    background: var(--gma-surface-2);
    border-radius: 980px;
    margin-bottom: 1.1rem;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
}
.gm-seg::-webkit-scrollbar { display: none; }
.gm-seg button {
    display: inline-flex; align-items: center; gap: .4rem;
    font-family: var(--gma-font);
    font-size: .8125rem; font-weight: 600; letter-spacing: -.005em;
    padding: .45rem .95rem;
    border: 0; border-radius: 980px;
    background: transparent;
    color: var(--gma-ink-2);
    cursor: pointer; white-space: nowrap;
    transition: background-color .2s var(--gma-ease), color .2s var(--gma-ease);
}
.gm-seg button:hover { color: var(--gma-ink); }
.gm-seg button.active {
    background: var(--gma-surface);
    color: var(--gma-ink);
    box-shadow: var(--gma-shadow-sm);
}
.gm-seg button > i { font-size: .85em; }

/* ---------- RESPONSIVE ---------- */
@media (max-width: 768px) {
    .gm-panel { padding: 1.25rem 1.1rem 1.1rem; border-radius: var(--gma-r-lg); }
    .gm-panel-head { flex-direction: column; align-items: stretch; gap: .85rem; }
    /* flex-basis follows the MAIN axis, so the 320px basis that gives the
       headline a sensible minimum WIDTH in the default row layout becomes a
       320px minimum HEIGHT the moment this container turns into a column --
       a 320px-tall box around two lines of text. Reset it to the content
       height. (.gm-logs-head is a different class and never had this.) */
    .gm-panel-headline { flex: 0 0 auto; }
    .gm-panel-tools { width: 100%; }
    .gm-search { max-width: none; flex: 1 1 100%; }
    .gm-toolbar { padding: .65rem .7rem; }
    .gm-toolbar-end { margin-left: 0; width: 100%; justify-content: space-between; }
    .gm-pager { justify-content: center; }
    .gm-pager-left, .gm-pager-right { width: 100%; justify-content: center; }

    /* Card-style rows: the header row is hidden and each cell carries its own
       label, so wide tables stay readable without horizontal scrolling. */
    .gm-dt-cards thead { display: none; }
    .gm-dt-cards, .gm-dt-cards tbody, .gm-dt-cards tr, .gm-dt-cards td { display: block; width: 100%; }
    .gm-dt-cards tbody tr {
        border-bottom: 1px solid var(--gma-hairline);
        padding: .35rem 0;
    }
    .gm-dt-cards tbody tr:last-child { border-bottom: 0; }
    .gm-dt-cards tbody td {
        display: flex; align-items: center; justify-content: space-between;
        gap: 1rem; border-bottom: 0; padding: .4rem .9rem; text-align: right;
    }
    .gm-dt-cards tbody td::before {
        content: attr(data-label);
        font-size: .6875rem; font-weight: 650; letter-spacing: .03em;
        text-transform: uppercase; color: var(--gma-ink-2);
        text-align: left; flex: none;
    }
    .gm-dt-cards tbody td:empty { display: none; }
    .gm-dt .gm-dt-num { text-align: right; }
}

@media (prefers-reduced-motion: reduce) {
    .gm-skel { animation: none; }
    .gm-btn-icon.is-spinning > i { animation: none; }
    .gm-btn, .gm-input, .gm-select, .gm-textarea, .gm-dt tbody tr, .gm-seg button { transition: none; }
}

/* ---------- SPLIT (chart beside table) ---------- */
.gm-split { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 1.75rem; align-items: center; }
.gm-split-chart { min-width: 0; display: grid; place-items: center; }
.gm-split-chart canvas { max-width: 100%; height: auto !important; }
.gm-split-table { min-width: 0; }
@media (max-width: 860px) {
    .gm-split { grid-template-columns: 1fr; gap: 1.25rem; }
    .gm-split-chart { max-width: 260px; margin: 0 auto; }
}

/* Short explanatory line under a sub-tab, above its table */
.gm-section-note {
    font-size: .8125rem;
    line-height: 1.5;
    color: var(--gma-ink-2);
    margin: 0 0 .9rem;
    max-width: 72ch;
}
.gm-section-note strong { color: var(--gma-ink); font-weight: 600; }
/* Legend swatch + percentage, used by the sources table */
.gm-swatch { width: 10px; height: 10px; border-radius: 50%; flex: none; display: inline-block; }
.gm-dt-pct {
    display: inline-block;
    margin-left: .5rem;
    min-width: 36px;
    font-size: .6875rem;
    font-weight: 650;
    color: var(--gma-ink-2);
    font-variant-numeric: tabular-nums;
}
/* ---------- ROW PRIMITIVES ---------- */
.gm-badge-stack { display: inline-flex; flex-wrap: wrap; gap: .3rem; align-items: center; }
.gm-ev-name { font-weight: 600; color: var(--gma-ink); margin-bottom: .3rem; letter-spacing: -.005em; }
.gm-count-pill { min-width: 30px; justify-content: center; font-size: .8125rem; font-weight: 700; padding: .3rem .55rem; }
.gm-amount { color: var(--gma-accent-ink); font-weight: 650; }

/* Capacity: the number carries the meaning, the bar gives it shape at a glance */
.gm-cap { display: flex; flex-direction: column; gap: .3rem; min-width: 92px; }
.gm-cap-num { font-size: .8125rem; font-weight: 650; color: var(--gma-ink); font-variant-numeric: tabular-nums; }
.gm-cap-num span { color: var(--gma-ink-2); font-weight: 500; }
.gm-cap-bar { display: block; height: 4px; border-radius: 980px; background: var(--gma-hairline); overflow: hidden; }
.gm-cap-bar > span { display: block; height: 100%; border-radius: 980px; background: var(--gma-accent); transition: width .4s var(--gma-ease); }
.gm-cap.is-high .gm-cap-bar > span { background: var(--gma-warn); }
.gm-cap.is-full .gm-cap-bar > span { background: var(--gma-danger); }

/* Action cluster on a table row */
.gm-row-actions { display: flex; flex-wrap: wrap; gap: .35rem; justify-content: flex-end; }
@media (max-width: 768px) {
    .gm-row-actions { justify-content: flex-start; }
    .gm-cap { min-width: 0; align-items: flex-end; }
    .gm-cap-bar { width: 90px; }
}
/* ---------- PAGE HEADER ---------- */
.gm-page-head {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 1.25rem; margin-bottom: 1.75rem; flex-wrap: wrap;
}
.gm-page-head-text { min-width: 0; }
.gm-page-sub {
    margin: .35rem 0 0; font-size: .9375rem; color: var(--gma-ink-2);
    letter-spacing: -.008em;
}
.gm-page-sub strong { color: var(--gma-ink); font-weight: 600; }
.gm-page-signout {
    margin-left: .6rem; padding-left: .6rem; border-left: 1px solid var(--gma-hairline);
    color: var(--gma-ink-3); text-decoration: none; font-size: .875rem; font-weight: 500;
    transition: color .2s var(--gma-ease);
}
.gm-page-signout:hover { color: var(--gma-danger); text-decoration: none; }
.gm-page-head-actions { display: flex; gap: .6rem; align-items: center; flex-shrink: 0; }
@media (max-width: 768px) {
    .gm-page-head-actions { width: 100%; }
    .gm-page-head-actions .gm-btn { width: 100%; justify-content: center; }
}

/* A 3-up KPI rail; the 5-up default rail is sized for the analytics header */
.gm-kpi-rail-3 { grid-template-columns: 1.4fr 1fr 1fr; }
@media (max-width: 900px) { .gm-kpi-rail-3 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .gm-kpi-rail-3 { grid-template-columns: 1fr; } }
/* ---------- LEGACY TABLE -> DESIGN SYSTEM ----------
   .gm-table is used by the events list and the manage view. It used to render
   each row as a floating rounded card (border-spacing + per-row shadow), which
   reads very differently from the flush, hairline-ruled tables everywhere else.
   This flattens it to match without touching a single template.

   Scoped to >=769px on purpose: the max-width:768px block above turns every row
   into a stacked card, and because media queries add no specificity an
   unscoped override here would land later in the cascade and destroy it. */
@media (min-width: 769px) {
    .gm-table { border-spacing: 0; border-collapse: collapse; }
    .gm-table th {
        position: sticky; top: 0; z-index: 2;
        background: var(--gma-surface-2);
        border-bottom: 1px solid var(--gma-hairline);
        padding: .7rem 1rem;
        font-size: .75rem; font-weight: 600;
        letter-spacing: .02em; text-transform: uppercase;
        color: var(--gma-ink-3); white-space: nowrap;
    }
    .gm-table td {
        padding: .85rem 1rem;
        border: 0;
        border-bottom: 1px solid var(--gma-hairline);
        background: transparent;
        font-size: .9375rem; color: var(--gma-ink);
        vertical-align: middle;
    }
    .gm-table tr td:first-child,
    .gm-table tr td:last-child { border-left: 0; border-right: 0; border-radius: 0; font-weight: inherit; }
    .gm-table tbody tr:last-child td { border-bottom: 0; }
    .gm-table tbody tr:hover td { background: var(--gma-surface-2); }
}

/* The events table is a panel, not a floating slab */
#eventsTableCard {
    border-top: 0 !important;
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-lg);
    box-shadow: var(--gma-shadow-sm);
    padding: 0;
    /* NOT `overflow: hidden`. This element is also the .gm-table-wrap scroller,
       and the shorthand sets overflow-x too -- which quietly cancelled
       `.gm-table-wrap { overflow-x: auto }` and, because .gm-table carries
       min-width: 850px above the 768px card layout, left the right-hand
       columns clipped and unreachable on every iPad (measured: the table needs
       850px inside 673-790px of content). overflow-y still clips, so the
       rounded corners are kept. */
    overflow-x: auto;
    overflow-y: hidden;
}
@media (max-width: 768px) {
    #eventsTableCard { border: 0; border-radius: 0; box-shadow: none; background: transparent; }
}
/* ---------- NARROW FORM COLUMN ---------- */
.gm-form-narrow { max-width: 560px; padding-top: 1.25rem; }
.gm-field-actions { display: flex; gap: .6rem; align-items: center; margin-top: 1.25rem; }
@media (max-width: 768px) {
    .gm-field-actions { flex-direction: column; align-items: stretch; }
    .gm-field-actions .gm-btn { width: 100%; justify-content: center; }
}
/* ---------- MANAGE VIEW ---------- */
.gm-back-btn { margin-bottom: 1.25rem; }

.gm-stat-row { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .6rem; }
.gm-stat-chip {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .32rem .7rem; border-radius: 980px;
    background: var(--gma-surface-2); border: 1px solid var(--gma-hairline);
    font-size: .8125rem; font-weight: 600; color: var(--gma-ink-2);
    font-variant-numeric: tabular-nums;
}
.gm-stat-chip-accent {
    background: var(--gma-accent-wash); border-color: var(--gma-accent-ring);
    color: var(--gma-accent-ink);
}
.gm-wrap-actions { flex-wrap: wrap; }

/* An inset panel reads as a secondary surface inside the page */
.gm-panel-inset { background: var(--gma-surface-2); }
.gm-panel-headline-sm h4 { font-size: 1rem; }
.gm-panel-headline-sm p { font-size: .8125rem; }

/* Inline form: fields flow on one row on desktop, stack on mobile */
.gm-inline-form {
    display: flex; flex-wrap: wrap; gap: .75rem; align-items: flex-end;
    margin-top: 1.1rem;
}
.gm-inline-form .gm-field { margin-bottom: 0; }
.gm-field-grow { flex: 1 1 180px; min-width: 0; }
.gm-field-action { flex: 0 0 auto; }
/* Below the desktop layout this becomes a grid rather than a single stacked
   column. The column stack was written for phones and then applied to
   everything under 768px, so an iPad in portrait -- which has room for three
   fields side by side -- rendered the same one-per-row tower as a 390px phone
   and stood 636px tall. auto-fit lets the row fill whatever width there is:
   one column on a phone, three on a tablet, without a breakpoint per device.

   The cut-off is 1024px, not 782px. Above 782px the desktop flex row took over
   and shared the width equally between the fields, which at 820-1024px left
   every field about 183-223px wide -- measured, the e-mail field needs 277px to
   show an ordinary address and the name field 193px, so a tablet user could not
   read what they had just typed. The grid gives the row a sensible column count
   at those widths instead. */
@media (max-width: 1024px) {
    .gm-inline-form {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(13.75rem, 1fr));
        align-items: end;
    }
    /* An e-mail address is roughly twice as long as a name or a type, so an
       equal share of the row is the wrong share. Spanning two columns is
       self-limiting: where auto-fit only produced one column, on a phone, the
       span is clamped back to that one column. */
    .gm-field-wide { grid-column: span 2; }
    /* The action is the end of the form, not another field, so it always takes
       its own full-width row instead of being dealt into the grid. */
    .gm-field-action { grid-column: 1 / -1; }
    .gm-field-action .gm-btn { width: 100%; justify-content: center; }
}

/* ---------- collapsible panel (see #manualAddBox in dashboard-view.php) ----------
   summary is display:none on desktop, so the panel renders exactly as it did
   before this existed: the headline below it is the real heading and nothing
   is clickable. It only becomes a disclosure where the height actually hurts. */
.gm-disclosure-summary { display: none; }
.gm-disclosure-chevron { transition: transform .18s var(--gma-ease); flex: 0 0 auto; }

@media (max-width: 782px) {
    .gm-disclosure-summary {
        display: flex; align-items: center; justify-content: space-between;
        gap: .75rem; min-height: 44px; cursor: pointer;
        font-size: .9375rem; font-weight: 650; color: var(--gma-ink);
        /* Both are needed: the modern property and the WebKit pseudo-element. */
        list-style: none;
    }
    .gm-disclosure-summary::-webkit-details-marker { display: none; }
    .gm-disclosure-summary:focus-visible {
        outline: 2px solid var(--gma-accent); outline-offset: 3px;
        border-radius: var(--gma-r-sm);
    }
    .gm-disclosure-label { display: inline-flex; align-items: center; gap: .5rem; min-width: 0; }
    .gm-disclosure[open] .gm-disclosure-chevron { transform: rotate(180deg); }

    /* Collapsed, the panel is nothing but its summary row, so the padding that
       exists to sit under a form leaves a dead band below the label. */
    .gm-disclosure:not([open]) { padding-bottom: .75rem; }

    /* The summary already names the panel; the h4 under it would say it twice.
       The description line is kept -- it is the part that explains the panel. */
    .gm-disclosure > .gm-panel-headline h4 { display: none; }
    .gm-disclosure > .gm-panel-headline { margin: .75rem 0 0; }
}

@media (prefers-reduced-motion: reduce) {
    .gm-disclosure-chevron { transition: none; }
}

/* ---------- touch sizing ----------
   Measured, not guessed: on a 390px viewport the text inputs came back 41px
   tall and the Toevoegen button 33px, both under the ~44px a fingertip needs.

   The width test is <=1024px rather than the phone breakpoint because an iPad
   in landscape is exactly 1024px wide and is no less a touch device -- that gap
   between the phone rules and the desktop layout is most of what "optimised for
   mobile but not for tablet" means here. pointer:coarse is ORed in so a tablet
   wider than 1024px is covered as well, and neither branch can reach a mouse
   driven desktop.

   The 16px font-size is not cosmetic. Safari on iOS zooms the viewport in when
   a focused field's text is under 16px and does not zoom back out, which throws
   the rest of the form off-screen mid-entry.

   .gm-btn-icon needs its width raised alongside: it sets an explicit 34px box,
   and min-height alone would stretch the circle into an oval. */
@media (max-width: 1024px), (pointer: coarse) {
    .gm-input,
    .gm-select,
    .gm-textarea,
    .gm-search input {
        min-height: 44px;
        font-size: 1rem;
    }
    .gm-btn { min-height: 44px; }
    .gm-btn-icon { width: 44px; height: 44px; }

    /* The rest of the touch surface is handled at the very end of this file --
       see "TOUCH TARGET FLOOR". It cannot live here: .gm-act, .gm-tab and the
       pager buttons are all re-declared further down, and a later rule of equal
       specificity wins regardless of the media query. */
}

/* Switch row */
.gm-switch {
    display: flex; align-items: center; gap: .6rem;
    margin: 1rem 0 0; cursor: pointer;
    font-size: .875rem; color: var(--gma-ink-2);
}
/* .gm-switch input is a self-contained toggle, defined near the end of this file. */
/* Manage-view toolbar row */
.gm-manage-tools { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; justify-content: flex-end; }
.gm-manage-tools .gm-search { width: 250px; max-width: 100%; }
@media (max-width: 768px) {
    .gm-manage-tools { justify-content: stretch; }
    .gm-manage-tools .gm-search { width: 100%; }
    .gm-manage-tools .gm-btn { flex: 1 1 auto; justify-content: center; }
}

.gm-toolbar-divider { width: 1px; align-self: stretch; min-height: 24px; background: var(--gma-hairline); margin: 0 .25rem; }
.gm-check { display: inline-flex; align-items: center; gap: .45rem; margin: 0; cursor: pointer; font-size: .875rem; font-weight: 500; color: var(--gma-ink-2); }
/* .gm-check input is a self-contained checkbox, defined near the end of this file. */

/* Tables that stand alone (not already inside a .gm-panel) get the panel chrome */
.gm-table-panel {
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-lg);
    box-shadow: var(--gma-shadow-sm);
    background: var(--gma-surface);
    /* Same trap as #eventsTableCard: this class is applied to .gm-table-wrap,
       so `overflow: hidden` would turn the participants table's scroller off
       and hide its last columns between 769px and ~1180px. */
    overflow-x: auto;
    overflow-y: hidden;
}
@media (max-width: 768px) {
    .gm-table-panel { border: 0; border-radius: 0; box-shadow: none; background: transparent; }
}
/* ---------- EVENT FORM ---------- */
/* A quiet inset surface for sub-options inside a form. Replaces the dashed
   #cbd5e0 boxes, which read as "unfinished" rather than "secondary". */
.gm-inset-box {
    padding: .9rem 1rem;
    background: var(--gma-surface-2);
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-md);
    box-sizing: border-box;
}

/* Sections are separated by space and a hairline, not a dashed rule */
.gm-form-section {
    margin-top: 2rem;
    padding-top: 1.75rem;
    border-top: 1px solid var(--gma-hairline);
}

#newEventForm .gm-admin-label { margin-bottom: .4rem; }
#newEventForm h4,
#newEventForm h5,
#newEventForm h6 { letter-spacing: -.015em; color: var(--gma-ink); }
#formTitle { font-size: 1.25rem; font-weight: 600; margin-bottom: 1.5rem; }
/* ---------- FORM TYPOGRAPHY & ICONS ---------- */
/* Icons used to be coloured per-section with text-primary / text-success,
   which is what produced the rainbow. One accent, one muted, nothing else. */
.gm-ico-accent { color: var(--gma-accent-ink); }
.gm-ico-muted  { color: var(--gma-ink-3); }

.gm-section-title {
    font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em;
    color: var(--gma-ink); display: flex; align-items: center;
}
.gm-section-note { font-size: .875rem; color: var(--gma-ink-2); margin-bottom: 1rem; }
.gm-inline-note  { font-size: .875rem; color: var(--gma-ink-2); font-weight: 500; }
.gm-link {
    color: var(--gma-accent-ink); font-weight: 600; text-decoration: none;
    word-break: break-all;
}
.gm-link:hover { color: var(--gma-accent-ink); text-decoration: underline; }

.gm-inset-clickable { cursor: pointer; transition: background-color .2s var(--gma-ease), border-color .2s var(--gma-ease); }
.gm-inset-clickable:hover { background: var(--gma-surface); border-color: var(--gma-hairline-2); }
/* ============================================================
   JS RENDERER SURFACES
   The admin's tables, builders, kiosk and report modal are built
   in JS template literals. They used to carry their own inline
   colours; these rules are where that styling now lives, so the
   whole dashboard changes when a token changes.
   ============================================================ */

/* --- sort affordance in table headers --- */
.gm-sort-ico {
    margin-left: .3rem;
    font-size: .68rem;
    opacity: .35;
    transition: opacity var(--gma-ease);
}
.gm-sort-ico.is-on { opacity: 1; color: var(--gma-accent-ink); }
.sortable:hover .gm-sort-ico { opacity: .7; }

/* --- tier badges: one tonal ramp instead of a seven-hue rainbow --- */
.gm-badge-tier { border: 1px solid transparent; }
.gm-tier-0 { background: var(--gma-accent-wash);  color: var(--gma-accent-ink); border-color: var(--gma-accent-ring); }
.gm-tier-1 { background: rgba(0,99,201,.08);      color: var(--gma-blue);       border-color: rgba(0,99,201,.16); }
.gm-tier-2 { background: rgba(178,80,0,.08);      color: var(--gma-warn);       border-color: rgba(178,80,0,.16); }
.gm-tier-3 { background: var(--gma-surface-2);    color: var(--gma-ink-2);      border-color: var(--gma-hairline); }

/* --- table cells --- */
.gm-dt-pick { width: 40px; text-align: center; }
.gm-dt-pick input[type="checkbox"] { cursor: pointer; margin: 0; }
.gm-dt-mail {
    text-decoration: none;
    color: var(--gma-ink-3);
    font-size: .82rem;
}
.gm-dt-mail:hover { color: var(--gma-accent-ink); text-decoration: underline; }

.gm-dt-empty,
.gm-dt-error {
    text-align: center;
    padding: 2.75rem 1rem !important;
    font-size: .85rem;
    font-weight: 500;
}
.gm-dt-empty { color: var(--gma-ink-3); }
.gm-dt-error { color: var(--gma-danger); font-weight: 600; }
.gm-dt-empty > i,
.gm-dt-error > i { display: block; font-size: 1.5rem; margin-bottom: .5rem; opacity: .5; }

/* --- drag-and-drop builder rows (ticket tiers, custom fields) --- */
.gm-builder-row {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
    align-items: center;
    padding: .6rem;
    margin-bottom: .5rem;
    background: var(--gma-surface);
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-md);
    cursor: grab;
    transition: border-color var(--gma-ease), box-shadow var(--gma-ease);
}
.gm-builder-row:hover { border-color: var(--gma-accent-ring); box-shadow: var(--gma-shadow-sm); }
.gm-builder-row:active { cursor: grabbing; }

.gm-grip {
    display: flex;
    align-items: center;
    padding: 0 .15rem;
    color: var(--gma-hairline-2);
    cursor: grab;
    flex: 0 0 auto;
    font-size: 1.1rem;
}
.gm-builder-row:hover .gm-grip { color: var(--gma-ink-3); }

.gm-flex-1 { flex: 1 1 0; min-width: 90px; }
.gm-flex-2 { flex: 2 1 0; min-width: 160px; }

.gm-euro-group {
    display: flex;
    align-items: stretch;
    min-width: 0;
}
.gm-euro-sign {
    display: flex;
    align-items: center;
    padding: 0 .6rem;
    background: var(--gma-surface-2);
    border: 1px solid var(--gma-field-border);
    border-right: none;
    border-radius: var(--gma-r-sm) 0 0 var(--gma-r-sm);
    font-weight: 600;
    font-size: .85rem;
    color: var(--gma-accent-ink);
}
/* --- computed total capacity ---
   Total Max Plekken is editable on its own, but becomes a mirror of the summed
   tier capacities once tiers exist. The tint reads as "derived"; the ink stays
   the primary text colour so it keeps full contrast against that tint.
   This replaces an inline grey that Bootstrap's .bg-white -- a background-color
   with !important -- had been silently overriding. */
.gm-input-strong { font-weight: 700; }
/* The tint carries the "derived from the tiers" meaning; the edge is not the
   place to carry it too. --gma-accent-ring is rgba(0,183,131,.28) = 1.30:1,
   so the locked capacity field had no visible boundary at all. Neutral edge,
   green fill: the field is still obviously locked, and it is still a field. */
.gm-input-locked {
    background: var(--gma-accent-wash);
    color: var(--gma-ink);
    border-color: var(--gma-field-border);
    cursor: not-allowed;
}

/* --- transient "Gekopieerd" confirmation ---
   Compounded with .gm-btn so it outranks the button variants by specificity
   rather than !important. Previously three inline styles carrying a literal
   #00b783, which is the brand green duplicated out of reach of the token. */
.gm-btn.gm-copied {
    background: var(--gma-accent);
    border-color: var(--gma-accent);
    color: #fff;
}

/* --- builder-row field (ticket tiers + custom fields) ---
   These inputs carry only .gm-cf-input, and the sole rule for that class in
   this stylesheet was the .gm-euro-group one below -- which only rounds a
   corner. Outside a euro group there was nothing at all, so the tier name,
   capacity and option fields fell back to default browser chrome while the
   row around them was fully designed. Sized to 34px to line up with
   .gm-euro-sign and .gm-icon-btn, which share these rows. */
.gm-cf-input {
    width: 100%;
    min-width: 0;
    box-sizing: border-box;
    height: 34px;
    font-family: var(--gma-font);
    font-size: .8125rem;
    font-weight: 500;
    color: var(--gma-ink);
    background: var(--gma-surface);
    border: 1px solid var(--gma-field-border);
    border-radius: var(--gma-r-sm);
    padding: 0 .6rem;
    transition: border-color .18s var(--gma-ease), box-shadow .18s var(--gma-ease),
                background-color .18s var(--gma-ease);
}
.gm-cf-input::placeholder { color: var(--gma-ink-3); }
.gm-cf-input:hover { border-color: var(--gma-field-border-hover); }
.gm-cf-input:focus {
    outline: none;
    border-color: var(--gma-accent);
    box-shadow: 0 0 0 3px var(--gma-accent-ring);
}
.gm-cf-input:disabled { background: var(--gma-surface-2); color: var(--gma-ink-3); cursor: not-allowed; }
/* The custom-field builder renders a <select> on this same class; without
   these it keeps native platform chrome while its row siblings do not. */
select.gm-cf-input {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 1.9rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' fill='none' stroke='%236e6e73' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .55rem center;
    cursor: pointer;
}
/* Spinners crowd an already dense row, and the capacity/price fields are
   driven by onchange handlers rather than by stepping. */
.gm-cf-input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.gm-cf-input[type="number"]::-webkit-outer-spin-button,
.gm-cf-input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.gm-euro-group .gm-cf-input { border-radius: 0 var(--gma-r-sm) var(--gma-r-sm) 0; min-width: 0; }

/* --- small icon-only button --- */
.gm-icon-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-sm);
    background: var(--gma-surface);
    color: var(--gma-ink-3);
    cursor: pointer;
    transition: background var(--gma-ease), color var(--gma-ease), border-color var(--gma-ease);
}
.gm-icon-btn:hover { background: var(--gma-surface-2); color: var(--gma-ink); }
.gm-icon-btn-danger:hover {
    background: rgba(215,0,21,.08);
    border-color: rgba(215,0,21,.2);
    color: var(--gma-danger);
}

/* --- compact checkbox + label pair --- */
.gm-check-tight {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    flex: 0 0 auto;
}
.gm-check-tight input[type="checkbox"] { margin: 0; cursor: pointer; }
.gm-check-tight .gm-check-label {
    margin: 0;
    font-size: .78rem;
    color: var(--gma-ink-3);
    cursor: pointer;
}

/* --- callout inside confirm dialogs --- */
.gm-callout {
    display: flex;
    gap: .5rem;
    align-items: flex-start;
    margin-top: .7rem;
    padding: .75rem .85rem;
    border-radius: var(--gma-r-md);
    font-size: .83rem;
    line-height: 1.5;
    text-align: left;
    background: var(--gma-surface-2);
    color: var(--gma-ink-2);
}
.gm-callout-warn {
    background: rgba(178,80,0,.07);
    color: var(--gma-warn);
}

/* --- bulk action preview list --- */
.gm-bulk-preview { max-height: 150px; overflow-y: auto; text-align: left; }
.gm-bulk-preview ul {
    margin: 0;
    padding-left: 1.2rem;
    color: var(--gma-ink-2);
    font-size: .85rem;
    line-height: 1.7;
}

/* --- custom-field report modal --- */
.gm-report-title {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    margin-bottom: .9rem;
    font-size: .92rem;
    font-weight: 600;
    color: var(--gma-ink);
}
.gm-report-item { margin-bottom: .9rem; }
.gm-report-legend {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: .75rem;
    margin-bottom: .35rem;
    font-size: .82rem;
}
.gm-report-key { color: var(--gma-ink-2); font-weight: 500; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gm-report-val {
    flex: 0 0 auto;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--gma-ink);
    background: var(--gma-surface-2);
    padding: .1rem .45rem;
    border-radius: var(--gma-r-sm);
}
.gm-report-pct { color: var(--gma-ink-3); font-weight: 400; }

/* --- share / tracking links --- */
.gm-track-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .75rem .9rem;
    background: var(--gma-surface);
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-md);
}
.gm-track-row + .gm-track-row { margin-top: .5rem; }
.gm-track-id { display: flex; align-items: center; gap: .75rem; min-width: 0; }
.gm-track-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: var(--gma-r-md);
    font-size: 1.15rem;
    flex: 0 0 auto;
}
/* Network marks keep their own identity -- that is the one place a
   non-brand colour is the correct answer. */
.gm-track-fb { background: rgba(24,119,242,.10); color: #1877f2; }
.gm-track-li { background: rgba(10,102,194,.10); color: #0a66c2; }
.gm-track-wa { background: var(--gma-accent-wash); color: var(--gma-accent-ink); }
.gm-track-name {
    font-weight: 600;
    font-size: .88rem;
    color: var(--gma-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ============================================================
   KIOSK / SCANNER
   This runs on a dark surface on a phone at a venue entrance, so
   the verdict has to be readable at arm's length and in one glance.
   ============================================================ */
.gm-scanbox {
    border: 2px solid #334155;
    border-radius: var(--gma-r-lg);
    padding: 1rem;
    transition: border-color var(--gma-ease);
}
.gm-scanbox.is-ok   { border-color: var(--gma-accent); }
.gm-scanbox.is-warn { border-color: #f59e0b; }
.gm-scanbox.is-bad  { border-color: #ef4444; }

.gm-scan-verdict {
    font-weight: 700;
    font-size: .78rem;
    letter-spacing: .06em;
    text-transform: uppercase;
    display: flex;
    align-items: center;
    gap: .4rem;
}
.gm-scanbox.is-ok   .gm-scan-verdict { color: var(--gma-accent); }
.gm-scanbox.is-warn .gm-scan-verdict { color: #f59e0b; }
.gm-scanbox.is-bad  .gm-scan-verdict { color: #ef4444; }

/* ---- the fold ----------------------------------------------------------
   The verdict line is a button, so the card can be folded down to it and the
   outcome still reads at a glance. Expanded it shows the verdict; folded it
   swaps to the name and headcount, which is the question the card gets asked
   between scans -- "who was that?" -- and keeps the row to one line so the
   viewfinder above it is clear. */
.gm-scan-peek {
    display: flex;
    align-items: center;
    gap: .55rem;
    width: 100%;
    /* No padding of its own: it sits inside the card's. The rest of a folded
       card is made tappable in the click handler instead, which keeps the two
       from fighting over the same rim of space. */
    padding: 0;
    min-height: 44px;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.gm-scan-peek:focus-visible {
    outline: 2px solid var(--gma-accent);
    outline-offset: -2px;
    border-radius: var(--gma-r-md);
}

.gm-scan-peek-ico { flex: 0 0 auto; font-size: 1.05rem; }
.gm-scanbox.is-ok   .gm-scan-peek-ico, .gm-scanbox.is-ok   .gm-scan-peek-verdict { color: var(--gma-accent); }
.gm-scanbox.is-warn .gm-scan-peek-ico, .gm-scanbox.is-warn .gm-scan-peek-verdict { color: #f59e0b; }
.gm-scanbox.is-bad  .gm-scan-peek-ico, .gm-scanbox.is-bad  .gm-scan-peek-verdict { color: #ef4444; }

.gm-scan-peek-text { flex: 1 1 auto; min-width: 0; }
.gm-scan-peek-verdict {
    display: block;
    font-weight: 700;
    font-size: .78rem;
    letter-spacing: .06em;
    text-transform: uppercase;
}
/* One line, ellipsised: a long name must not wrap the folded row into two and
   start eating the camera again. */
.gm-scan-peek-who {
    display: none;
    font-weight: 600;
    font-size: .95rem;
    color: #f8fafc;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.gm-scanbox.is-collapsed .gm-scan-peek-verdict { display: none; }
.gm-scanbox.is-collapsed .gm-scan-peek-who { display: block; }

.gm-scan-peek-chev {
    flex: 0 0 auto;
    font-size: .9rem;
    color: #94a3b8;
    transition: transform .22s var(--gma-ease);
}
.gm-scanbox.is-collapsed .gm-scan-peek-chev { transform: rotate(180deg); }

/* 1fr -> 0fr animates the body's real height without anyone having to measure
   it in JavaScript, and degrades to an instant fold where it is unsupported. */
.gm-scan-fold {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows .22s var(--gma-ease);
}
.gm-scanbox.is-collapsed .gm-scan-fold { grid-template-rows: 0fr; }
.gm-scan-fold > .gm-scan-body { min-height: 0; overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
    .gm-scan-fold, .gm-scan-peek-chev { transition: none; }
}

.gm-scan-details {
    margin-top: .65rem;
    padding-top: .65rem;
    border-top: 1px solid #334155;
}
.gm-scan-name {
    font-size: 1.2rem;
    font-weight: 700;
    color: #f8fafc;
    margin-bottom: .45rem;
    line-height: 1.3;
}
.gm-scan-standalone { margin-top: .65rem; margin-bottom: 0; font-size: 1.05rem; }

/* The sentence from the server, above the ticket. */
.gm-scan-msg {
    margin: .35rem 0 0;
    font-size: .9rem;
    line-height: 1.4;
    color: #cbd5e1;
}

/* Anything other than a plain Registered ticket -- cancelled, waitlisted --
   said next to the name, because that is the one thing the person on the door
   must not miss while reading the rest. */
.gm-scan-flag {
    display: inline-block;
    margin-left: .5rem;
    padding: .1rem .5rem;
    border-radius: 999px;
    background: rgba(239, 68, 68, .16);
    color: #fca5a5;
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    vertical-align: middle;
}

.gm-scan-meta {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    font-size: .88rem;
    color: #94a3b8;
}
/* flex-start, not center: these rows carry full event names and addresses now,
   so they wrap, and a centred icon drifts into the middle of a two-line value.
   The icon also must not be squeezed out by a long unbroken value. */
.gm-scan-meta > div { display: flex; align-items: flex-start; gap: .5rem; line-height: 1.4; }
.gm-scan-meta > div > i { flex: 0 0 auto; margin-top: .12em; }
.gm-scan-meta > div > span { min-width: 0; overflow-wrap: anywhere; }
.gm-scan-meta strong { color: #e2e8f0; }
.gm-scan-meta code {
    padding: .05rem .35rem;
    border-radius: 5px;
    background: rgba(148, 163, 184, .16);
    color: #e2e8f0;
    font-size: .85em;
    letter-spacing: .04em;
}

.gm-kiosk-empty { color: #94a3b8; padding: .65rem; font-size: .9rem; }
.gm-kiosk-hit {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    background: #0f172a;
    border: 1px solid #334155;
    padding: .75rem;
    border-radius: var(--gma-r-md);
    margin-bottom: .5rem;
}
.gm-kiosk-name { color: #fff; font-weight: 600; }
.gm-kiosk-sub {
    color: #94a3b8;
    font-size: .78rem;
    display: flex;
    align-items: center;
    gap: .35rem;
    margin-top: .15rem;
}
.gm-kiosk-flag {
    color: #f59e0b;
    font-weight: 600;
    font-size: .82rem;
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    white-space: nowrap;
}

/* ==========================================================================
   ROW ACTIONS Â· OVERFLOW MENU Â· STATUS TAGS Â· DASHBOARD KPI CARDS
   ========================================================================== */

/* ---------- Row actions ----------------------------------------------------
   One chrome for every action, because six differently-coloured pills in a
   table cell read as six warnings. The icon carries the colour instead -- it
   is the part you can find without reading, and it leaves the labels calm.

   The fill is opaque white rather than the grey surface token. The table's
   hover state painted rows with that same grey, so grey buttons dissolved
   into the row as the cursor crossed it, which is what made them look like
   they were materialising on hover.                                         */
.gm-act {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .4rem .7rem;
    border: 1px solid var(--gma-hairline-2);
    border-radius: var(--gma-r-sm);
    background: #fff;
    color: var(--gma-ink);
    font-family: inherit;
    font-size: .78rem;
    font-weight: 600;
    line-height: 1.25;
    white-space: nowrap;
    cursor: pointer;
    transition: background .18s var(--gma-ease), border-color .18s var(--gma-ease),
                box-shadow .18s var(--gma-ease), transform .12s var(--gma-ease);
}
.gm-act:hover { background: var(--gma-surface-2); border-color: rgba(0,0,0,.2); color: var(--gma-ink); }
.gm-act:active { transform: translateY(.5px); }
.gm-act:focus-visible {
    outline: none;
    border-color: var(--gma-accent);
    box-shadow: 0 0 0 3px var(--gma-accent-ring);
}
/* The action you take most often, marked without shouting. */
.gm-act-key { background: var(--gma-accent-wash); border-color: var(--gma-accent-ring); }
.gm-act-key:hover { background: rgba(0,183,131,.17); border-color: var(--gma-accent); }
.gm-act-more { padding: .4rem .52rem; }
.gm-act-more[aria-expanded="true"] { background: var(--gma-surface-2); border-color: rgba(0,0,0,.22); }

.gm-act-i { font-size: .95em; line-height: 1; }
.gm-i-green  { color: #006b4b; }
.gm-i-blue   { color: #0071e3; }
.gm-i-purple { color: #8944ab; }
.gm-i-amber  { color: #b25000; }
.gm-i-red    { color: var(--gma-danger); }

.gm-row-actions { gap: .4rem; }

/* The row tint was the same grey as the old buttons. It is now a whisper, and
   the buttons are opaque, so neither one depends on the other. */
.gm-table tbody tr:hover td { background: rgba(0,0,0,.016); }

/* ---------- Overflow menu --------------------------------------------------
   Fixed, not absolute: the events card clips its own overflow to keep its
   corners round, which would slice this in half on the last row.            */
.gm-menu { position: relative; display: inline-flex; }
.gm-menu-pop {
    position: fixed;
    z-index: 9998;
    display: flex;
    flex-direction: column;
    min-width: 182px;
    padding: 6px;
    background: rgba(255,255,255,.94);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
    border: 1px solid var(--gma-hairline-2);
    border-radius: var(--gma-r-md);
    box-shadow: var(--gma-shadow-lg);
    animation: gmMenuIn .16s var(--gma-ease);
}
.gm-menu-pop[hidden] { display: none; }
@keyframes gmMenuIn {
    from { opacity: 0; transform: translateY(-5px) scale(.97); }
    to   { opacity: 1; transform: none; }
}
.gm-menu-item {
    display: flex;
    align-items: center;
    gap: .55rem;
    width: 100%;
    padding: .5rem .6rem;
    border: 0;
    border-radius: var(--gma-r-sm);
    background: transparent;
    color: var(--gma-ink);
    font-family: inherit;
    font-size: .82rem;
    font-weight: 500;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
}
.gm-menu-item:hover { background: var(--gma-surface-2); }
.gm-menu-item:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--gma-accent-ring); }
.gm-menu-item-danger { color: var(--gma-danger); }
.gm-menu-item-danger:hover { background: rgba(215,0,21,.09); }
.gm-menu-sep { display: block; height: 1px; margin: 5px 4px; background: var(--gma-hairline); }

/* ---------- Status tags ----------------------------------------------------
   Every state now shares one anatomy: tinted field, matching hairline, and
   real space between glyph and label. "Gesloten" and "Gearchiveerd" had no
   rule at all -- they rendered as bare text beside an icon, which is why they
   looked unfinished next to the others.                                     */
.gm-status-badge {
    gap: .4rem;
    padding: .34rem .62rem;
    line-height: 1.3;
}
.gm-status-badge > i { font-size: .82em; line-height: 1; }
.gm-status-open     { background: rgba(0,183,131,.12);   color: #00835d;          border-color: rgba(0,183,131,.30); }
.gm-status-upcoming { background: rgba(118,118,128,.12); color: var(--gma-ink-2); border-color: rgba(0,0,0,.10); }
.gm-status-auto     { background: rgba(0,113,227,.10);   color: var(--gma-blue);  border-color: rgba(0,113,227,.24); }
.gm-status-closed   { background: rgba(118,118,128,.18); color: #4a4a4f;          border-color: rgba(0,0,0,.14); }
.gm-status-archived { background: rgba(178,80,0,.10);    color: var(--gma-warn);  border-color: rgba(178,80,0,.22); }

/* ---------- Page tabs ----------
   The segmented control sat flush against the card above it, so the two read
   as one welded object. */
.gm-tabs-page { margin: 22px 0 24px; }
@media (max-width: 680px) { .gm-tabs-page { margin: 16px 0 18px; } }

/* ---------- Dashboard KPI cards --------------------------------------------
   The summary rail was three cells sharing hairlines: correct, but it read as
   a fragment of a table sitting on top of a table. These are three objects --
   each owns its radius, its shadow and a tinted glyph tile, and the
   attendance figure finally gets a meter so the number has somewhere to sit. */
.gm-kpi-cards {
    gap: 14px;
    background: transparent;
    border: 0;
    border-radius: 0;
    overflow: visible;
}
.gm-kpi-cards .gm-kpi {
    position: relative;
    gap: 7px;
    padding: 18px 18px 20px;
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-lg);
    background: #fff;
    box-shadow: var(--gma-shadow-sm);
    overflow: hidden;
    transition: box-shadow .22s var(--gma-ease), transform .22s var(--gma-ease);
}
.gm-kpi-cards .gm-kpi:hover { box-shadow: var(--gma-shadow-md); transform: translateY(-2px); }
.gm-kpi-cards .gm-kpi-hero {
    background:
        radial-gradient(120% 140% at 100% 0%, rgba(0,183,131,.16) 0%, rgba(0,183,131,0) 58%),
        linear-gradient(180deg, rgba(0,183,131,.07) 0%, rgba(0,183,131,.02) 100%);
    border-color: var(--gma-accent-ring);
}
.gm-kpi-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    margin-bottom: 3px;
    border-radius: 10px;
    font-size: 1rem;
    line-height: 1;
}
.gm-kpi-tile-green { background: rgba(0,183,131,.14);  color: #00835d; }
.gm-kpi-tile-blue  { background: rgba(0,113,227,.12);  color: #0071e3; }
.gm-kpi-tile-amber { background: rgba(255,159,10,.18); color: #b25000; }
.gm-kpi-cards .gm-kpi-foot { font-size: .76rem; }
.gm-kpi-meter {
    display: block;
    height: 5px;
    margin: 4px 0 2px;
    border-radius: 99px;
    background: rgba(118,118,128,.16);
    overflow: hidden;
}
.gm-kpi-meter > span {
    display: block;
    height: 100%;
    width: 0;
    border-radius: inherit;
    background: linear-gradient(90deg, var(--gma-accent) 0%, #4fd1ab 100%);
    transition: width .7s var(--gma-ease);
}
@media (max-width: 560px) { .gm-kpi-cards { gap: 10px; } }

@media (prefers-reduced-motion: reduce) {
    .gm-menu-pop { animation: none; }
    .gm-kpi-cards .gm-kpi:hover { transform: none; }
    .gm-kpi-meter > span { transition: none; }
}

/* =====================================================================
   EVENTS TABLE - SECOND PASS
   The ID column cost a full column width to show a random slug that
   told a human nothing. Removing it funds two things: a meta line that
   actually distinguishes events sharing a name, and action buttons with
   a real hit area that stay on one line.
   ===================================================================== */

/* ---------- Event cell: glyph + name + meta ---------- */
.gm-ev { display: flex; align-items: flex-start; gap: .7rem; min-width: 0; }

.gm-ev-glyph {
    flex: none;
    width: 34px;
    height: 34px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 10px;
    font-size: .95rem;
    margin-top: 1px;
}
/* Same ink as the open status tag. Two different greens sat on one row --
   the tile used the on-white accent while the tag next to it had already been
   darkened for its tint, which reads as a mistake rather than a choice. */
.gm-ev-glyph-walk   { background: rgba(0,183,131,.12);  color: #006b4b; }
.gm-ev-glyph-custom { background: rgba(137,68,171,.12); color: #8944ab; }

.gm-ev-body { min-width: 0; display: flex; flex-direction: column; gap: .24rem; }
.gm-ev-head { display: flex; align-items: center; min-width: 0; }

.gm-ev-name { font-weight: 600; color: var(--gma-ink); letter-spacing: -.005em; margin-bottom: 0; }

/* The badges used to trail the name on the same line and wrap to a second one
   whenever an event had more than one, which left the name looking ragged and
   the wrapped badge looking orphaned. Their own row always breaks in the same
   place. :empty keeps an event with no badges from paying for the gap. */
.gm-ev-tags { display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; }
.gm-ev-tags:empty { display: none; }

.gm-ev-meta { display: flex; align-items: center; flex-wrap: wrap; gap: .1rem .8rem; }
.gm-ev-m {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .78rem;
    font-weight: 500;
    color: var(--gma-ink-2);
}
.gm-ev-m > i { font-size: .9em; opacity: .75; }

/* ---------- Row actions: a 2x2 block, not a five-wide strip ----------
   Five controls on one line made the Acties column as wide as the event name
   beside it. Two rows of two, with the overflow button as a full-height rail
   on the right, roughly halves the column and every target stays 34px.
   Columns are auto rather than 1fr so each one sizes to its own widest label
   instead of padding the shorter pair out to match. */
.gm-row-actions {
    display: grid;
    grid-template-columns: auto auto auto;
    gap: .4rem;
    align-items: stretch;
    width: max-content;
    margin-left: auto;
}
.gm-row-actions .gm-act { width: 100%; }
/* The rail spans both rows, so the overflow button cannot be pushed onto a
   line of its own -- which is the failure the old nowrap row defended against. */
.gm-row-actions .gm-menu { grid-column: 3; grid-row: 1 / span 2; display: flex; }
.gm-row-actions .gm-act-more { width: 34px; height: 100%; }

.gm-act {
    min-height: 34px;
    padding: 0 .72rem;
    font-size: .8125rem;
    white-space: nowrap;
}
.gm-act-t { display: inline; }

/* 'Beheer' was the only tinted button. A tint reads as "this one is different"
   rather than "this one is first", and its green competed with the status tag
   two columns away. The chrome is uniform now and the icon colour does the
   separating, which is what the icons were coloured for. */
.gm-act-key { background: #fff; border-color: var(--gma-hairline-2); }
.gm-act-key:hover { background: var(--gma-surface-2); border-color: rgba(0,0,0,.2); }

/* Halving the column bought enough room that labels only need to go at
   genuinely narrow widths. The icon colour and the aria-label carry the
   meaning once the text is gone. */
@media (max-width: 1180px) {
    .gm-row-actions .gm-act-t { display: none; }
    .gm-row-actions .gm-act { width: 34px; padding: 0; justify-content: center; }
}

/* Below the table breakpoint each row becomes a card with the full width to
   spend, so the labels come back and the block stretches edge to edge. */
@media (max-width: 768px) {
    .gm-row-actions { width: 100%; margin-left: 0; grid-template-columns: 1fr 1fr auto; }
    .gm-row-actions .gm-act-t { display: inline; }
    .gm-row-actions .gm-act { width: 100%; padding: 0 .72rem; justify-content: center; }
    .gm-row-actions .gm-act-more { width: 44px; }
    .gm-ev-glyph { width: 30px; height: 30px; border-radius: 9px; }
}

/* ---------- Status: one hue per state ----------
   'Binnenkort' was grey, the same family as 'Gesloten', so a forward
   looking state and a stopped one read as the same kind of thing. The
   scale now follows the traffic light people already know:
   green go, amber not yet, red stopped, grey filed away, blue automatic. */
/* These inks are a step darker than the matching body-text tokens on purpose.
   A tag sits on its own tint, not on white, so the surface it has to beat is
   lighter than the page -- the green tag measured 4.23:1 against its own chip
   while passing comfortably against white. Each value below clears AA with
   headroom so a later tweak cannot quietly drop it under the line. */
.gm-status-open     { background: rgba(0,183,131,.12);   color: #006b4b; border-color: rgba(0,183,131,.30); }
.gm-status-upcoming { background: rgba(178,80,0,.10);    color: #8f4100; border-color: rgba(178,80,0,.24); }
.gm-status-auto     { background: rgba(0,113,227,.10);   color: #0057b0; border-color: rgba(0,113,227,.24); }
.gm-status-closed   { background: rgba(215,0,21,.09);    color: #b3000f; border-color: rgba(215,0,21,.22); }
.gm-status-archived { background: rgba(118,118,128,.16); color: #4a4a4f; border-color: rgba(0,0,0,.14); }

/* ==========================================================================
   Modal sheets
   Every modal used to carry a 6px top bar in a different colour -- blue,
   purple, green, red -- which was the loudest element on screen and said
   nothing the title and buttons were not already saying. One shell now, with
   a single danger tone for the destructive confirm.
   ========================================================================== */

.gm-modal-sheet {
    border: none;
    border-radius: 20px;
    background: var(--gma-surface);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .18), 0 2px 8px rgba(0, 0, 0, .06);
    overflow: hidden;
}

.gm-modal-body { padding: 28px 32px 24px; }

.gm-modal-title {
    display: flex;
    align-items: center;
    gap: .6rem;
    margin: 0 0 .4rem;
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -0.021em;
    color: var(--gma-ink);
}
.gm-modal-title-icon { color: var(--gma-accent-ink); font-size: 1.15rem; }
.gm-modal-danger .gm-modal-title-icon { color: var(--gma-danger); }

.gm-modal-sub {
    margin: 0 0 1.4rem;
    font-size: .9375rem;
    line-height: 1.5;
    color: var(--gma-ink-2);
}

.gm-modal-foot {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: .6rem;
    margin-top: 1.5rem;
}
.gm-modal-foot-ruled {
    padding-top: 1.25rem;
    border-top: 1px solid var(--gma-hairline);
}

.gm-modal-infobox {
    padding: 14px 16px;
    margin-bottom: 1.5rem;
    text-align: left;
    background: var(--gma-surface-2);
    border: 1px solid var(--gma-hairline);
    border-radius: var(--gma-r-md);
    font-size: .875rem;
    color: var(--gma-ink-2);
}

/* The destructive confirm is the one place a colour carries meaning, so it
   keeps a tone -- on the heading, not as a bar across the top. */
.gm-modal-danger {
    box-shadow: 0 24px 60px rgba(0, 0, 0, .18), 0 0 0 1px var(--gma-danger-ring);
}
.gm-modal-danger .gm-modal-title { color: var(--gma-danger); }

.gm-input-confirm {
    text-align: center;
    text-transform: uppercase;
    font-weight: 700;
    letter-spacing: .08em;
}

/* Bootstrap's backdrop is a flat 50% black. */
.modal-backdrop.show {
    background: rgba(0, 0, 0, .32);
    -webkit-backdrop-filter: saturate(140%) blur(6px);
    backdrop-filter: saturate(140%) blur(6px);
    opacity: 1;
}

/* Stack modal footers on narrow screens so the buttons stay thumb-sized. */
@media (max-width: 576px) {
    .gm-modal-body { padding: 22px 20px 20px; }
    .gm-modal-foot { flex-direction: column-reverse; align-items: stretch; }
    .gm-modal-foot .gm-btn { width: 100%; justify-content: center; }
}

/* ==========================================================================
   Rich-text editor
   Quill ships its own chrome and was previously restyled in three separate
   places in this file. This is the only definition.
   ========================================================================== */

/* No height here on purpose. Quill's own sheet sets .ql-container{height:100%}
   and these editors sit in a Bootstrap .row, whose columns are stretched flex
   items with a definite height. The 100% therefore resolved against the whole
   column -- label and toolbar included -- so the editor box ended up roughly
   70px taller than its column and spilled over the section heading underneath
   it ("Betalingen & Donaties" was half-covered). The height is governed by
   .ql-editor's min/max below, which applies to every editor rather than only
   the ones that remembered to carry this class. */
.gm-editor-host {
    width: 100%;
    font-size: .9375rem;
}

.ql-toolbar.ql-snow {
    border: 1px solid var(--gma-field-border) !important;
    border-bottom: none !important;
    border-radius: var(--gma-r-md) var(--gma-r-md) 0 0;
    background: var(--gma-surface-2);
    padding: 8px 10px;
}
.ql-container.ql-snow {
    border: 1px solid var(--gma-field-border) !important;
    border-radius: 0 0 var(--gma-r-md) var(--gma-r-md);
    background: var(--gma-surface);
    font-family: var(--gma-font);
    font-size: .9375rem;
    /* Beats Quill's .ql-container{height:100%} on specificity, so it holds
       regardless of which stylesheet the browser loaded last. */
    height: auto;
}
/* Grows with the text, then scrolls, so a long description can never push the
   form apart or reach over the section below it. */
.ql-editor { min-height: 140px; max-height: 320px; overflow-y: auto; color: var(--gma-ink); }
.ql-editor.ql-blank::before { color: var(--gma-ink-3); font-style: normal; }

.ql-snow .ql-stroke { stroke: var(--gma-ink-2); }
.ql-snow .ql-fill { fill: var(--gma-ink-2); }
.ql-snow button {
    border-radius: 7px;
    transition: background-color .15s var(--gma-ease);
}
.ql-snow button:hover { background: rgba(0, 0, 0, .05); }
.ql-snow button:hover .ql-stroke { stroke: var(--gma-ink); }
.ql-snow button:hover .ql-fill { fill: var(--gma-ink); }
.ql-snow button.ql-active { background: var(--gma-accent-wash); }
.ql-snow button.ql-active .ql-stroke { stroke: var(--gma-accent-ink); }
.ql-snow button.ql-active .ql-fill { fill: var(--gma-accent-ink); }

/* ==========================================================================
   Check-in button
   Previously this class set only `transition` and `border-width: 2px`, and the
   markup carried no base class, so the browser drew its default button chrome
   with a 2px border of its own choosing.
   ========================================================================== */

.checkin-btn.inactive {
    background: var(--gma-surface);
    border: 1px solid var(--gma-hairline-2);
    color: var(--gma-ink);
}
.checkin-btn.inactive:hover:not(:disabled) {
    background: var(--gma-surface-2);
    border-color: var(--gma-ink-3);
    color: var(--gma-ink);
}
.checkin-btn.active {
    background: var(--gma-accent-wash);
    border: 1px solid var(--gma-accent-ring);
    color: var(--gma-accent-ink);
}
.checkin-btn.active:hover:not(:disabled) {
    background: var(--gma-accent);
    border-color: var(--gma-accent);
    color: #fff;
}

/* ==========================================================================
   Toggle and checkbox
   Both used to inherit their whole appearance from Bootstrap's
   .form-check-input. The switch set a 2.1rem x 1.2rem box without ever making
   it a switch, so it rendered as a stretched square.
   ========================================================================== */

.gm-switch input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex-shrink: 0;
    width: 44px;
    height: 26px;
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    border: 1px solid var(--gma-field-border);
    border-radius: 999px;
    background: var(--gma-hairline-2);
    background-image: none;
    cursor: pointer;
    transition: background-color .24s var(--gma-ease);
}
.gm-switch input[type="checkbox"]::after {
    content: "";
    position: absolute;
    top: 1px;
    left: 1px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
    transition: transform .24s var(--gma-ease);
}
.gm-switch input[type="checkbox"]:checked { background: var(--gma-accent); border-color: var(--gma-accent); }
.gm-switch input[type="checkbox"]:checked::after { transform: translateX(18px); }
.gm-switch input[type="checkbox"]:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px var(--gma-accent-ring);
}

.gm-check input[type="checkbox"],
.gm-dt-pick input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    position: relative;
    flex-shrink: 0;
    width: 19px;
    height: 19px;
    margin: 0;
    border: 1.5px solid var(--gma-field-border);
    border-radius: 6px;
    background: var(--gma-surface);
    background-image: none;
    cursor: pointer;
    transition: background-color .15s var(--gma-ease), border-color .15s var(--gma-ease);
}
.gm-check input[type="checkbox"]:hover,
.gm-dt-pick input[type="checkbox"]:hover { border-color: var(--gma-ink-3); }
.gm-check input[type="checkbox"]:checked,
.gm-dt-pick input[type="checkbox"]:checked {
    background: var(--gma-accent);
    border-color: var(--gma-accent);
}
/* Drawn rather than an SVG background so it inherits no Bootstrap asset. */
.gm-check input[type="checkbox"]:checked::after,
.gm-dt-pick input[type="checkbox"]:checked::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 6px;
    width: 4px;
    height: 9px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}
.gm-check input[type="checkbox"]:focus-visible,
.gm-dt-pick input[type="checkbox"]:focus-visible {
    outline: none;
    box-shadow: 0 0 0 4px var(--gma-accent-ring);
}

/* ==========================================================================
   Scanner kiosk
   The element is reparented to <body> on open: position:fixed resolves against
   the nearest ancestor with a transform, filter, backdrop-filter or contain,
   and the active theme wraps page content in one, which pinned the kiosk
   inside the content column instead of covering the viewport.
   ========================================================================== */

body.gm-kiosk-open { overflow: hidden; }

.gm-kiosk-title {
    display: flex;
    align-items: center;
    gap: .5rem;
    font-weight: 700;
    font-size: 1.125rem;
    letter-spacing: -0.015em;
    color: var(--gma-ink);
}
.gm-kiosk-title i.bi { color: var(--gma-accent-ink); }

.gm-kiosk-body { justify-content: center; }

.gm-kiosk-search-label {
    display: block;
    margin-bottom: .55rem;
    font-size: .8125rem;
    font-weight: 600;
    color: var(--gma-ink-2);
}
.gm-kiosk-search-label span { font-weight: 400; color: var(--gma-ink-3); }

.gm-kiosk-lastscan {
    width: 100%;
    max-width: 500px;
    margin-top: 20px;
    padding: 15px 20px;
    border-radius: var(--gma-r-lg);
    background: var(--gma-surface);
    border: 1px solid var(--gma-hairline);
    box-shadow: var(--gma-shadow-sm);
}

/* The archive list is signalled with a neutral rail instead of a colour
   assigned from script. */
.gm-table-card-archive { border-top: 4px solid var(--gma-ink-3); }

/* Login card typography, previously written inline on the two echoed lines. */
.gm-login-title {
    margin: 0 0 .35rem;
    font-size: 2rem;
    font-weight: 700;
    letter-spacing: -0.022em;
    color: var(--gma-ink);
}
.gm-login-sub {
    margin: 0 0 1.75rem;
    font-size: 1.0625rem;
    color: var(--gma-ink-2);
}

/* The word the user has to retype before a destructive action. */
.gm-confirm-word { color: var(--gma-danger); letter-spacing: .04em; }

/* "Optioneel" and similar asides inside a field label. */
.gm-label-note { font-weight: 400; color: var(--gma-ink-3); }

/* Label beside a checkbox, replacing Bootstrap's .form-check-label. */
.gm-check-label {
    margin: 0;
    font-size: .875rem;
    color: var(--gma-ink-2);
    cursor: pointer;
}

/* Expanded custom-field row. The open state used to be written from script as
   a blue tint, on a plugin whose accent is green. */
.gm-cf-head-open {
    background: var(--gma-accent-wash);
    border-color: var(--gma-accent-ring);
}

/* Invalid state. Was injected from admin.js and keyed to Bootstrap's
   .form-control / .form-select; keyed to the element instead so renaming a
   control class cannot silently remove the error styling. background-image is
   left alone so .gm-select keeps its chevron while errored. */
#gm-plugin-root input.is-invalid,
#gm-plugin-root select.is-invalid,
#gm-plugin-root textarea.is-invalid {
    border-color: var(--gma-danger) !important;
    box-shadow: 0 0 0 4px var(--gma-danger-ring) !important;
}

#gm-plugin-root input[type="checkbox"].is-invalid {
    outline: 2px solid var(--gma-danger);
    outline-offset: 2px;
    box-shadow: none !important;
}

/* ============================================================
   EVENT FORM
   The create/edit screen. It was the last place still rendering raw Bootstrap
   controls, so its fields sat a few pixels and one border colour away from
   every other field in the admin.
   ============================================================ */

/* The form heading. fw-bold + text-dark pinned it to Bootstrap's ink rather
   than the admin palette, so it read darker than every other section title. */
.gm-form-title {
    font-size: 1.0625rem;
    font-weight: 700;
    letter-spacing: -0.014em;
    color: var(--gma-ink);
    margin: 0;
}

/* A time field holds five characters; stretching it to the grid column makes
   the pair read as two separate questions instead of a range. */
.gm-input-auto { width: auto; min-width: 0; }

/* .gm-switch carries a top margin for stacked rows. Inside an inset box the
   box owns the spacing, so the margin would push the row off centre. */
.gm-switch-flush { margin: 0; }

/* A switch whose label is the main statement of its row, not an aside. */
.gm-switch-strong { font-weight: 600; color: var(--gma-ink); }

/* ============================================================
   FIELD BOUNDARIES
   Controls used to be drawn with a transparent border and identified by their
   fill. That fill was --gma-surface-2, the same colour as .gm-inset-box, so a
   field sitting in one of those boxes was invisible -- 1.00:1 against its own
   background. These values are measured against BOTH surfaces rather than
   picked by eye: #8a8a8e is 3.44:1 on white and 3.16:1 on #f5f5f7, so the
   boundary clears WCAG 1.4.11 wherever a field is placed.

   No green appears in this block on purpose. The focus colour is left alone so
   the plugin keeps exactly one brand green.
   ============================================================ */
:root {
    --gma-field-border: #8a8a8e;
    --gma-field-border-hover: #6e6e73;
}

/* The admin side had no hover state at all: a control looked identical whether
   or not the pointer was on it.
   :enabled keeps this off disabled fields, and :not(:focus) stops it winning
   over the focus ring, which is declared earlier in the file. */
.gm-input:enabled:hover:not(:focus),
.gm-select:enabled:hover:not(:focus),
.gm-textarea:enabled:hover:not(:focus),
.gm-search input:enabled:hover:not(:focus),
.gm-logs-search input:enabled:hover:not(:focus) {
    border-color: var(--gma-field-border-hover);
}

/* A disabled field must read as inert, which is the one case where a flat grey
   fill is the right answer. The admin side never defined this. */
.gm-input:disabled, .gm-select:disabled, .gm-textarea:disabled {
    background: var(--gma-surface-2);
    border-color: var(--gma-hairline-2);
    color: var(--gma-ink-3);
    cursor: not-allowed;
}

/* =========================================================================
   STYLED DROPDOWNS (gm-select)
   -------------------------------------------------------------------------
   A native <select> drops down a list painted by the operating system. No
   stylesheet can reach it, which is why every dropdown in the plugin looked
   like a plain browser control sitting next to carefully styled fields.
   assets/gm-select.js draws the list itself and keeps the real <select> in
   the DOM as the source of truth; these rules dress what it draws.

   The popup is NOT a descendant of .gm-combo. It is appended to <body> so
   that cards, modals and the tables' overflow:auto cannot clip it, which
   means its rules must stay unscoped and its size modifier is mirrored onto
   it as .is-sm by the script. The custom properties it needs are copied onto
   the element at open time, so it still resolves the same tokens as the
   control it belongs to.

   Geometry below deliberately mirrors .gm-input / .gm-select above, so a row
   mixing a text field and a dropdown still lines up to the pixel.
   ========================================================================= */

/* Kept in the DOM, out of sight and out of the tab order. Deliberately not
   display:none: constraint validation cannot report against a field that is
   not rendered at all. */
.gm-combo-native {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.gm-combo {
    position: relative;
    display: block;
    width: 100%;
}
.gm-combo-auto { width: auto; min-width: 150px; display: inline-block; vertical-align: middle; }

.gm-combo-btn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    width: 100%;
    margin: 0;
    font-family: var(--gma-font);
    font-size: .875rem;
    font-weight: 500;
    line-height: 1.35;
    text-align: left;
    color: var(--gma-ink);
    background: var(--gma-surface);
    border: 1px solid var(--gma-field-border);
    border-radius: var(--gma-r-md);
    padding: .625rem .875rem;
    box-sizing: border-box;
    cursor: pointer;
    transition: background-color .18s var(--gma-ease), border-color .18s var(--gma-ease),
                box-shadow .18s var(--gma-ease);
}
.gm-combo-sm .gm-combo-btn { font-size: .8125rem; padding: .45rem .7rem; }
.gm-combo-strong .gm-combo-btn { font-weight: 600; }

.gm-combo-btn:hover { border-color: var(--gma-ink-2); }
.gm-combo-btn:focus-visible,
.gm-combo.is-open .gm-combo-btn {
    outline: none;
    border-color: var(--gma-accent);
    box-shadow: 0 0 0 4px var(--gma-accent-ring);
}
.gm-combo.is-invalid .gm-combo-btn {
    border-color: var(--gma-danger);
    box-shadow: 0 0 0 4px var(--gma-danger-ring);
}
.gm-combo.is-disabled .gm-combo-btn,
.gm-combo-btn:disabled {
    cursor: not-allowed;
    opacity: .55;
    background: var(--gma-surface-2);
}

.gm-combo-value {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The empty "Selecteer..." choice reads as a prompt, not as an answer. */
.gm-combo-value.is-placeholder { color: var(--gma-ink-3); font-weight: 400; }

/* Drawn rather than loaded: the same chevron as the native control, with no
   dependency on the icon font being available. */
.gm-combo-caret {
    flex: 0 0 auto;
    width: 8px;
    height: 8px;
    margin-left: .25rem;
    border-right: 1.5px solid var(--gma-ink-2);
    border-bottom: 1.5px solid var(--gma-ink-2);
    border-radius: 1px;
    transform: translateY(-2px) rotate(45deg);
    transition: transform .2s var(--gma-ease);
}
.gm-combo.is-open .gm-combo-caret { transform: translateY(1px) rotate(-135deg); }

/* --- the popup --- */
.gm-combo-pop {
    position: fixed;
    z-index: 100000;
    display: flex;
    flex-direction: column;
    max-height: min(320px, 60vh);
    max-width: calc(100vw - 16px);
    overflow: hidden;
    background: var(--gma-surface, #fff);
    border: 1px solid var(--gma-hairline-2, rgba(0,0,0,.12));
    border-radius: var(--gma-r-md, 12px);
    box-shadow: var(--gma-shadow-lg, 0 12px 32px rgba(0,0,0,.08), 0 2px 8px rgba(0,0,0,.04));
    font-family: var(--gma-font, inherit);
    padding: .3rem;
    animation: gmComboIn .14s var(--gma-ease, ease) both;
}
.gm-combo-pop[hidden] { display: none; }
.gm-combo-pop.is-above { transform-origin: bottom left; }

@keyframes gmComboIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
    .gm-combo-pop { animation: none; }
    .gm-combo-caret { transition: none; }
}

.gm-combo-search {
    padding: .25rem .25rem .4rem;
    border-bottom: 1px solid var(--gma-hairline, rgba(0,0,0,.08));
    margin-bottom: .3rem;
}
.gm-combo-search-input {
    width: 100%;
    box-sizing: border-box;
    font-family: inherit;
    font-size: .8125rem;
    color: var(--gma-ink, #1d1d1f);
    background: var(--gma-surface-2, #f5f5f7);
    border: 1px solid var(--gma-field-border, #8a8a8e);
    border-radius: var(--gma-r-sm, 8px);
    padding: .4rem .6rem;
    outline: none;
}
.gm-combo-search-input:focus {
    background: var(--gma-surface, #fff);
    border-color: var(--gma-accent, #00b783);
    box-shadow: 0 0 0 3px var(--gma-accent-ring, rgba(0,183,131,.28));
}

.gm-combo-list {
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    outline: none;
    -webkit-overflow-scrolling: touch;
}

.gm-combo-group {
    padding: .45rem .6rem .25rem;
    font-size: .6875rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--gma-ink-3, #6e6e73);
}

.gm-combo-opt {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .6rem;
    font-size: .875rem;
    font-weight: 500;
    line-height: 1.35;
    color: var(--gma-ink, #1d1d1f);
    border-radius: var(--gma-r-sm, 8px);
    cursor: pointer;
    user-select: none;
}
.gm-combo-pop.is-sm .gm-combo-opt { font-size: .8125rem; padding: .4rem .55rem; }

/* Keyboard and pointer share one highlight, so arrowing down and hovering
   never disagree about which row is about to be chosen. */
.gm-combo-opt.is-active { background: var(--gma-surface-2, #f5f5f7); }
.gm-combo-opt.is-selected { color: var(--gma-accent-ink, #00835d); font-weight: 600; }
.gm-combo-opt[aria-disabled="true"] { color: var(--gma-ink-3, #6e6e73); opacity: .5; cursor: not-allowed; }

/* Reserved whether or not it is drawn, so rows do not shift sideways as the
   selection moves. */
.gm-combo-tick {
    flex: 0 0 auto;
    width: 14px;
    height: 14px;
    position: relative;
}
.gm-combo-opt.is-selected .gm-combo-tick::after {
    content: "";
    position: absolute;
    left: 3px;
    top: 0;
    width: 5px;
    height: 10px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
}

.gm-combo-txt { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.gm-combo-empty {
    padding: .75rem .6rem;
    font-size: .8125rem;
    color: var(--gma-ink-3, #6e6e73);
    text-align: center;
}
.gm-combo-empty[hidden] { display: none; }

/* Touch targets on phones: the list is what a steward actually taps at the
   door, so rows get the full 44px rather than the desktop density. */
@media (max-width: 782px) {
    .gm-combo-opt { padding: .7rem .6rem; font-size: .9375rem; }
    .gm-combo-pop.is-sm .gm-combo-opt { padding: .7rem .6rem; font-size: .9375rem; }
    .gm-combo-pop { max-height: min(50vh, 360px); }
}

/* The custom-field builder packs its controls into tight grid rows, so the
   dropdown there matches .gm-cf-input's 34px shape rather than the roomier
   form field above. */
.gm-combo-cf .gm-combo-btn {
    height: 34px;
    padding: 0 .6rem;
    font-size: .8125rem;
    border-radius: var(--gma-r-sm);
}

/* ==========================================================================
   SCANNER KIOSK -- DOOR MODE
   THIS BLOCK MUST STAY ABOVE "TOUCH TARGET FLOOR" AND BELOW EVERY OTHER
   KIOSK RULE. The kiosk is declared three separate times earlier in this file
   (the original light-mode block, the liquid-glass pass, and the reparenting
   fix); at equal specificity the last declaration wins, so this is where the
   kiosk is actually decided.

   Why dark. The kiosk is a full-screen surface held at a venue door, often in
   a dim foyer or outdoors at night. The old light mode put a ~1100:1 white
   sheet around a small black camera box: it blinds the person holding it,
   and it wastes the screen on chrome instead of the one thing that matters.
   Door mode inverts that -- the camera IS the screen, everything else floats.

   Why this also fixes a real defect. The .gm-scanbox block further up says
   "this runs on a dark surface", but the kiosk was converted to light mode
   afterwards and that block was never revisited. Measured on the shipping
   CSS, .gm-scan-name was rgb(248,250,252) on rgb(245,245,247) -- a contrast
   ratio of 1.04:1. The scanned guest's name, the single most important string
   on the screen, was white-on-white and therefore invisible; the only reason
   it was not reported is that the 2s flash showed the name and then faded to
   a blank card. Going dark makes that block correct again instead of leaving
   two conflicting themes in one file.

   Why the verdict is split in two. A door needs both an instant glance
   ("green = let them in", readable across a queue) and a durable detail card
   (name, ticket type, quantity -- still there after the flash). The flash is
   the glance; #kioskLastScan is the record, pinned under the viewfinder at
   z-index 8 so the flash passes over it rather than replacing it.
   ========================================================================== */

.gm-scanner-kiosk {
    /* Scoped so the kiosk can go dark without touching the light dashboard
       that is still mounted behind it. */
    --k-bg:      #0b0d12;
    --k-surface: rgba(14, 17, 23, .94);
    --k-raise:   rgba(255, 255, 255, .07);
    --k-raise-2: rgba(255, 255, 255, .12);
    --k-line:    rgba(255, 255, 255, .14);
    --k-line-2:  rgba(255, 255, 255, .24);
    /* Field edges get their own, much stronger value. --k-line-2 is a
       decorative hairline; composited over the kiosk surface it only reaches
       about 2.2:1, which is the "I cannot see where the box is" problem this
       plugin already fixed once on the light side. At .45 the composite is
       rgb(123,125,129) on rgb(14,17,23) -- 4.4:1, clear of the 3:1 floor the
       field-border suite enforces. */
    --k-field-border: rgba(255, 255, 255, .45);
    --k-ink:     #f6f7f9;   /* 18.3:1 on --k-bg */
    --k-ink-2:   #aeb4c0;   /*  9.1:1 on --k-bg */
    --k-ok:      #34d399;   /* 10.1:1 */
    --k-warn:    #fbbf24;   /* 11.6:1 */
    --k-bad:     #fb7185;   /*  7.1:1 */

    background: var(--k-bg);
    color: var(--k-ink);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* --- header ------------------------------------------------------------- */
.gm-scanner-kiosk .gm-kiosk-header {
    flex: 0 0 auto;
    gap: .75rem;
    padding: max(10px, env(safe-area-inset-top)) 14px 10px;
    background: rgba(11, 13, 18, .72);
    -webkit-backdrop-filter: saturate(160%) blur(18px);
    backdrop-filter: saturate(160%) blur(18px);
    border-bottom: 1px solid var(--k-line);
    box-shadow: none;
}
.gm-scanner-kiosk .gm-kiosk-title { color: var(--k-ink); font-size: 1rem; min-width: 0; }
.gm-scanner-kiosk .gm-kiosk-title i.bi { color: var(--k-ok); }
.gm-scanner-kiosk .gm-kiosk-stats {
    color: var(--k-ink-2);
    font-size: .8125rem;
    font-weight: 600;
    gap: .5rem;
    margin-inline-start: auto;
}
.gm-scanner-kiosk .gm-kiosk-stats span {
    background: var(--k-raise-2);
    color: var(--k-ink);
    border: 1px solid var(--k-line);
    font-size: .9375rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    padding: 3px 11px;
}
.gm-scanner-kiosk .gm-kiosk-close {
    flex: 0 0 auto;
    /* The global touch floor only fires at <=1024px or on a coarse pointer.
       A door kiosk is finger-operated at every width -- including a
       wall-mounted 1280px tablet that reports a fine pointer when driven by a
       stylus -- so the 44px target is unconditional here. */
    width: 44px;
    height: 44px;
    min-width: 44px;
    min-height: 44px;
    background: var(--k-raise);
    color: var(--k-ink);
    border: 1px solid var(--k-line);
    font-size: 1.1rem;
}
.gm-scanner-kiosk .gm-kiosk-close:hover { background: var(--k-raise-2); color: #fff; }

/* A door team wants "how many left" without doing arithmetic. Width is set
   from updateKioskCount(); 0% is a legitimate value, so the track is always
   painted and only the fill moves. */
.gm-kiosk-progress {
    flex: 0 0 auto;
    height: 3px;
    background: var(--k-raise);
    overflow: hidden;
}
.gm-kiosk-progress > span {
    display: block;
    height: 100%;
    width: 0;
    background: linear-gradient(90deg, var(--k-ok), #22d3ee);
    transition: width .45s var(--gma-ease);
}

/* --- camera ------------------------------------------------------------- */
.gm-scanner-kiosk .gm-kiosk-body {
    flex: 1 1 auto;
    min-height: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    overflow: hidden;
}
.gm-scanner-kiosk .gm-kiosk-camera-wrap {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    max-width: none;
    margin: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: #000;
    position: relative;
    overflow: hidden;
}

/* html5-qrcode sizes its own nodes inline and ships a silver border and a
   camera-select UI. We drive the camera from .gm-kiosk-controls, so the
   library chrome is removed -- except its status/error text, which is the
   only place a permission failure is reported. */
.gm-scanner-kiosk #qr-reader {
    width: 100%; height: 100%;
    border: 0 !important;
    border-radius: 0;
    background: #000;
}
.gm-scanner-kiosk #qr-reader__scan_region {
    width: 100%; height: 100%;
    background: #000;
    display: flex; align-items: center; justify-content: center;
}
.gm-scanner-kiosk #qr-reader__scan_region img { display: none !important; }
.gm-scanner-kiosk #qr-reader video {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    display: block;
}
.gm-scanner-kiosk #qr-reader__dashboard_section_csr,
.gm-scanner-kiosk #qr-reader__dashboard_section_swaplink { display: none !important; }
.gm-scanner-kiosk #qr-reader__dashboard { padding: 0 !important; }
.gm-scanner-kiosk #qr-reader__header_message,
.gm-scanner-kiosk #qr-reader__dashboard_section_csr span {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    z-index: 9;
    margin: 0;
    padding: .6rem .9rem;
    border: 0 !important;
    background: rgba(11, 13, 18, .9);
    color: var(--k-ink) !important;
    font-size: .8125rem;
    text-align: center;
}

/* Viewfinder. Tracks the 70%-of-shortest-edge qrbox that initCameraStream()
   asks html5-qrcode for, so the brackets frame the region that is actually
   decoded rather than a decorative square. */
.gm-kiosk-reticle {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: min(70%, 70vh, 340px);
    aspect-ratio: 1;
    pointer-events: none;
    z-index: 6;
}
.gm-kiosk-corner {
    position: absolute;
    width: 38px; height: 38px;
    border: 3px solid var(--k-ok);
    filter: drop-shadow(0 2px 10px rgba(0, 0, 0, .55));
}
.gm-kiosk-corner.tl { top: 0; left: 0;  border-right: 0; border-bottom: 0; border-radius: 14px 0 0 0; }
.gm-kiosk-corner.tr { top: 0; right: 0; border-left: 0;  border-bottom: 0; border-radius: 0 14px 0 0; }
.gm-kiosk-corner.bl { bottom: 0; left: 0;  border-right: 0; border-top: 0; border-radius: 0 0 0 14px; }
.gm-kiosk-corner.br { bottom: 0; right: 0; border-left: 0;  border-top: 0; border-radius: 0 0 14px 0; }
.gm-kiosk-sweep {
    position: absolute;
    left: 6%; right: 6%;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, transparent, var(--k-ok), transparent);
    box-shadow: 0 0 14px 2px rgba(52, 211, 153, .55);
    animation: gmKioskSweep 2.6s var(--gma-ease) infinite;
}
@keyframes gmKioskSweep {
    0%, 100% { top: 8%;  opacity: 0; }
    12%      {            opacity: 1; }
    88%      {            opacity: 1; }
    50%      { top: 92%; opacity: 1; }
}
/* The reduced-motion block above neutralises the animation but leaves the
   line parked wherever 0% put it, which reads as a stray rule. Hide it. */
@media (prefers-reduced-motion: reduce) {
    .gm-kiosk-sweep { display: none; }
}

.gm-kiosk-hint {
    position: absolute;
    left: 50%;
    bottom: 18px;
    transform: translateX(-50%);
    z-index: 6;
    margin: 0;
    max-width: calc(100% - 24px);
    padding: .4rem .85rem;
    border-radius: 50px;
    background: rgba(11, 13, 18, .72);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    color: var(--k-ink-2);
    font-size: .8125rem;
    font-weight: 500;
    white-space: nowrap;
    text-align: center;
}

/* --- verdict: the glance ------------------------------------------------ */
.gm-scanner-kiosk .gm-flash-overlay {
    z-index: 10;
    gap: .25rem;
    /* Semi-transparent rather than solid: the verdict still reads as a wall of
       colour from across a queue, but the camera stays visible underneath so
       the operator can see they are still pointed at the right person. */
    -webkit-backdrop-filter: saturate(140%) blur(2px);
    backdrop-filter: saturate(140%) blur(2px);
    transition: opacity .14s var(--gma-ease);
}
.gm-scanner-kiosk .gm-flash-overlay.success { background: radial-gradient(130% 100% at 50% 40%, rgba(16, 185, 129, .95), rgba(4, 78, 56, .92)); }
.gm-scanner-kiosk .gm-flash-overlay.warning { background: radial-gradient(130% 100% at 50% 40%, rgba(245, 158, 11, .95), rgba(104, 64, 3, .92)); }
.gm-scanner-kiosk .gm-flash-overlay.error   { background: radial-gradient(130% 100% at 50% 40%, rgba(239, 68, 68, .95), rgba(105, 16, 16, .92)); }
.gm-scanner-kiosk .gm-flash-icon {
    font-size: clamp(3.75rem, 20vw, 7rem);
    margin-bottom: 0;
}
.gm-scanner-kiosk .gm-flash-title { font-size: clamp(1.75rem, 9vw, 3rem); }
.gm-scanner-kiosk .gm-flash-msg   { font-size: clamp(1rem, 4.5vw, 1.6rem); margin-top: .35rem; }

/* Ring the viewfinder in the verdict colour too, so the signal survives even
   if the wash is missed. Progressive enhancement: browsers without :has()
   simply keep the neutral frame. */
.gm-kiosk-camera-wrap:has(.gm-flash-overlay.success) { box-shadow: inset 0 0 0 5px var(--k-ok); }
.gm-kiosk-camera-wrap:has(.gm-flash-overlay.warning) { box-shadow: inset 0 0 0 5px var(--k-warn); }
.gm-kiosk-camera-wrap:has(.gm-flash-overlay.error)   { box-shadow: inset 0 0 0 5px var(--k-bad); }
.gm-kiosk-camera-wrap:has(.gm-flash-overlay.warning) .gm-kiosk-corner { border-color: var(--k-warn); }
.gm-kiosk-camera-wrap:has(.gm-flash-overlay.error)   .gm-kiosk-corner { border-color: var(--k-bad); }

/* --- verdict: the record ------------------------------------------------ */
/* Sits UNDER the flash (z-index 8 vs 10) so it is already in place when the
   wash fades, instead of appearing a beat later. */
.gm-scanner-kiosk .gm-kiosk-lastscan,
.gm-scanner-kiosk .gm-scanbox {
    position: absolute;
    left: 10px; right: 10px; bottom: 10px;
    z-index: 8;
    width: auto;
    max-width: none;
    margin: 0;
    padding: .85rem 1rem;
    border-radius: var(--gma-r-lg);
    background: var(--k-surface);
    -webkit-backdrop-filter: saturate(160%) blur(18px);
    backdrop-filter: saturate(160%) blur(18px);
    border: 1px solid var(--k-line);
    box-shadow: 0 14px 34px rgba(0, 0, 0, .5);
}
/* The card now carries the whole ticket, not a name and a headcount, so on a
   phone held in portrait it can be taller than the camera area it floats over.
   Capping it against the viewfinder's own height keeps the reticle usable and
   lets the operator scroll the rest, instead of the card growing off-screen
   and taking its last rows with it. */
.gm-scanner-kiosk .gm-kiosk-lastscan,
.gm-scanner-kiosk .gm-scanbox {
    max-height: min(58%, 420px);
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}
.gm-scanner-kiosk .gm-scanbox { border-width: 1px 1px 1px 4px; }
.gm-scanner-kiosk .gm-scan-msg { color: var(--k-ink-2); }
.gm-scanner-kiosk .gm-scan-peek-who { color: var(--k-ink); }
.gm-scanner-kiosk .gm-scan-peek-chev { color: var(--k-ink-2); }

/* Folded, the card is one row and nothing is scrollable inside it, so the
   scroll cap is lifted -- otherwise the fold animates towards a height the
   card is still reserving room for. */
.gm-scanner-kiosk .gm-scanbox.is-collapsed {
    max-height: none;
    overflow: hidden;
    cursor: pointer;
}
.gm-scanner-kiosk .gm-scanbox.is-ok   { border-left-color: var(--k-ok); }
.gm-scanner-kiosk .gm-scanbox.is-warn { border-left-color: var(--k-warn); }
.gm-scanner-kiosk .gm-scanbox.is-bad  { border-left-color: var(--k-bad); }
.gm-scanner-kiosk .gm-scanbox.is-ok   .gm-scan-verdict { color: var(--k-ok); }
.gm-scanner-kiosk .gm-scanbox.is-warn .gm-scan-verdict { color: var(--k-warn); }
.gm-scanner-kiosk .gm-scanbox.is-bad  .gm-scan-verdict { color: var(--k-bad); }
.gm-scanner-kiosk .gm-scan-details { border-top-color: var(--k-line); }
.gm-scanner-kiosk .gm-scan-name    { color: var(--k-ink); }
.gm-scanner-kiosk .gm-scan-meta    { color: var(--k-ink-2); }
.gm-scanner-kiosk .gm-scan-meta strong { color: var(--k-ink); }

/* --- controls ----------------------------------------------------------- */
.gm-scanner-kiosk .gm-kiosk-controls {
    flex: 0 0 auto;
    display: flex;
    gap: 10px;
    margin: 0;
    padding: 12px 14px max(12px, env(safe-area-inset-bottom));
    background: rgba(11, 13, 18, .92);
    border-top: 1px solid var(--k-line);
}
.gm-scanner-kiosk .gm-kiosk-btn {
    flex: 1 1 0;
    justify-content: center;
    min-height: 52px;
    padding: 10px 12px;
    border-radius: var(--gma-r-md);
    background: var(--k-raise);
    border: 1px solid var(--k-line);
    color: var(--k-ink);
    font-size: .875rem;
    font-weight: 600;
    box-shadow: none;
    /* Three buttons on a 360px phone: the label is the first thing to go, the
       44px target is not. */
    gap: .4rem;
}
.gm-scanner-kiosk .gm-kiosk-btn i.bi { font-size: 1.15rem; }
.gm-scanner-kiosk .gm-kiosk-btn:hover { background: var(--k-raise-2); border-color: var(--k-line-2); color: #fff; }
.gm-scanner-kiosk .gm-kiosk-btn[aria-expanded="true"] {
    background: var(--gma-accent);
    border-color: var(--gma-accent);
    color: #fff;
}
@media (max-width: 360px) {
    .gm-scanner-kiosk .gm-kiosk-btn > span { display: none; }
}

/* --- manual search sheet ------------------------------------------------ */
/* Was a permanently open card below the fold, which pushed the camera into a
   corner for a fallback that is used a handful of times a night. It is now a
   sheet over the camera, opened from the dock. */
.gm-kiosk-scrim {
    position: absolute;
    inset: 0;
    z-index: 20;
    background: rgba(0, 0, 0, .55);
    opacity: 0;
    visibility: hidden;
    transition: opacity .25s var(--gma-ease), visibility .25s var(--gma-ease);
}
.gm-scanner-kiosk.gm-kiosk-searching .gm-kiosk-scrim { opacity: 1; visibility: visible; }

.gm-scanner-kiosk .gm-kiosk-search {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    z-index: 21;
    width: auto;
    max-width: none;
    margin: 0;
    padding: 10px 14px max(14px, env(safe-area-inset-bottom));
    background: var(--k-surface);
    -webkit-backdrop-filter: saturate(160%) blur(20px);
    backdrop-filter: saturate(160%) blur(20px);
    border: 1px solid var(--k-line);
    border-bottom: 0;
    border-radius: var(--gma-r-lg) var(--gma-r-lg) 0 0;
    box-shadow: 0 -16px 40px rgba(0, 0, 0, .55);
    transform: translateY(101%);
    visibility: hidden;
    transition: transform .3s var(--gma-ease), visibility .3s var(--gma-ease);
}
.gm-scanner-kiosk.gm-kiosk-searching .gm-kiosk-search { transform: none; visibility: visible; }

.gm-kiosk-sheet-close {
    display: block;
    width: 100%;
    min-height: 32px;
    margin: 0 0 .35rem;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--k-ink-2);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}
.gm-kiosk-sheet-close:hover { color: var(--k-ink); }

.gm-scanner-kiosk .gm-kiosk-search-label { color: var(--k-ink-2); }
.gm-scanner-kiosk .gm-kiosk-search-label span { color: #8b93a1; }
.gm-scanner-kiosk .gm-kiosk-search input {
    min-height: 52px;
    background: rgba(255, 255, 255, .06);
    border: 1px solid var(--k-field-border);
    border-radius: var(--gma-r-md);
    color: var(--k-ink);
    font-size: 1rem;
}
.gm-scanner-kiosk .gm-kiosk-search input::placeholder { color: #7f8798; }
.gm-scanner-kiosk .gm-kiosk-search input:focus {
    background: rgba(255, 255, 255, .10);
    border-color: var(--k-ok);
    box-shadow: 0 0 0 4px rgba(52, 211, 153, .25);
}

#kioskSearchResults {
    margin-top: 10px;
    max-height: min(38vh, 260px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}
.gm-scanner-kiosk .gm-kiosk-hit {
    background: rgba(255, 255, 255, .06);
    border: 1px solid var(--k-line);
    border-radius: var(--gma-r-md);
    color: var(--k-ink);
    padding: .7rem .8rem;
}
.gm-scanner-kiosk .gm-kiosk-hit:last-child { margin-bottom: 0; }
.gm-scanner-kiosk .gm-kiosk-name  { color: var(--k-ink); }
.gm-scanner-kiosk .gm-kiosk-sub   { color: var(--k-ink-2); }
.gm-scanner-kiosk .gm-kiosk-flag  { color: var(--k-warn); }
.gm-scanner-kiosk .gm-kiosk-empty { color: var(--k-ink-2); text-align: center; }

/* --- roomier screens ---------------------------------------------------- */
/* A laptop or a wall-mounted tablet should not stretch a phone layout edge to
   edge: the camera gets a framed stage and the sheet becomes a centred panel. */
@media (min-width: 992px) {
    .gm-scanner-kiosk .gm-kiosk-body { padding: 20px; }
    .gm-scanner-kiosk .gm-kiosk-camera-wrap {
        width: min(100%, 760px);
        margin: 0 auto;
        border-radius: var(--gma-r-lg);
        box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
    }
    .gm-scanner-kiosk .gm-kiosk-controls {
        justify-content: center;
        background: transparent;
        border-top: 0;
        padding-top: 0;
    }
    .gm-scanner-kiosk .gm-kiosk-btn { flex: 0 0 auto; min-width: 150px; }
    .gm-scanner-kiosk .gm-kiosk-search {
        left: 50%;
        right: auto;
        bottom: 24px;
        width: min(560px, calc(100% - 48px));
        transform: translate(-50%, calc(100% + 24px));
        border-radius: var(--gma-r-lg);
        border-bottom: 1px solid var(--k-line);
    }
    .gm-scanner-kiosk.gm-kiosk-searching .gm-kiosk-search { transform: translate(-50%, 0); }
}

/* ============================ TOUCH TARGET FLOOR ===========================
   THIS BLOCK MUST STAY LAST IN THIS FILE.

   The touch sizing near the .gm-input/.gm-btn rules covers the form controls
   only. Measuring the whole dashboard at iPad widths found everything a tablet
   user actually reaches for still below Apple's 44px floor: the sixteen
   row-action buttons on every list (34px), the view tabs (40-43px), the
   segmented sub-tabs (34px), the logs search field and its refresh button
   (41px / 38px) and the pager arrows (32px). A 390px phone renders the same
   34px buttons, so this is not a tablet-only correction -- it is the rest of
   the touch surface, on every touch device.

   It has to be last because .gm-act, .gm-tab and .gm-pager button are all
   re-declared later in the file; at equal specificity the later rule wins and
   an earlier floor is simply ignored. Appending a new component below this
   block will silently reopen the same hole -- the tablet-sweep suite is what
   catches that.

   min-* rather than width/height: the used size is max(min-size, size), so an
   explicit 32px or 38px box is lifted without !important and without
   re-stating any geometry. The .gm-row-actions selectors are repeated at their
   own specificity because `.gm-row-actions .gm-act` (0,2,0) sets width: 34px
   below 1180px and would otherwise keep the icon squares narrow. */
@media (max-width: 1024px), (pointer: coarse) {
    .gm-act,
    .gm-tab,
    .gm-seg button,
    .gm-logs-refresh,
    .gm-logs-search input,
    .gm-pager button,
    .gm-logs-foot-right button,
    .gm-kiosk-btn,
    .gm-kiosk-close,
    .gm-kiosk-sheet-close,
    .gm-kiosk-hit button {
        min-height: 44px;
    }
    .gm-act-more,
    .gm-logs-refresh,
    .gm-pager button,
    .gm-logs-foot-right button,
    .gm-kiosk-close {
        min-width: 44px;
        justify-content: center;
    }
    .gm-row-actions .gm-act,
    .gm-row-actions .gm-act-more {
        min-width: 44px;
        min-height: 44px;
    }
}
/* ==========================================
   MOBILE BUILDER ROWS (Tiers & Custom Fields)
   ========================================== */
@media (max-width: 768px) {
    .gm-builder-row {
        display: grid !important;
        /* 3 strict columns: Grip | Inputs | Trash Can */
        grid-template-columns: auto 1fr auto !important;
        gap: 12px 10px !important;
        padding: 16px 12px !important;
    }
    
    /* 1. Grip & Trash span the first TWO rows and center vertically */
    .gm-builder-row > .gm-grip { 
        grid-column: 1 !important; 
        grid-row: 1 / span 2 !important; 
        align-self: center !important;
    }
    .gm-builder-row > .gm-icon-btn-danger { 
        grid-column: 3 !important; 
        grid-row: 1 / span 2 !important; 
        align-self: center !important;
        width: 44px !important;
        height: 44px !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
    }

    /* 2. All inputs, dropdowns, and checkboxes lock into the middle column */
    .gm-builder-row > :not(.gm-grip):not(.gm-icon-btn-danger) {
        grid-column: 2 !important;
        width: 100% !important;
        margin: 0 !important;
    }

    /* 3. Match input height to the 44px trash can for a clean, unified look */
    .gm-builder-row .gm-cf-input,
    .gm-builder-row .gm-combo-cf .gm-combo-btn {
        height: 44px !important;
        font-size: 1rem !important; /* Prevents auto-zoom on iOS */
    }
    
    /* 4. Tweak spacing for the checkbox at the bottom */
    .gm-builder-row .gm-check-tight {
        margin-top: 4px !important;
    }
}