/* ==========================================================================
   Pre-COP31 — application theme

   1. Tokens (light + dark)
   2. Base
   3. App shell
   4. Components
   5. Public check-in
   6. Auth screens
   7. Landing
   8. Third-party overrides
   9. Responsive / print / motion

   Theming: every colour is a custom property declared once for light and
   re-declared under [data-theme="dark"]. Nothing hard-codes a hex outside
   section 1, so dark mode needs no per-component work and cannot drift.

   White-label: --brand and --brand-2 are overridden inline per organization,
   so a tenant's colours flow through every accent without a second stylesheet.
   ========================================================================== */

/* ─────────────────────────── 1. Tokens — light ────────────────────────── */

:root,
[data-theme="light"] {
  --brand:        #0059b3;
  --brand-2:      #0070d0;
  --brand-soft:   #e7f1fa;

  --bg:           #f7f8fc;
  --surface:      #ffffff;
  --surface-2:    #f9fafb;
  --sidebar:      #0f1729;
  --sidebar-hover:#1c2740;
  --sidebar-text: #94a3b8;

  --ink:          #0f172a;
  --ink-2:        #334155;
  --muted:        #64748b;

  --line:         #e5e7eb;
  --line-2:       #d1d5db;

  --success:      #059669;
  --warning:      #d97706;
  --danger:       #dc2626;
  --info:         #0284c7;

  --shadow-xs:    0 1px 2px rgba(15,23,42,.06);
  --shadow-sm:    0 1px 3px rgba(15,23,42,.09), 0 1px 2px rgba(15,23,42,.06);
  --shadow:       0 4px 12px -2px rgba(15,23,42,.10), 0 2px 6px -2px rgba(15,23,42,.06);
  --shadow-lg:    0 20px 40px -12px rgba(15,23,42,.18);

  --radius:       14px;
  --radius-sm:    10px;
  --sidebar-w:    252px;
  --topbar-h:     62px;

  --bs-primary:     #0059b3;
  --bs-primary-rgb: 79,70,229;
  --bs-body-color:  #0f172a;
  --bs-body-bg:     #f7f8fc;
  --bs-border-color:#e5e7eb;

  color-scheme: light;
}

/* ─────────────────────────── 1b. Tokens — dark ────────────────────────────
   Not an inversion: surfaces are desaturated navy so the brand still reads,
   and text sits near #e2e8f0 rather than pure white to cut halation. */

[data-theme="dark"] {
  --brand:        #4aa8ee;
  --brand-2:      #79c4f7;
  --brand-soft:   #062a52;

  --bg:           #0b1120;
  --surface:      #131c31;
  --surface-2:    #1a2540;
  --sidebar:      #080d19;
  --sidebar-hover:#161f36;
  --sidebar-text: #94a3b8;

  --ink:          #e2e8f0;
  --ink-2:        #cbd5e1;
  --muted:        #94a3b8;

  --line:         #243049;
  --line-2:       #2f3d5c;

  --success:      #34d399;
  --warning:      #fbbf24;
  --danger:       #f87171;
  --info:         #38bdf8;

  --shadow-xs:    0 1px 2px rgba(0,0,0,.30);
  --shadow-sm:    0 1px 3px rgba(0,0,0,.36);
  --shadow:       0 4px 14px rgba(0,0,0,.42);
  --shadow-lg:    0 20px 44px rgba(0,0,0,.55);

  --bs-body-color:  #e2e8f0;
  --bs-body-bg:     #0b1120;
  --bs-border-color:#243049;

  color-scheme: dark;
}

/* ─────────────────────────────── 2. Base ──────────────────────────────── */

* { box-sizing: border-box; }

/* Fluid root.
   Every font-size in this file is expressed in rem, so this single rule sets
   the scale of the whole interface. Previously everything was fixed px, which
   is why the UI looked correct on a laptop and shrank into the corner of a
   large or high-resolution display — the pixels got smaller, the type did not.
   Floor 16px keeps phones exactly where they were; the ceiling stops a very
   wide monitor turning the app cartoonishly large. */
/* Published as a custom property rather than written straight onto html:
   a11y.css also sets html's font-size, for the per-account text-size control,
   and it loads after this file. Declared as a plain value this rule simply
   lost — the root sat at the browser's 16px default on every display, which
   is why a 1920px monitor showed exactly the same size type as a laptop.
   a11y.css multiplies this now instead of replacing it, so both work. */
:root { --pc-root-size: clamp(15.5px, 0.2vw + 14.4px, 18px); }
html {
  font-size: var(--pc-root-size);
  -webkit-text-size-adjust: 100%;
}

/* Self-hosted rather than linked to fonts.googleapis.com: the platform's CSP
   is `font-src 'self' data:` (app/bootstrap.php), so a Google Fonts <link>
   would be silently blocked and every page would have quietly fallen back to
   the OS default the whole time. One variable file covers weight 300–900 —
   the sizes this stylesheet actually asks for (400/500/600/700/800) — so
   there is no faux-bold synthesis at the heavier weights the way a static
   400-and-700-only file would need. Latin subset only: nothing on this
   platform is set in a non-Latin script.
   'Inter' was named here before this and was never actually loaded anywhere
   (no @font-face, no link) — every page has been silently rendering in the
   system-ui fallback all along. Roboto is now the one that is actually true. */
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('../fonts/roboto/Roboto-Variable.woff2') format('woff2-variations'),
       url('../fonts/roboto/Roboto-Variable.woff2') format('woff2');
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: 'Roboto', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 0.9375rem;          /* 15px at the 16px floor, 18.75px at the cap */
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  /* Only colours transition — animating "all" makes the sidebar and every
     chart jank on theme switch. */
  transition: background-color .2s ease, color .2s ease;
}

a { text-decoration: none; color: var(--brand); }
a:hover { color: var(--brand-2); }

h1,h2,h3,h4,h5,h6 { font-weight: 700; letter-spacing: -.02em; color: var(--ink); }

::selection { background: var(--brand); color: #fff; }

.text-muted { color: var(--muted) !important; }

/* Scrollbars, so dark mode has no bright gutter. */
* { scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 6px; }
*::-webkit-scrollbar-thumb:hover { background: var(--muted); }

/* ──────────────────────────── 3. App shell ────────────────────────────── */

.pc-topbar {
  height: var(--topbar-h);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 1040;
  display: flex; align-items: center;
  padding: 0 18px;
}

.pc-brand { display: flex; align-items: center; gap: 10px; }
.pc-brand-mark {
  width: 2.125rem; height: 2.125rem; border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: #fff; font-size: 1.0625rem; flex-shrink: 0;
  box-shadow: 0 4px 10px rgba(0,89,179,.32);
}
.pc-brand-name { font-weight: 800; font-size: 1.0313rem; color: var(--ink); letter-spacing: -.03em; }

.pc-shell { display: flex; min-height: calc(100vh - var(--topbar-h)); }

.pc-sidebar {
  width: var(--sidebar-w); flex: 0 0 var(--sidebar-w);
  background: var(--sidebar);
  position: sticky; top: var(--topbar-h);
  height: calc(100vh - var(--topbar-h));
  overflow-y: auto;
  display: flex; flex-direction: column;
  padding: 14px 0;
  z-index: 1030;
}
.pc-nav-label {
  color: #64748b; font-size: 0.6563rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 14px 20px 6px;
}
.pc-nav { list-style: none; margin: 0; padding: 0 10px; }
.pc-nav a {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; margin-bottom: 2px;
  border-radius: var(--radius-sm);
  color: var(--sidebar-text); font-size: 0.875rem;
  transition: background .15s, color .15s;
}
.pc-nav a i { font-size: 1rem; width: 20px; text-align: center; }
.pc-nav a:hover { background: var(--sidebar-hover); color: #fff; }
.pc-nav a.active {
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: #fff; font-weight: 600;
  box-shadow: 0 4px 12px rgba(0,89,179,.36);
}
.pc-sidebar-foot { margin-top: auto; padding: 14px 20px 4px; border-top: 1px solid #1e293b; }

.pc-main { flex: 1 1 auto; min-width: 0; padding: 22px 24px 44px; }

.pc-page-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 20px;
}
.pc-page-title { font-size: 1.4375rem; font-weight: 800; margin: 0 0 2px; }
.pc-page-sub { color: var(--muted); font-size: 0.875rem; margin: 0; }

.pc-backdrop { display: none; position: fixed; inset: 0; background: rgba(15,23,42,.5); z-index: 1025; }
.pc-backdrop.show { display: block; }

/* ───────────────────────────── 4. Components ──────────────────────────── */

.pc-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
  margin-bottom: 20px;
}
.pc-card-head {
  padding: 15px 19px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
}
.pc-card-title { font-size: 0.9688rem; font-weight: 700; margin: 0; }
.pc-card-body { padding: 19px; }
.pc-card-body.tight { padding: 0; }

/* Stat tiles */
.pc-stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
  padding: 17px 19px; height: 100%;
  display: flex; align-items: center; gap: 14px;
  transition: transform .18s, box-shadow .18s, border-color .18s;
  position: relative; overflow: hidden;
}
.pc-stat:hover { transform: translateY(-2px); box-shadow: var(--shadow); border-color: var(--brand); }
.pc-stat-icon {
  width: 2.875rem; height: 2.875rem; border-radius: 12px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.25rem; color: #fff;
}
.pc-stat-value { font-size: 1.5rem; font-weight: 800; line-height: 1.1; letter-spacing: -.03em; }
.pc-stat-label { font-size: 0.7188rem; color: var(--muted); font-weight: 700;
                 text-transform: uppercase; letter-spacing: .05em; }
.pc-stat-sub { font-size: 0.75rem; color: var(--muted); }

.grad-ocean  { background: linear-gradient(135deg,#0059b3,#0070d0); }
.grad-emerald { background: linear-gradient(135deg,#059669,#10b981); }
.grad-amber   { background: linear-gradient(135deg,#d97706,#f59e0b); }
.grad-rose    { background: linear-gradient(135deg,#e11d48,#f43f5e); }
.grad-sky     { background: linear-gradient(135deg,#0284c7,#0ea5e9); }
.grad-reef  { background: linear-gradient(135deg,#0059b3,#00a050); }
.grad-slate   { background: linear-gradient(135deg,#334155,#64748b); }
.grad-teal    { background: linear-gradient(135deg,#003090,#0070d0); }

/* Forms */
.form-label { font-weight: 600; font-size: 0.8125rem; color: var(--ink-2); margin-bottom: 5px; }
.form-control, .form-select {
  border-radius: var(--radius-sm);
  border-color: var(--line-2);
  background: var(--surface);
  color: var(--ink);
  font-size: 0.875rem; padding: .55rem .8rem;
}
.form-control:focus, .form-select:focus {
  background: var(--surface); color: var(--ink);
  border-color: var(--brand);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 15%, transparent);
}
.form-control::placeholder { color: var(--muted); opacity: .75; }
.input-group-text {
  background: var(--surface-2); border-color: var(--line-2);
  color: var(--muted); border-radius: var(--radius-sm);
}
.form-text { font-size: 0.7813rem; color: var(--muted); }
/* Excluded: Tom Select builds a .ts-wrapper around every searchable dropdown
   and copies the field's `required` onto it as a CLASS, which made this rule
   paint a second asterisk floating on the control itself — the label already
   carries the only one this is for. */
.required:not(.ts-wrapper)::after { content: ' *'; color: var(--danger); }
.form-check-input:checked { background-color: var(--brand); border-color: var(--brand); }

.btn { border-radius: var(--radius-sm); font-weight: 600; font-size: 0.875rem; padding: .55rem 1.05rem; }
.btn-primary { background: var(--brand); border-color: var(--brand); }
.btn-primary:hover, .btn-primary:focus {
  background: color-mix(in srgb, var(--brand) 85%, #000);
  border-color: color-mix(in srgb, var(--brand) 85%, #000);
}
.btn-brand {
  background: #0e3d7c;
  color: #fff; border: none;
  box-shadow: 0 6px 16px rgba(14,61,124,.28);
}
/* ── Why this needs an explicit background on every state ─────────────────
   .btn-brand rides on Bootstrap's .btn, which drives its OWN hover, focus and
   active backgrounds off custom properties — --bs-btn-hover-bg and
   --bs-btn-active-bg — that only get a real value from a Bootstrap variant
   class (.btn-primary, .btn-outline-secondary, and so on). .btn-brand is not
   one of those, so it never sets them, and var(--bs-btn-hover-bg) with no
   fallback resolves to nothing: the property is treated as unset and
   background-color falls back to its initial value, transparent.

   Bootstrap's own .btn:hover/:focus-visible/:active rules and this one are
   the same specificity — one class plus one pseudo-class — so this wins on
   source order alone, which is fragile the moment somebody reorders a
   <link>. Declaring the background on all three states here means it wins
   regardless of order, and there is no separate class in this codebase that
   depends on order to render correctly.

   The bug this fixes: white text with nothing behind it on hover — every
   button using .btn-brand across the site (101 places), the submit button
   on the public registration form among them. */
.btn-brand:hover,
.btn-brand:focus-visible,
.btn-brand:active {
  /* !important, and specifically here: Bootstrap also ships
     .btn:first-child:active { background-color: var(--bs-btn-active-bg); … } —
     for adjacent toggle-style buttons, but it matches ANY standalone .btn
     that happens to be first in its row, which .btn-brand usually is (the
     primary action is conventionally listed first). That selector is one
     class plus two pseudo-classes, genuinely more specific than this rule at
     one class plus one, so it wins on specificity regardless of load order —
     equal-specificity source-order tricks that fixed :hover and
     :focus-visible do not reach it. Matching every adjacency combinator
     Bootstrap might combine with :active (:first-child, :last-child,
     :only-child, :nth-child(n)) to chase an equal specificity would be
     guessing at a moving target; pinning the two properties this rule
     actually owns is the narrow, deliberate fix. */
  background: #0e3d7c !important; color: #fff !important; border-color: transparent;
}
.btn-brand:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn-brand:focus-visible { box-shadow: 0 0 0 4px color-mix(in srgb, #0e3d7c 30%, transparent); }
.btn-lg { padding: .72rem 1.4rem; font-size: 0.9688rem; }
.btn-sm { padding: .34rem .72rem; font-size: 0.8rem; }

.badge { font-weight: 600; letter-spacing: .01em; padding: .38em .65em; }

/* Status pills — semantic, so a status is recognisable at a glance anywhere. */
.pill { display: inline-flex; align-items: center; gap: 5px;
        font-size: 0.7188rem; font-weight: 700; padding: 3px 9px; border-radius: 20px;
        text-transform: uppercase; letter-spacing: .03em; }
.pill-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pill-active,   .pill-completed { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); }
.pill-trial,    .pill-draft     { background: color-mix(in srgb, var(--warning) 16%, transparent); color: var(--warning); }
.pill-expired,  .pill-cancelled { background: color-mix(in srgb, var(--danger) 14%, transparent);  color: var(--danger); }
.pill-suspended                 { background: color-mix(in srgb, var(--danger) 14%, transparent);  color: var(--danger); }
.pill-neutral                   { background: color-mix(in srgb, var(--muted) 15%, transparent);   color: var(--muted); }

/* Avatars */
.pc-avatar {
  border-radius: 50%; object-fit: cover;
  background: var(--brand-soft); color: var(--brand);
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 700; flex-shrink: 0;
}
.pc-avatar-sm { width: 2.125rem; height: 2.125rem; font-size: 0.8125rem; }
.pc-avatar-md { width: 3.25rem; height: 3.25rem; font-size: 1.1875rem; }
.pc-avatar-lg { width: 5.5rem; height: 5.5rem; font-size: 2rem; }

/* Tables */
.table { --bs-table-color: var(--ink); --bs-table-bg: transparent; margin-bottom: 0; }
.table > thead th {
  background: var(--surface-2);
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted);
  border-bottom: 1px solid var(--line); white-space: nowrap;
  padding: 11px 14px;
}
.table > tbody td { padding: 12px 14px; vertical-align: middle; border-color: var(--line); }
.table > tbody tr:hover > * { background: var(--surface-2); }

/* Empty states */
.pc-empty { text-align: center; padding: 52px 20px; color: var(--muted); }
.pc-empty i { font-size: 2.75rem; opacity: .28; display: block; margin-bottom: 14px; }
.pc-empty h3 { font-size: 1rem; color: var(--ink); margin-bottom: 6px; }
.pc-empty p { font-size: 0.8438rem; max-width: 380px; margin: 0 auto 16px; }

/* Skeleton loader */
.pc-skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--line) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: pc-shimmer 1.4s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes pc-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* QR panel */
.pc-qr-frame {
  background: #fff; border: 1px solid var(--line);
  border-radius: var(--radius); padding: 14px;
  display: inline-block; box-shadow: var(--shadow-xs);
}
.pc-qr-frame img { display: block; width: 200px; height: 200px; image-rendering: pixelated; }

.pc-copy {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface-2); border: 1px dashed var(--line-2);
  border-radius: var(--radius-sm); padding: 9px 12px;
  font-size: 0.8rem; word-break: break-all;
}

.chart-box { position: relative; height: 280px; }
.chart-box.short { height: 210px; }

/* Live indicator */
.pc-live {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.7188rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--success);
}
.pc-live-dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--success);
  animation: pc-pulse 1.8s ease-in-out infinite;
}
@keyframes pc-pulse {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 60%, transparent); }
  50%      { opacity: .7; box-shadow: 0 0 0 6px transparent; }
}

/* A row that just arrived via polling. */
.pc-row-new { animation: pc-flash 2s ease-out; }
@keyframes pc-flash {
  0%   { background: color-mix(in srgb, var(--success) 22%, transparent); }
  100% { background: transparent; }
}

/* Timeline */
.pc-timeline { position: relative; padding-left: 28px; }
.pc-timeline::before { content:''; position:absolute; left:8px; top:4px; bottom:4px; width:2px; background: var(--line); }
.pc-timeline-item { position: relative; padding-bottom: 16px; }
.pc-timeline-item::before {
  content:''; position:absolute; left:-24px; top:5px; width:11px; height:11px; border-radius:50%;
  background: var(--brand); border: 2px solid var(--surface);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--brand) 26%, transparent);
}

/* Surfaces Bootstrap paints itself */
.modal-content, .dropdown-menu, .offcanvas, .accordion-item, .list-group-item, .card {
  background: var(--surface); color: var(--ink); border-color: var(--line);
}
.modal-header, .modal-footer { border-color: var(--line); }
.dropdown-item { color: var(--ink-2); }
.dropdown-item:hover, .dropdown-item:focus { background: var(--surface-2); color: var(--ink); }
.dropdown-divider { border-color: var(--line); }
.bg-light { background: var(--surface-2) !important; color: var(--ink); }
.border, .border-top, .border-bottom, .border-start, .border-end { border-color: var(--line) !important; }
hr { border-color: var(--line); opacity: 1; }
.progress { background: var(--line); border-radius: 5px; height: 8px; }
.progress-bar { background: var(--brand); border-radius: 5px; }
.nav-tabs { border-color: var(--line); }
.nav-tabs .nav-link { color: var(--muted); border: none; border-bottom: 2px solid transparent; font-weight: 600; }
.nav-tabs .nav-link:hover { color: var(--ink); border-bottom-color: var(--line-2); }
.nav-tabs .nav-link.active { color: var(--brand); background: transparent; border-bottom-color: var(--brand); }

/* ──────────────────────── 5. Public check-in ──────────────────────────── */

.pc-public {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: 22px 14px;
  background:
    radial-gradient(ellipse 70% 50% at 50% 0%, color-mix(in srgb, var(--brand) 16%, transparent), transparent 70%),
    var(--bg);
}
.pc-checkin {
  width: 100%; max-width: 480px;
  background: var(--surface);
  border-radius: 20px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.pc-checkin-banner {
  height: 132px; position: relative;
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  background-size: cover; background-position: center;
}
.pc-checkin-banner::after {
  content:''; position:absolute; inset:0;
  background: radial-gradient(circle at 20% 120%, rgba(255,255,255,.22), transparent 60%);
}
.pc-checkin-logo {
  width: 68px; height: 68px; border-radius: 16px; background: #fff;
  border: 3px solid #fff; object-fit: contain; padding: 5px;
  margin: -40px auto 0; position: relative; z-index: 2; display: block;
  box-shadow: var(--shadow);
}
.pc-checkin-body { padding: 16px 24px 26px; }
.pc-checkin-meta { display: flex; align-items: center; gap: 9px; font-size: 0.8438rem;
                   color: var(--ink-2); padding: 7px 0; }
.pc-checkin-meta i { color: var(--brand); width: 18px; text-align: center; flex-shrink: 0; }

.pc-success-check {
  width: 84px; height: 84px; border-radius: 50%; margin: 0 auto 18px;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--success) 14%, transparent);
  color: var(--success); font-size: 2.625rem;
  animation: pc-pop .45s cubic-bezier(.16,1,.3,1);
}
@keyframes pc-pop { 0% { transform: scale(.4); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }

/* ── Certificate ────────────────────────────────────────────────────────────
   A double-border frame rather than an image is what reads as "certificate"
   here — no asset to ship, and it scales to any paper size when printed. */
.pc-cert-page { min-height: 100vh; padding: 28px 14px; background: var(--bg); }
.pc-cert {
  width: 100%; max-width: 900px; margin: 0 auto;
  background: var(--surface);
  border-radius: 4px;
  box-shadow: var(--shadow-lg);
  padding: 10px;
}
.pc-cert-frame {
  border: 2px solid var(--cert-brand, var(--brand));
  border-radius: 2px;
  padding: 3px;
}
.pc-cert-inner {
  border: 1px solid color-mix(in srgb, var(--cert-brand, var(--brand)) 45%, transparent);
  border-radius: 2px;
  padding: clamp(28px, 5vw, 56px) clamp(24px, 6vw, 64px);
  text-align: center;
}
.pc-cert-logo {
  width: 64px; height: 64px; border-radius: 12px; object-fit: contain;
  margin: 0 auto 14px; display: block; padding: 6px; background: var(--surface-2);
}
.pc-cert-eyebrow {
  color: var(--cert-brand, var(--brand)); font-weight: 700; font-size: 0.75rem;
  letter-spacing: .18em; text-transform: uppercase; margin-bottom: 22px;
}
.pc-cert-lede { color: var(--muted); font-size: 0.9375rem; margin-bottom: 6px; }
.pc-cert-name {
  font-size: clamp(1.7rem, 4.4vw, 2.7rem); font-weight: 800; letter-spacing: -.02em;
  color: var(--ink); margin: 4px 0 18px;
  font-family: Georgia, 'Times New Roman', serif;
}
.pc-cert-event { font-size: 1.15rem; font-weight: 700; color: var(--ink); margin-bottom: 4px; }
.pc-cert-meta { color: var(--muted); font-size: 0.875rem; margin-bottom: 30px; }
.pc-cert-org { color: var(--ink-2); font-size: 0.9375rem; font-weight: 600; margin-bottom: 36px; }

.pc-cert-sign-row {
  display: flex; justify-content: space-between; align-items: flex-end;
  gap: 24px; margin-top: 30px; text-align: left; flex-wrap: wrap;
}
.pc-cert-sign-line {
  border-top: 1px solid var(--line-2); padding-top: 8px; min-width: 220px;
}
.pc-cert-sign-name  { font-weight: 700; font-size: 0.9375rem; }
.pc-cert-sign-title { color: var(--muted); font-size: 0.8125rem; }
.pc-cert-verify {
  text-align: right; color: var(--muted); font-size: 0.75rem; line-height: 1.5;
}
.pc-cert-verify code {
  color: var(--ink-2); background: var(--surface-2); padding: 1px 6px;
  border-radius: 4px; font-size: 0.75rem;
}
.pc-cert-actions { max-width: 900px; margin: 20px auto 0; display: flex; gap: 10px; justify-content: center; }

@media (max-width: 575.98px) {
  .pc-cert-sign-row { flex-direction: column; align-items: stretch; text-align: center; }
  .pc-cert-verify { text-align: center; }
  .pc-cert-sign-line { text-align: center; }
}

@media print {
  .pc-cert-page { padding: 0; background: #fff; }
  .pc-cert { box-shadow: none; max-width: none; }
}

/* ────────────────────────── 6. Auth screens ───────────────────────────── */

/* Column, not a centring box: the navbar and masi trim sit at their natural
   height at the top and the card centres in whatever space is left. Centring
   every child would lay the navbar out beside the form. */
.pc-auth {
  min-height: 100vh; display: flex; flex-direction: column;
  background: linear-gradient(150deg, #062a52 0%, #0059b3 45%, #0070d0 100%);
  position: relative;
}
.pc-auth > .lp-navbar, .pc-auth > .pc-masi { flex: 0 0 auto; }
/* Tapa runner down the left edge, matching the hero. */
.pc-auth::before {
  content:''; position:absolute; top:0; bottom:0; left:0; width: min(300px, 32%);
  background-image: var(--tapa); background-size: 120px 120px; opacity: .42;
  pointer-events: none; z-index: 0;
  -webkit-mask-image: linear-gradient(to right, #000 55%, transparent);
          mask-image: linear-gradient(to right, #000 55%, transparent);
}
.pc-auth-wrap {
  width: 100%; max-width: 430px; margin: auto;
  padding: 34px 16px; position: relative; z-index: 1;
}
.pc-auth-md    { max-width: 33rem; }
.pc-auth-split { max-width: 68rem; }
/* The signup form has enough fields to look like a ribbon in a single column
   on a large display, so it gets a pitch panel beside it instead. */
.pc-auth-split .pc-auth-pitch { color: #fff; }
.pc-auth-split .pc-auth-pitch h2 {
  color: #fff; font-size: clamp(1.5rem, 2.2vw, 2.1rem);
  font-weight: 800; letter-spacing: -.03em; line-height: 1.15;
}
.pc-auth-split .pc-auth-pitch p { color: rgba(255,255,255,.74); }
.pc-auth-point { display: flex; gap: .8rem; align-items: flex-start; margin-bottom: 1.1rem; }
.pc-auth-point i {
  flex: 0 0 1.75rem; width: 1.75rem; height: 1.75rem; border-radius: 8px;
  display: grid; place-items: center; font-size: .9rem; color: #fff;
  background: rgba(255,255,255,.16);
}
.pc-auth-point strong { color: #fff; display: block; font-size: .95rem; }
.pc-auth-point span   { color: rgba(255,255,255,.68); font-size: .875rem; }
.pc-auth-brand { text-align: center; margin-bottom: 22px; color: #fff; }
.pc-auth-brand .pc-brand-mark { width: 3.25rem; height: 3.25rem; font-size: 1.5625rem; margin: 0 auto 12px; }
.pc-auth-brand h1 { color: #fff; font-size: 1.3125rem; margin: 0 0 4px; }
.pc-auth-brand p { color: rgba(255,255,255,.66); font-size: 0.8438rem; margin: 0; }
.pc-auth-card {
  background: var(--surface); border-radius: 18px; padding: 30px 28px;
  box-shadow: 0 24px 60px rgba(0,0,0,.34);
}
.pc-auth-card h2 { font-size: 1.1875rem; margin: 0 0 4px; }
.pc-auth-card .sub { color: var(--muted); font-size: 0.8438rem; margin: 0 0 20px; }
.pc-auth-foot { text-align: center; margin-top: 18px; font-size: 0.8438rem; color: rgba(255,255,255,.72); }
.pc-auth-foot a { color: #a9d6f2; font-weight: 600; }

.pc-meter { height: 5px; border-radius: 3px; background: var(--line); overflow: hidden; margin-top: 7px; }
.pc-meter span { display: block; height: 100%; width: 0; transition: width .25s, background .25s; }

/* ───────────────────────────── 7. Landing ─────────────────────────────── */

/* ── Pacific motif ──────────────────────────────────────────────────────────
   A masi (tapa cloth) geometry — concentric diamonds with corner triangles.
   Used at low opacity over the brand gradient so it reads as cloth texture
   rather than wallpaper. White strokes, so one tile works on any brand colour
   and survives a white-label palette change. */
:root {
  --tapa: url("data:image/svg+xml,%3Csvg width='120' height='120' viewBox='0 0 120 120' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolygon points='60,4 116,60 60,116 4,60' fill='none' stroke='white' stroke-opacity='.20' stroke-width='2'/%3E%3Cpolygon points='60,22 98,60 60,98 22,60' fill='none' stroke='white' stroke-opacity='.13' stroke-width='1.4'/%3E%3Cpolygon points='60,40 80,60 60,80 40,60' fill='white' fill-opacity='.10'/%3E%3Cpolygon points='0,0 22,0 0,22' fill='white' fill-opacity='.16'/%3E%3Cpolygon points='120,0 98,0 120,22' fill='white' fill-opacity='.16'/%3E%3Cpolygon points='0,120 22,120 0,98' fill='white' fill-opacity='.16'/%3E%3Cpolygon points='120,120 98,120 120,98' fill='white' fill-opacity='.16'/%3E%3C/svg%3E");
}

/* Masi trim — a woven band that separates sections, in the brand palette. */
.pc-masi {
  height: 22px; width: 100%;
  background-color: #eef0fb;
  background-image: url("data:image/svg+xml,%3Csvg width='76' height='26' viewBox='0 0 76 26' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='76' height='26' fill='%23eef0fb'/%3E%3Cpath d='M0 26 L19 5 L38 26 Z' fill='%23c7cbf0'/%3E%3Cpath d='M38 0 L57 21 L76 0 Z' fill='%23dcc9f5'/%3E%3Cpolygon points='19,12 22.5,15.5 19,19 15.5,15.5' fill='%23a5abe8'/%3E%3Cpolygon points='57,7 60.5,10.5 57,14 53.5,10.5' fill='%23c3a8ef'/%3E%3C/svg%3E");
  background-size: 76px 26px; background-repeat: repeat-x;
  border-top: 1px solid #e0e4f6; border-bottom: 1px solid #e0e4f6;
}
.pc-masi.thin { height: 14px; background-size: 46px 16px; }
[data-theme="dark"] .pc-masi {
  background-color: #1a1f3a;
  background-image: url("data:image/svg+xml,%3Csvg width='76' height='26' viewBox='0 0 76 26' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='76' height='26' fill='%231a1f3a'/%3E%3Cpath d='M0 26 L19 5 L38 26 Z' fill='%233b3f70'/%3E%3Cpath d='M38 0 L57 21 L76 0 Z' fill='%234a3a72'/%3E%3Cpolygon points='19,12 22.5,15.5 19,19 15.5,15.5' fill='%23575ca0'/%3E%3Cpolygon points='57,7 60.5,10.5 57,14 53.5,10.5' fill='%236b4fa3'/%3E%3C/svg%3E");
  border-color: #262c4e;
}

/* ── Navbar ─────────────────────────────────────────────────────────────────
   Transparent while it sits over the coloured hero, then settling onto the
   brand gradient once the page scrolls under it. Both states are light-on-dark,
   so the link colour never has to jump. */
.lp-navbar {
  /* Always on brand colour. `sticky-top` keeps the bar in normal flow, so a
     transparent bar at scroll-0 would put white text on the light page
     background and disappear — the colour is not decoration, it is what makes
     the links legible. Scrolling deepens it rather than introducing it. */
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-2) 100%);
  border-bottom: 1px solid transparent;
  padding: .62rem 0;
  transition: background .3s ease, box-shadow .3s ease, padding .3s ease;
}
.lp-navbar.scrolled,
.lp-navbar.solid {
  background: linear-gradient(135deg, #003090 0%, #0070d0 100%);
  box-shadow: 0 8px 26px -10px rgba(15,23,42,.62);
  padding: .42rem 0;
}
/* Masi motif woven through the bar. */
.lp-navbar::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image: var(--tapa); background-size: 120px 120px;
  opacity: .26; transition: opacity .3s ease;
}
.lp-navbar.scrolled::after, .lp-navbar.solid::after { opacity: .34; }
.lp-navbar > .container { position: relative; z-index: 1; }

.lp-brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.lp-brand-mark {
  width: 2.125rem; height: 2.125rem; border-radius: 10px; flex: 0 0 2.125rem;
  display: grid; place-items: center; color: #fff; font-size: 1.0625rem;
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  box-shadow: 0 3px 10px -2px rgba(0,89,179,.55);
}
.lp-brand-name { font-weight: 800; letter-spacing: -.02em; color: #fff; font-size: 1.12rem; }
.lp-navbar .lp-brand-mark { background: rgba(255,255,255,.16); box-shadow: none; }
.lp-navbar.scrolled .lp-brand-mark,
.lp-navbar.solid   .lp-brand-mark { background: rgba(255,255,255,.2); }

.lp-nav-link {
  color: rgba(255,255,255,.84); font-weight: 500; font-size: .945rem;
  padding: .5rem .85rem; border-radius: 8px; transition: color .15s, background .15s;
}
.lp-nav-link:hover, .lp-nav-link:focus { color: #fff; background: rgba(255,255,255,.14); }
.lp-nav-link.active { color: #fff; font-weight: 600; background: rgba(255,255,255,.16); }

.lp-toggler {
  border: 1px solid rgba(255,255,255,.35); border-radius: 9px; padding: .3rem .6rem;
  font-size: 1.35rem; color: #fff; line-height: 1;
}
.lp-toggler:focus { box-shadow: 0 0 0 .2rem rgba(255,255,255,.3); }

.lp-btn-ghost {
  border: 1px solid rgba(255,255,255,.5); color: #fff; font-weight: 600;
  padding: .44rem 1.05rem; border-radius: 9px; background: transparent;
}
.lp-btn-ghost:hover { border-color: #fff; color: var(--brand); background: #fff; }

/* Used both in the navbar (on colour) and in page content (on surface), so it
   carries its own gradient rather than depending on the backdrop. */
.lp-btn-solid {
  background: #fff; color: var(--brand); font-weight: 700;
  padding: .44rem 1.05rem; border-radius: 9px;
  border: 1px solid transparent; box-shadow: 0 3px 10px -3px rgba(15,23,42,.35);
}
.lp-btn-solid:hover { color: var(--brand-2); background: #fff; filter: brightness(1.02); }
/* Outside the bar it needs to be the brand colour, not white on white. */
.lp-footer .lp-btn-solid,
section .lp-btn-solid,
.pc-card .lp-btn-solid {
  background: linear-gradient(135deg, var(--brand), var(--brand-2));
  color: #fff; box-shadow: 0 3px 10px -3px rgba(0,89,179,.6);
}
.lp-footer .lp-btn-solid:hover,
section .lp-btn-solid:hover,
.pc-card .lp-btn-solid:hover { color: #fff; filter: brightness(1.07); }

.lp-theme-btn {
  border: 1px solid rgba(255,255,255,.35); color: #fff; border-radius: 9px;
  padding: .44rem .7rem; background: transparent;
}
.lp-theme-btn:hover { color: var(--brand); border-color: #fff; background: #fff; }

/* The collapsed menu is a panel, not a squashed row. It also forces the solid
   bar, because an open menu floating over page content is unreadable. */
@media (max-width: 991.98px) {
  #lpNavMenu { padding: .85rem .25rem .55rem; }
  .lp-nav-link { display: block; padding: .62rem .7rem; }
  .lp-btn-ghost, .lp-btn-solid, .lp-theme-btn { width: 100%; text-align: center; }
}

/* ── Hero ───────────────────────────────────────────────────────────────────
   A photograph of the thing the product does, behind a brand overlay.

   The overlay is asymmetric on purpose. The photo is busiest on the left —
   faces, signage, a tablet — which is exactly where the headline sits, so the
   scrim is near-opaque there and thins out to the right where the check-in
   card floats and the picture should still read. Legibility first; the image
   is atmosphere, not content. */
.lp-hero {
  /* The gradient is the fallback: if the image 404s or has not arrived yet,
     the hero is still the branded panel it was before, never bare white. */
  background:
    linear-gradient(155deg,#062a52 0%,#0059b3 45%,#0070d0 100%);
  color: #fff; padding: 84px 0 92px; position: relative; overflow: hidden;
  isolation: isolate;
}
/* Photo layer. image-set lets the browser take WebP when it can (124 KB) and
   fall back to JPEG (196 KB) when it cannot. */
.lp-hero::after {
  content:''; position:absolute; inset:0; z-index:-2;
  background-image: url('../img/hero.jpg');
  background-image: image-set(url('../img/hero.webp') type('image/webp'),
                              url('../img/hero.jpg')  type('image/jpeg'));
  background-size: cover;
  background-position: 68% center;   /* keeps the QR signage and desk in frame */
  background-repeat: no-repeat;
}
/* Overlay layer — brand colour, weighted to the left. */
.lp-hero::before {
  content:''; position:absolute; inset:0; z-index:-1;
  background:
    linear-gradient(100deg,
      rgba(5,25,47,.96) 0%,
      rgba(10,58,128,.92) 30%,
      rgba(0,89,179,.78) 56%,
      rgba(20,135,201,.55) 78%,
      rgba(31,150,190,.46) 100%),
    radial-gradient(circle at 84% 6%, rgba(0,160,80,.42), transparent 58%);
}
/* Phones get the 760px variant — a 1376px photo on a 390px screen is waste. */
@media (max-width: 767.98px) {
  .lp-hero::after {
    background-image: url('../img/hero-sm.jpg');
    background-image: image-set(url('../img/hero-sm.webp') type('image/webp'),
                                url('../img/hero-sm.jpg')  type('image/jpeg'));
    background-position: 62% center;
  }
  /* Text runs full width on a phone, so the scrim must be even across it. */
  .lp-hero::before {
    background:
      linear-gradient(180deg, rgba(5,25,47,.94) 0%, rgba(0,89,179,.9) 60%, rgba(20,135,201,.88) 100%);
  }
}
/* Tapa cloth across the hero — a wide band down the left, the way a masi
   runner is laid, rather than a flat tile over the whole panel. Its own
   element rather than a pseudo-element: ::before and ::after are both spoken
   for by the overlay and the photo, and a third layer needs a third box.
   Lower opacity than elsewhere so it textures the photo instead of fighting
   it for attention. */
.lp-hero-tapa {
  position: absolute; top: 0; bottom: 0; left: 0; width: min(20.5rem, 34%);
  background-image: var(--tapa); background-size: 120px 120px;
  opacity: .34; z-index: 0; pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, #000 50%, transparent);
          mask-image: linear-gradient(to right, #000 50%, transparent);
}

/* Any brand-gradient band (page headers, closing CTA) gets the same cloth. */
.pc-band { position: relative; overflow: hidden; }
.pc-band::before {
  content:''; position:absolute; inset:0; pointer-events:none;
  background-image: var(--tapa); background-size: 120px 120px; opacity: .3;
}
.pc-band > .container { position: relative; z-index: 1; }
.lp-hero > .container { position: relative; z-index: 1; }

/* Typewriter.
   Every phrase is rendered invisibly into the same grid cell as the animated
   one, so the box is always sized to the *tallest and widest* phrase and the
   hero never changes height while typing. A min-height reserving a single line
   is not enough: the moment a longer phrase wraps to two lines the whole
   banner grows, then shrinks again as it is erased. Letting the browser
   measure the real phrases means it stays correct at every viewport width and
   font size, with no magic numbers. */
.pc-type-wrap { display: inline-grid; vertical-align: top; text-align: left; }
.pc-type-wrap > * { grid-area: 1 / 1; }
.pc-type-ghost { visibility: hidden; pointer-events: none; user-select: none; }
.pc-type {
  color: #8fd3f4;
  text-shadow: 0 2px 18px rgba(5,25,47,.55);
}
.pc-type-caret {
  display: inline-block; width: .06em; min-width: 2px; height: .95em;
  background: #79c4f7; margin-left: .06em; vertical-align: -0.1em;
  animation: afCaret 1.05s steps(1) infinite;
}
@keyframes afCaret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* Exposed to screen readers, invisible on screen. */
.pc-sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
@media (prefers-reduced-motion: reduce) { .pc-type-caret { animation: none; } }

.lp-hero h1 {
  color:#fff; font-size: clamp(2.05rem, 5vw, 3.35rem);
  letter-spacing:-.038em; line-height: 1.1; font-weight: 800;
  text-shadow: 0 2px 24px rgba(5,25,47,.5);
}
.lp-hero .lead { color: rgba(255,255,255,.8); font-size: 1.08rem; }
.lp-eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(255,255,255,.12); border: 1px solid rgba(255,255,255,.2);
  color: #fff; font-size: .8rem; font-weight: 600; letter-spacing: .01em;
  padding: .34rem .85rem; border-radius: 30px; margin-bottom: 1.1rem;
}
.lp-trust { color: rgba(255,255,255,.62); font-size: .85rem; }
.lp-stat-n { font-size: 1.75rem; font-weight: 800; color: #fff; letter-spacing: -.03em; line-height: 1; }
.lp-stat-l { color: rgba(255,255,255,.6); font-size: .78rem; text-transform: uppercase; letter-spacing: .07em; }

/* Section furniture */
.lp-section-tag {
  color: var(--brand); font-weight: 700; font-size: .78rem;
  text-transform: uppercase; letter-spacing: .1em;
}
.lp-h2 { font-weight: 800; letter-spacing: -.03em; font-size: clamp(1.5rem, 3vw, 2.05rem); }

/* ── Scroll reveal ──────────────────────────────────────────────────────────
   Elements start slightly offset and fade in when they enter the viewport.
   The .js-reveal class is only added by script, so with JavaScript disabled
   nothing is ever hidden — content must never depend on an animation running. */
.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .55s cubic-bezier(.22,.61,.36,1),
              transform .55s cubic-bezier(.22,.61,.36,1);
  will-change: opacity, transform;
}
.js-reveal [data-reveal].is-visible {
  opacity: 1; transform: none; will-change: auto;
}

/* ── Section illustrations ──────────────────────────────────────────────── */
.pc-ill { width: 100%; height: auto; max-width: 20rem; display: block; margin: 0 auto; overflow: visible; }
.pc-ill-shadow { fill: rgba(15,23,42,.10); }
[data-theme="dark"] .pc-ill-shadow { fill: rgba(0,0,0,.4); }

/* The whole illustration drifts, so it does not sit dead on the page. */
.pc-ill-sheet, .pc-ill-scan, .pc-ill-chart { animation: afFloat 6s ease-in-out infinite; }
.pc-ill-scan  { animation-duration: 7s; animation-delay: -1.5s; }
.pc-ill-chart { animation-duration: 8s; animation-delay: -3s; }
@keyframes afFloat {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}

/* Ticks draw themselves onto the sheet, one after another. */
.pc-ill-tick polyline {
  stroke-dasharray: 26; stroke-dashoffset: 26;
  animation: afDraw 4.5s ease-in-out infinite;
}
@keyframes afDraw {
  0%, 8%    { stroke-dashoffset: 26; }
  22%, 78%  { stroke-dashoffset: 0; }
  92%, 100% { stroke-dashoffset: 26; }
}

/* Pencil writes along the page. */
.pc-ill-pencil { animation: afWrite 4.5s ease-in-out infinite; transform-origin: 60% 60%; }
@keyframes afWrite {
  0%, 100% { transform: translate(0,0) rotate(0deg); }
  25%      { transform: translate(-6px,-16px) rotate(-4deg); }
  50%      { transform: translate(-11px,-32px) rotate(2deg); }
  75%      { transform: translate(-5px,-14px) rotate(-2deg); }
}

/* Scanner sweep + confirmation pulse. */
.pc-ill-scanline { animation: afSweep 2.8s cubic-bezier(.45,0,.55,1) infinite; opacity: .9; }
@keyframes afSweep {
  0%, 100% { transform: translateY(0);   opacity: 0; }
  10%      { opacity: .95; }
  50%      { transform: translateY(58px); opacity: .95; }
  90%      { opacity: 0; }
}
.pc-ill-pulse { animation: afPop 2.8s ease-in-out infinite; transform-origin: 130px 150px; }
@keyframes afPop {
  0%, 45%   { opacity: 0; transform: scale(.7); }
  60%, 88%  { opacity: 1; transform: scale(1); }
  100%      { opacity: 0; transform: scale(.7); }
}

/* Bars grow from the baseline. */
.pc-ill-bars rect {
  y: 150px; height: 0;
  animation: afGrow 3.6s cubic-bezier(.22,.61,.36,1) infinite;
}
@keyframes afGrow {
  0%, 6%    { height: 0;             y: 150px; }
  35%, 70%  { height: var(--h, 40px); y: calc(150px - var(--h, 40px)); }
  96%, 100% { height: 0;             y: 150px; }
}
.pc-ill-dot { animation: afBlink 1.6s ease-in-out infinite; }
@keyframes afBlink { 0%,100% { opacity: 1; } 50% { opacity: .25; } }

/* Floating tapa diamonds behind a section — depth without another image. */
.pc-floaters { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 0; }
.pc-floater {
  position: absolute; border: 2px solid var(--brand);
  opacity: .09; border-radius: 6px; transform: rotate(45deg);
  animation: afDrift 18s ease-in-out infinite;
}
.pc-floater:nth-child(1) { width: 4.5rem; height: 4.5rem; top: 12%;  left: 6%;  }
.pc-floater:nth-child(2) { width: 2.75rem; height: 2.75rem; top: 62%; left: 13%; animation-delay: -4s; border-color: var(--brand-2); }
.pc-floater:nth-child(3) { width: 6rem;   height: 6rem;   top: 22%;  right: 7%; animation-delay: -9s; }
.pc-floater:nth-child(4) { width: 2rem;   height: 2rem;   top: 74%;  right: 16%; animation-delay: -13s; border-color: var(--brand-2); }
@keyframes afDrift {
  0%, 100% { transform: rotate(45deg) translate(0,0); }
  33%      { transform: rotate(52deg) translate(10px,-16px); }
  66%      { transform: rotate(38deg) translate(-8px,12px); }
}
.pc-has-floaters { position: relative; }
.pc-has-floaters > .container { position: relative; z-index: 1; }

/* One switch turns all of it off for anyone who asked the OS to stop motion. */
@media (prefers-reduced-motion: reduce) {
  .pc-ill-sheet, .pc-ill-scan, .pc-ill-chart, .pc-ill-pencil, .pc-ill-scanline,
  .pc-ill-pulse, .pc-ill-tick polyline, .pc-ill-bars rect, .pc-ill-dot, .pc-floater {
    animation: none !important;
  }
  .pc-ill-bars rect { height: var(--h, 40px); y: calc(150px - var(--h, 40px)); }
  .pc-ill-tick polyline { stroke-dashoffset: 0; }
  .js-reveal [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* Footer */
.lp-footer { background: var(--surface-2); border-top: 1px solid var(--line); }
.lp-footer-head {
  font-size: .78rem; text-transform: uppercase; letter-spacing: .09em;
  color: var(--ink); font-weight: 700; margin-bottom: .9rem;
}
.lp-footer a { color: var(--muted); text-decoration: none; }
.lp-footer a:hover { color: var(--brand); }
.lp-footer-base {
  border-top: 1px solid var(--line); padding: 1.1rem 0;
  display: flex; flex-wrap: wrap; gap: .5rem; justify-content: space-between;
  font-size: .83rem; color: var(--muted);
}
.lp-feature {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 25px; height: 100%;
  box-shadow: var(--shadow-xs); transition: transform .2s, box-shadow .2s;
}
.lp-feature:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
.lp-step {
  width: 3.125rem; height: 3.125rem; border-radius: 14px; display: flex;
  align-items: center; justify-content: center; font-size: 1.3125rem; color:#fff; margin-bottom: 14px;
}
.lp-price {
  background: var(--surface); border: 2px solid var(--line);
  border-radius: 18px; padding: 28px; height: 100%; position: relative;
  transition: transform .2s, border-color .2s, box-shadow .2s;
}
.lp-price:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.lp-price.featured { border-color: var(--brand); box-shadow: var(--shadow); }
.lp-price-badge {
  position: absolute; top: -12px; left: 50%; transform: translateX(-50%);
  background: linear-gradient(135deg, var(--brand), var(--brand-2)); color: #fff;
  font-size: 0.6875rem; font-weight: 700; padding: 4px 14px; border-radius: 20px;
  text-transform: uppercase; letter-spacing: .06em;
}
.lp-price-amount { font-size: 2.4rem; font-weight: 800; letter-spacing: -.03em; }
/* Marks a check-in that staff entered by hand rather than the attendee
   scanning. Deliberately quiet — informative, not an accusation. */
.pc-badge-manual {
  background: var(--brand-soft); color: var(--brand);
  font-size: 0.625rem; font-weight: 700; padding: 2px 7px;
  text-transform: uppercase; letter-spacing: .04em; vertical-align: 1px;
}
[data-theme="dark"] .pc-badge-manual { background: #262c4e; color: #a5b4fc; }

.lp-save-badge {
  background: var(--success); color: #fff; font-size: 0.6875rem; font-weight: 700;
  padding: 2px 8px; vertical-align: 1px;
}

/* ────────────────────── 8. Third-party overrides ──────────────────────── */

/* DataTables 2.x uses dt-* class names, not the legacy dataTables_* ones. */
.dt-container { color: var(--ink-2); }
.dt-container .dt-search input,
.dt-container .dt-length select {
  border: 1px solid var(--line-2); border-radius: 8px; padding: 5px 10px;
  background: var(--surface); color: var(--ink); font-size: 0.8125rem;
}
.dt-container .dt-search input:focus, .dt-container .dt-length select:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 16%, transparent);
}
.dt-container .dt-info, .dt-container .dt-length label, .dt-container .dt-search label {
  color: var(--muted); font-size: 0.7813rem;
}
.page-link { background: var(--surface); border-color: var(--line); color: var(--ink-2); }
.page-link:hover { background: var(--surface-2); color: var(--brand); border-color: var(--line); }
.page-item.active .page-link { background: var(--brand); border-color: var(--brand); color:#fff; }
.page-item.disabled .page-link { background: var(--surface); color: var(--muted); border-color: var(--line); }

/* ── Tom Select ──────────────────────────────────────────────────────────
   An enhanced dropdown has to be indistinguishable from a native one.

   select.js turns a <select> into a search box once it passes twelve options,
   so a single filter row can legitimately hold one of each — on the programme
   page Type has fourteen and became a widget while Pillar has six and stayed
   native. TomSelect copies form-select onto its wrapper, then zeroes that
   padding and re-applies its own inset to .ts-control with different numbers
   (6.36px/12.72px against this file's .55rem/.8rem). The two controls came out
   33px and 43px tall, side by side, in the same row.

   So they are matched here rather than the enhancement being switched off:
   a 225-country list genuinely needs the search, and the answer to two things
   looking different is to make them look the same. */
.ts-wrapper.form-select {
  /* The wrapper carries the border, background and radius it inherited from
     .form-select. What it must NOT keep is TomSelect's own min-height, which
     is what held the box 10px short. */
  padding: 0;
  height: auto;
  min-height: 0;
}
.ts-wrapper.form-select .ts-control {
  /* Exactly the inset .form-control/.form-select use above, so the height
     resolves to the same number by the same arithmetic.
     !important because the vendor sheet is linked AFTER this file and matches
     at the same specificity — without it these lose the cascade on source
     order alone, which is what the first attempt did. */
  padding: .55rem .8rem !important;
  min-height: 0 !important;
  border: 0;
  background: transparent;
  border-radius: inherit;
  font-size: inherit;
  line-height: inherit;
  box-shadow: none;
}
.ts-wrapper.form-select.focus,
.ts-wrapper.form-select .ts-control:focus-within {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 15%, transparent);
}
.ts-control {
  background: var(--surface) !important; border-color: var(--line-2) !important;
  border-radius: var(--radius-sm) !important; color: var(--ink);
}
.ts-dropdown { background: var(--surface); border-color: var(--line); color: var(--ink); }
.ts-dropdown .active { background: var(--brand-soft); color: var(--brand); }

/* Flatpickr */
.flatpickr-calendar { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-lg); }
.flatpickr-months .flatpickr-month, .flatpickr-weekdays, span.flatpickr-weekday {
  background: var(--surface); color: var(--ink); fill: var(--ink);
}
.flatpickr-day { color: var(--ink-2); }
.flatpickr-day:hover { background: var(--surface-2); border-color: var(--surface-2); }
.flatpickr-day.selected { background: var(--brand); border-color: var(--brand); color:#fff; }
.flatpickr-day.prevMonthDay, .flatpickr-day.nextMonthDay, .flatpickr-day.flatpickr-disabled { color: var(--muted); }

/* SweetAlert2 */
.swal2-popup { background: var(--surface) !important; color: var(--ink) !important; border-radius: 16px !important; }
.swal2-title, .swal2-html-container { color: var(--ink) !important; }

/* ─────────────────── 9. Responsive / print / motion ───────────────────── */

@media (max-width: 991.98px) {
  .pc-sidebar {
    position: fixed; left: 0; top: var(--topbar-h);
    transform: translateX(-100%); transition: transform .25s ease;
    box-shadow: var(--shadow-lg);
  }
  .pc-sidebar.open { transform: translateX(0); }
  .pc-main { padding: 18px 15px 40px; }
  .pc-page-title { font-size: 1.25rem; }
}

@media (max-width: 575.98px) {
  body { font-size: 0.875rem; }
  .pc-card-body { padding: 15px; }
  .pc-card-head { padding: 13px 15px; }
  .pc-stat { padding: 14px 15px; gap: 12px; }
  .pc-stat-icon { width: 2.5rem; height: 2.5rem; font-size: 1.0625rem; }
  .pc-stat-value { font-size: 1.25rem; }
  .pc-qr-frame img { width: 168px; height: 168px; }
  .pc-auth-card { padding: 24px 20px; }
  .chart-box { height: 240px; }
}

@media print {
  .pc-topbar, .pc-sidebar, .pc-backdrop, .no-print, .btn { display: none !important; }
  .pc-main { padding: 0; }
  .pc-card { box-shadow: none; border: 1px solid #ccc; break-inside: avoid; }
  body { background: #fff; color: #000; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; transition-duration: .001ms !important;
  }
}
