@font-face { font-family: 'Fraunces'; font-style: normal; font-weight: 100 900; font-display: swap; src: url('/fonts/Fraunces/Fraunces-Variable.woff2') format('woff2'); }
@font-face { font-family: 'Fraunces'; font-style: italic; font-weight: 100 900; font-display: swap; src: url('/fonts/Fraunces/Fraunces-Italic-Variable.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: normal; font-weight: 300 700; font-display: swap; src: url('/fonts/Inter/Inter-Variable.woff2') format('woff2'); }
@font-face { font-family: 'Inter'; font-style: italic; font-weight: 300 700; font-display: swap; src: url('/fonts/Inter/Inter-Italic-Variable.woff2') format('woff2'); }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400 600; font-display: swap; src: url('/fonts/JetBrainsMono/JetBrainsMono-Variable.woff2') format('woff2'); }

/* ============================================================================
   Ogtech RFID Event Experience — design system
   v0.2 · 2026-04-30
   Drop into wwwroot/css/ as `design.css` or split into a Razor partial.
   Ports cleanly to Bootstrap 5 — these tokens override Bootstrap variables
   if you later run the Bootstrap SCSS build (e.g. $primary: var(--midnight)).
   ============================================================================ */

/* ----------------------------------------------------------------------------
   TOKENS
   ---------------------------------------------------------------------------- */
:root {
  /* Brand */
  --midnight:        oklch(0.18 0.02 250);
  --midnight-deeper: oklch(0.13 0.02 250);
  --midnight-2:      oklch(0.22 0.02 250);
  --midnight-3:      oklch(0.28 0.02 250);
  --midnight-4:      oklch(0.36 0.02 250);

  --amber:           oklch(0.78 0.15 70);
  --amber-dim:       oklch(0.66 0.13 65);
  --amber-bright:    oklch(0.86 0.13 75);
  --amber-soft:      oklch(0.78 0.15 70 / 0.18);

  /* Reserved (no VIP in v1) */
  --brass:           oklch(0.82 0.13 85);

  /* TV foreground */
  --cream:           oklch(0.96 0.02 80);
  --cream-mute:      oklch(0.78 0.02 80);
  --cream-faint:     oklch(0.55 0.02 80);

  /* Warm neutrals */
  --ink-0:   oklch(1.00 0 0);
  --ink-50:  oklch(0.985 0.005 80);
  --ink-100: oklch(0.96 0.008 80);
  --ink-150: oklch(0.93 0.01 80);
  --ink-200: oklch(0.89 0.012 80);
  --ink-300: oklch(0.80 0.014 80);
  --ink-400: oklch(0.66 0.016 80);
  --ink-500: oklch(0.52 0.018 80);
  --ink-600: oklch(0.40 0.018 80);
  --ink-700: oklch(0.30 0.018 80);
  --ink-800: oklch(0.22 0.016 80);
  --ink-900: oklch(0.13 0.012 80);

  /* Status */
  --success:    oklch(0.62 0.13 155);
  --success-bg: oklch(0.95 0.04 155);
  --warning:    oklch(0.66 0.14 65);
  --warning-bg: oklch(0.96 0.05 75);
  --danger:     oklch(0.58 0.18 25);
  --danger-bg:  oklch(0.95 0.04 25);
  --info:       oklch(0.58 0.10 230);
  --info-bg:    oklch(0.95 0.025 230);

  /* Type */
  --ff-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --ff-sans:    'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --ff-mono:    'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --ff-rtl:     'Noto Naskh Arabic', var(--ff-display);

  --fs-12: 0.75rem;   --fs-13: 0.8125rem; --fs-14: 0.875rem;
  --fs-15: 0.9375rem; --fs-16: 1rem;      --fs-18: 1.125rem;
  --fs-20: 1.25rem;   --fs-24: 1.5rem;    --fs-28: 1.75rem;
  --fs-32: 2rem;      --fs-40: 2.5rem;

  --r-xs: 4px; --r-sm: 6px; --r-md: 10px; --r-lg: 16px; --r-xl: 24px;

  --sh-sm: 0 1px 2px oklch(0.18 0.02 250 / 0.06), 0 2px 6px oklch(0.18 0.02 250 / 0.04);
  --sh-md: 0 4px 14px oklch(0.18 0.02 250 / 0.08), 0 2px 4px oklch(0.18 0.02 250 / 0.04);
  --sh-lg: 0 28px 64px oklch(0.18 0.02 250 / 0.16);

  --ease-out:    cubic-bezier(.2, .65, .25, 1);
  --ease-in-out: cubic-bezier(.4, 0, .2, 1);
  --t-fast: 150ms; --t-med: 300ms; --t-slow: 1200ms;
  --t-tv:   700ms;
}

/* ----------------------------------------------------------------------------
   RESET
   ---------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--ff-sans);
  font-size: var(--fs-15);
  line-height: 1.55;
  color: var(--ink-800);
  background: var(--ink-100);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, h5 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }
p, ul, ol { margin: 0; }
ul { padding: 0; list-style: none; }
button { font: inherit; cursor: pointer; }
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
code, .mono { font-family: var(--ff-mono); }
.tnum { font-feature-settings: 'tnum' 1; }
.eyebrow {
  font-size: var(--fs-12); text-transform: uppercase;
  letter-spacing: 0.16em; color: var(--ink-500); font-weight: 500;
}

/* ----------------------------------------------------------------------------
   SCREEN ROOT MODES
   Set on <body> per file. Locks viewport, picks bg + fg.
   ---------------------------------------------------------------------------- */
body.screen          { min-height: 100vh; min-height: 100dvh; overflow: hidden; }
body.screen--tv      { background: var(--midnight-deeper); color: var(--cream); position: relative; }
body.screen--admin   { background: var(--ink-100); color: var(--ink-800); overflow: auto; }
body.screen--worker  { background: var(--ink-100); color: var(--ink-800); overflow: auto; }

/* ----------------------------------------------------------------------------
   COMPONENT PRIMITIVES
   ---------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px;
  font-size: var(--fs-13); font-weight: 600;
  background: var(--midnight); color: var(--cream);
  border: 1px solid var(--midnight);
  border-radius: var(--r-sm);
  transition: background var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
  box-shadow: var(--sh-sm);
}
.btn:hover    { background: var(--midnight-2); }
.btn:active   { transform: translateY(1px); }
.btn:focus-visible { outline: 3px solid var(--amber-soft); outline-offset: 2px; }
.btn--secondary { background: var(--ink-0); color: var(--ink-800); border-color: var(--ink-300); }
.btn--secondary:hover { background: var(--ink-100); }
.btn--ghost     { background: transparent; color: var(--ink-700); border-color: transparent; box-shadow: none; }
.btn--ghost:hover { background: var(--ink-150); }
.btn--accent    { background: var(--amber); color: var(--midnight); border-color: var(--amber); }
.btn--accent:hover { background: var(--amber-bright); }
.btn--danger    { background: var(--ink-0); color: var(--danger); border-color: var(--ink-300); }
.btn--danger:hover { background: var(--danger-bg); }
.btn--lg { padding: 12px 20px; font-size: var(--fs-15); border-radius: var(--r-md); }
.btn--xl { padding: 18px 28px; font-size: var(--fs-18); border-radius: var(--r-lg); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; box-shadow: none; }

.field { display: flex; flex-direction: column; gap: 4px; }
.field label { font-size: var(--fs-13); color: var(--ink-700); font-weight: 500; }
.field .req { color: var(--amber-dim); margin-inline-start: 2px; }
.field .help { font-size: var(--fs-12); color: var(--ink-500); margin-top: 2px; }
.input {
  appearance: none; width: 100%;
  padding: 8px 12px;
  font: inherit; font-size: var(--fs-14);
  background: var(--ink-0); color: var(--ink-900);
  border: 1px solid var(--ink-300); border-radius: var(--r-sm);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.input::placeholder { color: var(--ink-400); }
.input:focus { outline: none; border-color: var(--midnight-3); box-shadow: 0 0 0 3px oklch(0.18 0.02 250 / 0.10); }
.field.is-error .input { border-color: var(--danger); box-shadow: 0 0 0 3px oklch(0.58 0.18 25 / 0.12); }
.field.is-error .help { color: var(--danger); }

.input--xl  { padding: 18px 18px; font-size: var(--fs-20); border-radius: var(--r-md); }
.field--xl label { font-size: var(--fs-15); }

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; font-size: 11px; font-weight: 600;
  border-radius: 999px; letter-spacing: 0.02em;
  background: var(--ink-150); color: var(--ink-700);
}
.badge--success { background: var(--success-bg); color: var(--success); }
.badge--warning { background: var(--warning-bg); color: var(--warning); }
.badge--danger  { background: var(--danger-bg);  color: var(--danger); }
.badge--info    { background: var(--info-bg);    color: var(--info); }
.badge--mono    { font-family: var(--ff-mono); font-weight: 500; letter-spacing: 0; }

.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.dot--live { color: var(--success); animation: pulse 1.6s var(--ease-out) infinite; }
.dot--idle { color: var(--ink-400); }
.dot--off  { color: var(--danger); }
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 oklch(0.62 0.13 155 / 0.45); }
  50%      { box-shadow: 0 0 0 6px oklch(0.62 0.13 155 / 0); }
}

/* ----------------------------------------------------------------------------
   LOGO LOCKUP
   ---------------------------------------------------------------------------- */
.og-lockup { display: inline-flex; align-items: center; gap: 10px; }
.og-lockup .og-mark { width: 40px; height: 40px; }
.og-lockup .og-word { font-family: var(--ff-sans); font-weight: 700; font-size: 20px; letter-spacing: -0.03em; color: currentColor; }
.og-lockup--lg .og-mark { width: 56px; height: 56px; }
.og-lockup--lg .og-word { font-size: 28px; }
.og-lockup--xl .og-mark { width: 72px; height: 72px; }
.og-lockup--xl .og-word { font-size: 36px; }
.og-mark { display: grid; place-items: center; border-radius: 8px; background: var(--midnight); color: var(--amber); }
.og-mark--inverse { background: var(--amber); color: var(--midnight); }
.og-mark--ghost   { background: transparent; color: currentColor; box-shadow: 0 0 0 1.5px currentColor inset; }
.og-mark svg { width: 70%; height: 70%; }

/* ----------------------------------------------------------------------------
   ADMIN CHROME
   ---------------------------------------------------------------------------- */
.admin {
  width: 100%; min-height: 100vh; min-height: 100dvh;
  display: grid; grid-template-columns: 220px 1fr;
  background: var(--ink-100);
  font-size: var(--fs-14); color: var(--ink-800);
}
.admin .sidebar {
  background: var(--midnight); color: var(--cream-mute);
  display: flex; flex-direction: column;
  padding: 20px 14px;
  position: sticky; top: 0;
  height: 100vh; height: 100dvh;
  overflow-y: auto;
}
.admin .sidebar .brand {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 8px 18px;
  border-bottom: 1px solid oklch(1 0 0 / 0.06);
  margin-bottom: 14px;
}
.admin .sidebar .brand .word { font-weight: 700; color: var(--cream); letter-spacing: -0.02em; font-size: var(--fs-16); }
.admin .sidebar .nav { display: flex; flex-direction: column; gap: 2px; }
.admin .sidebar .nav .group { font-size: 11px; text-transform: uppercase; letter-spacing: 0.14em; color: oklch(0.6 0.02 80); padding: 14px 10px 6px; }
.admin .sidebar .nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: var(--r-sm);
  font-size: var(--fs-13); color: var(--cream-mute); font-weight: 500;
}
.admin .sidebar .nav a.is-active { background: oklch(1 0 0 / 0.08); color: var(--cream); position: relative; }
.admin .sidebar .nav a.is-active::before {
  content: ''; position: absolute; inset-inline-start: -14px; top: 6px; bottom: 6px;
  width: 3px; background: var(--amber); border-radius: 0 2px 2px 0;
}
.admin .sidebar .nav a:hover:not(.is-active) { background: oklch(1 0 0 / 0.04); color: var(--cream); }
.admin .sidebar .nav .ico { width: 16px; height: 16px; opacity: 0.7; }
.admin .sidebar .me {
  margin-top: auto; padding: 12px 10px;
  display: flex; align-items: center; gap: 10px;
  border-top: 1px solid oklch(1 0 0 / 0.06);
}
.admin .sidebar .me .av {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--amber); color: var(--midnight);
  display: grid; place-items: center; font-weight: 700; font-size: var(--fs-12);
}
.admin .sidebar .me .who { line-height: 1.2; }
.admin .sidebar .me .who .n { color: var(--cream); font-size: var(--fs-13); font-weight: 500; }
.admin .sidebar .me .who .r { color: oklch(0.6 0.02 80); font-size: 11px; }

.admin .main { display: flex; flex-direction: column; min-width: 0; }
.admin .topbar {
  background: var(--ink-0); border-bottom: 1px solid var(--ink-200);
  padding: 12px 24px;
  display: flex; align-items: center; gap: 16px;
}
.admin .topbar .crumb   { color: var(--ink-500); font-size: var(--fs-13); }
.admin .topbar .crumb b { color: var(--ink-900); font-weight: 600; }
.admin .topbar .search {
  margin-inline-start: auto; flex-shrink: 0;
  display: flex; align-items: center; gap: 6px;
  background: var(--ink-100); border-radius: var(--r-sm);
  padding: 6px 10px; font-size: var(--fs-13); color: var(--ink-600);
  width: 240px;
}
.admin .topbar .clock { font-family: var(--ff-mono); font-size: var(--fs-13); color: var(--ink-500); }

.admin .content { padding: 22px 24px; flex: 1; }
.admin .page-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.admin .page-head h1 { font-size: var(--fs-24); letter-spacing: -0.02em; color: var(--ink-900); }
.admin .page-head .actions { display: flex; gap: 8px; }

.card {
  background: var(--ink-0); border-radius: var(--r-md);
  border: 1px solid var(--ink-200); box-shadow: var(--sh-sm);
}
.card .hd { padding: 12px 16px; border-bottom: 1px solid var(--ink-200); display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.card .hd h3 { font-size: var(--fs-14); color: var(--ink-900); }
.card .bd { padding: 14px 16px; }

.kpi {
  background: var(--ink-0); border: 1px solid var(--ink-200); border-radius: var(--r-md);
  padding: 14px 16px; box-shadow: var(--sh-sm); position: relative;
  display: flex; flex-direction: column; gap: 6px;
}
.kpi .l { font-size: var(--fs-12); color: var(--ink-500); text-transform: uppercase; letter-spacing: 0.1em; }
.kpi .v {
  font-family: var(--ff-sans); font-weight: 600;
  font-size: var(--fs-32); letter-spacing: -0.025em; color: var(--ink-900);
  font-feature-settings: 'tnum' 1; line-height: 1;
}
.kpi .d  { font-size: var(--fs-12); color: var(--ink-500); display: flex; align-items: center; gap: 6px; }
.kpi .d.up { color: var(--success); }
.kpi .accent-bar { position: absolute; top: 0; inset-inline-start: 14px; right: 14px; height: 2px; background: var(--amber); border-radius: 2px; opacity: 0.4; }
.kpi--accent .accent-bar { opacity: 1; }

.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
.tbl th { text-align: start; font-weight: 500; color: var(--ink-500); padding: 8px 12px; border-bottom: 1px solid var(--ink-200); font-size: var(--fs-12); text-transform: uppercase; letter-spacing: 0.06em; }
.tbl td { padding: 10px 12px; border-bottom: 1px solid var(--ink-150); color: var(--ink-800); vertical-align: middle; }
.tbl tr:hover td { background: var(--ink-50); }
.tbl .num { font-family: var(--ff-mono); font-feature-settings: 'tnum' 1; }

/* ----------------------------------------------------------------------------
   GATE WORKER CHROME
   ---------------------------------------------------------------------------- */
.worker { width: 100%; min-height: 100vh; min-height: 100dvh; background: var(--ink-100); display: flex; flex-direction: column; }
.worker .topbar {
  background: var(--midnight); color: var(--cream);
  padding: 16px 24px;
  display: flex; align-items: center; gap: 16px;
}
.worker .topbar .word { font-weight: 700; letter-spacing: -0.02em; font-size: var(--fs-18); }
.worker .topbar .where { font-size: var(--fs-13); color: var(--cream-mute); margin-inline-start: 6px; }
.worker .topbar .me { margin-inline-start: auto; font-size: var(--fs-13); color: var(--cream-mute); display: flex; align-items: center; gap: 10px; }
.worker .topbar .me .av { width: 28px; height: 28px; border-radius: 50%; background: var(--amber); color: var(--midnight); display: grid; place-items: center; font-weight: 700; font-size: var(--fs-12); }

/* ----------------------------------------------------------------------------
   TV CHROME — used by all Package A files
   ---------------------------------------------------------------------------- */
.tv {
  position: fixed; inset: 0;
  font-family: var(--ff-sans);
  color: var(--cream);
  background:
    url('/img/tv-bg.jpg') center / cover no-repeat,
    var(--midnight-deeper);
  container-type: inline-size;
}
.tv-corner { position: absolute; padding: 36px 48px; font-size: 18px; }
.tv-corner--tl { top: 0; inset-inline-start: 0; }
.tv-corner--tr { top: 0; inset-inline-end: 0; }
.tv-corner--bl { bottom: 0; inset-inline-start: 0; }
.tv-corner--br { bottom: 0; inset-inline-end: 0; }
.tv-corner .where {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 13px; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--cream-mute);
}
.tv-corner .clock { font-family: var(--ff-mono); font-feature-settings: 'tnum' 1; font-size: 13px; color: var(--cream-mute); letter-spacing: 0.05em; }
.tv-corner .event { font-size: 12px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--cream-faint); }

/* RFID-wave concentric arcs from bottom-start corner */
.tv-pattern {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    radial-gradient(circle at -10% 110%, transparent 280px, oklch(0.78 0.15 70 / 0.05) 281px, oklch(0.78 0.15 70 / 0.05) 282px, transparent 283px),
    radial-gradient(circle at -10% 110%, transparent 380px, oklch(0.78 0.15 70 / 0.05) 381px, oklch(0.78 0.15 70 / 0.05) 382px, transparent 383px),
    radial-gradient(circle at -10% 110%, transparent 480px, oklch(0.78 0.15 70 / 0.04) 481px, oklch(0.78 0.15 70 / 0.04) 482px, transparent 483px),
    radial-gradient(circle at -10% 110%, transparent 580px, oklch(0.78 0.15 70 / 0.04) 581px, oklch(0.78 0.15 70 / 0.04) 582px, transparent 583px),
    radial-gradient(circle at -10% 110%, transparent 680px, oklch(0.78 0.15 70 / 0.03) 681px, oklch(0.78 0.15 70 / 0.03) 682px, transparent 683px),
    radial-gradient(circle at -10% 110%, transparent 780px, oklch(0.78 0.15 70 / 0.03) 781px, oklch(0.78 0.15 70 / 0.03) 782px, transparent 783px),
    radial-gradient(circle at -10% 110%, transparent 880px, oklch(0.78 0.15 70 / 0.02) 881px, oklch(0.78 0.15 70 / 0.02) 882px, transparent 883px);
}
.tv-pattern--mirror { transform: scaleX(-1); }

/* Decorative anniversary/event mark — sits in-flow at the end of the
   active or idle content block, directly below the closing line.
   Sized via clamp + cqw so multi-guest layouts still fit on TV. */
.tv-mark {
  display: block;
  margin: clamp(24px, 3cqw, 64px) auto 0;
  width: clamp(180px, 22cqw, 420px);
  height: auto;
  max-height: 18cqh;
  object-fit: contain;
  pointer-events: none;
}
/* When 3+ guests are showing, shrink the mark so vertical centring
   keeps the whole block on screen at any TV size. */
.tv-content:has(.tv-names[data-count="3"]) .tv-mark,
.tv-content:has(.tv-names[data-count="4"]) .tv-mark {
  margin-top: clamp(16px, 2cqw, 40px);
  width: clamp(140px, 16cqw, 300px);
}

.tv-stage {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  padding: 80px;
}

/* Welcome typography — viewport-relative for TV preview at any size */
.tv-eyebrow {
  font-size: clamp(28px, 2.2cqw, 48px);
  font-weight: 900;
  letter-spacing: 0;
  color: red;
  margin-bottom: 28px;
}
.tv-name {
  font-family: var(--ff-display);
  font-variation-settings: 'opsz' 144, 'SOFT' 80, 'wght' 500;
  font-size: clamp(64px, 8cqw, 160px);
  line-height: 0.96;
  letter-spacing: -0.02em;
  color: var(--cream);
}
.tv-name em {
  font-style: italic;
  font-variation-settings: 'opsz' 144, 'SOFT' 100, 'wght' 400;
  color: var(--amber-bright);
}
.tv-accent-bar { width: 120px; height: 3px; background: red; border-radius: 2px; margin: 32px auto 0; }
.tv-sub {
  margin-top: 28px;
  font-size: clamp(16px, 1.4cqw, 28px);
  color: var(--cream-mute);
  letter-spacing: 0.04em;
  max-width: 65%;
  line-height: 1.4;
}

/* Welcome idle */
.tv-idle {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 80px; text-align: center;
}
.tv-idle .ev-name {
  font-family: var(--ff-display);
  font-variation-settings: 'opsz' 144, 'SOFT' 60, 'wght' 400;
  font-size: clamp(48px, 5.5cqw, 96px);
  line-height: 1; color: var(--cream-mute); letter-spacing: -0.02em;
}
.tv-idle .ev-tag {
  margin-top: 20px;
  font-size: clamp(14px, 1.2cqw, 22px);
  color: var(--cream-faint); letter-spacing: 0.16em; text-transform: uppercase;
}
.tv-idle .tv-idle__logos {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 3cqw, 48px);
}
.tv-idle .tv-idle__logo {
  width: clamp(180px, 20cqw, 350px);
  height: auto;
}
.tv-idle .tv-idle__mark {
  width: clamp(140px, 16cqw, 280px);
  height: auto;
}
.tv-idle .tv-idle__line {
  width: clamp(120px, 14cqw, 240px);
  height: 2px;
  background: red;
  border-radius: 2px;
  margin: clamp(24px, 3cqw, 48px) auto;
}
.tv-idle .tv-idle__tagline {
  font-family: var(--ff-display);
  font-variation-settings: 'opsz' 96, 'SOFT' 60, 'wght' 400;
  font-size: clamp(20px, 2.2cqw, 40px);
  color: var(--ink-0);
  letter-spacing: 0.06em;
  text-align: center;
  line-height: 1.3;
}
.tv-idle .ev-pulse {
  margin-top: 36px;
  font-size: 14px; letter-spacing: 0.4em; text-transform: uppercase;
  color: red; display: inline-flex; align-items: center; gap: 12px;
}
.tv-idle .ev-pulse::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%;
  background: red; animation: tvpulse 2.4s var(--ease-out) infinite;
}
@keyframes tvpulse {
  0%, 100% { box-shadow: 0 0 0 0 oklch(0.78 0.15 70 / 0.5); transform: scale(1); }
  50%      { box-shadow: 0 0 0 10px oklch(0.78 0.15 70 / 0); transform: scale(1.15); }
}

/* Welcome state machine — drives the live SignalR-fed screen.
   Eyebrow, accent bar, and footer slogan are persistent singletons.
   Only the guest names stack/animate as tags arrive and expire. */
.tv-stage--demo .tv-content {
  display: flex; flex-direction: column; align-items: center;
  width: 100%;
}
.tv-stage--demo.is-idle .tv-content { display: none; }
.tv-stage--demo .tv-idle { display: none; opacity: 0; transition: opacity var(--t-tv) var(--ease-out); }
.tv-stage--demo.is-idle .tv-idle { display: flex; opacity: 1; }

/* Vertical stack of names — older arrivals on top, newest at the bottom.
   When the older one's hold expires, it collapses up and the rest reflow. */
.tv-names {
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(8px, 1cqw, 24px);
  width: 100%;
}
.tv-guest-name {
  font-family: var(--ff-display);
  font-variation-settings: 'opsz' 144, 'SOFT' 80, 'wght' 500;
  letter-spacing: -0.02em;
  line-height: 0.96;
  color: #fff;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  padding-inline: 0.12em;
  transition:
    opacity var(--t-tv) var(--ease-out),
    transform var(--t-tv) var(--ease-out),
    font-size var(--t-tv) var(--ease-out),
    margin var(--t-tv) var(--ease-out);
}
.tv-guest-name em {
  font-style: italic;
  font-variation-settings: 'opsz' 144, 'SOFT' 100, 'wght' 400;
  color: #fff;
}
/* Entering: name starts collapsed at height 0 (others stay put), then
   grows + fades in as `is-entering` is removed on the next frame. */
.tv-guest-name.is-entering {
  opacity: 0;
  transform: translateY(18px);
  font-size: 0 !important;
  margin: 0 !important;
}
/* Leaving: name collapses to height 0 and drifts upward, so its row
   smoothly disappears while neighbours grow back to the new count size. */
.tv-guest-name.is-leaving {
  opacity: 0;
  transform: translateY(-16px);
  font-size: 0 !important;
  margin: 0 !important;
}

/* Count-based scaling. 1 = hero, 2 = balanced pair, 3+ = compact stack
   that still keeps each name legible at 1920x1080. */
.tv-names[data-count="1"] .tv-guest-name { font-size: clamp(64px, 8cqw, 160px); }
.tv-names[data-count="2"] .tv-guest-name { font-size: clamp(52px, 6cqw, 128px); }
.tv-names[data-count="3"] .tv-guest-name { font-size: clamp(40px, 4.6cqw, 96px); }
.tv-names[data-count="4"] .tv-guest-name { font-size: clamp(32px, 3.6cqw, 76px); }

/* In-Hall TV */
.tv-inhall .tv-pattern {
    background-color: var(--midnight-deeper);
    background-image:
        linear-gradient(oklch(0.13 0.02 250 / 0.45), oklch(0.13 0.02 250 / 0.45)),
        url('/img/inhall-bg.jpg');
    background-size: 100% 100%;
    background-position: center center;
    background-repeat: no-repeat;
}
.tv-inhall .tv-stage { padding: clamp(60px, 6cqw, 120px); align-items: stretch; }
.tv-inhall.with-image .tv-stage {
  display: grid; grid-template-columns: 1fr 1.2fr; gap: clamp(32px, 3cqw, 64px);
  text-align: start; align-items: center;
}

/* In-hall crossfade: the idle view and the message stage are stacked,
   absolutely-positioned layers. Exactly one is lit at a time; the client
   JS toggles `is-hidden` to fade between them. The duration here MUST stay
   in sync with FADE_IH in rfid-screen-client.js, otherwise the JS hold
   timers and the visual fade drift apart. */
.tv-inhall .tv-stage,
.tv-inhall .tv-idle {
  transition: opacity var(--t-tv) var(--ease-out);
}
.tv-inhall .tv-stage.is-hidden,
.tv-inhall .tv-idle.is-hidden {
  opacity: 0;
}
.tv-inhall .ih-greeting {
  font-family: var(--ff-display);
  font-variation-settings: 'opsz' 144, 'SOFT' 80, 'wght' 500;
  font-size: clamp(40px, 3.8cqw, 72px); line-height: 1.1; letter-spacing: -0.01em;
  color: var(--cream); margin-bottom: 14px;
}
.tv-inhall .ih-kicker {
  font-size: clamp(14px, 1cqw, 18px); letter-spacing: 0.4em; text-transform: uppercase;
  color: var(--amber); margin-bottom: 32px; display: inline-flex; align-items: center; gap: 16px;
}
.tv-inhall .ih-kicker::before { content: ''; width: 36px; height: 1.5px; background: var(--amber); }
.tv-inhall .ih-body {
  margin-top: 32px;
  font-size: clamp(18px, 1.8cqw, 32px); line-height: 1.5; color: var(--cream-mute);
  font-weight: 300;
}
.tv-inhall .ih-body strong { color: var(--cream); font-weight: 600; }
.tv-inhall .ih-image {
  border-radius: 18px; overflow: hidden;
  background: linear-gradient(135deg, oklch(0.36 0.05 250) 0%, oklch(0.22 0.03 250) 100%);
  height: 100%;
  position: relative;
  display: grid; place-items: center;
}
.tv-inhall .ih-image::after {
  content: ''; position: absolute; inset: 0;
  background:
    radial-gradient(circle at 70% 30%, oklch(0.78 0.15 70 / 0.25) 0%, transparent 50%),
    repeating-linear-gradient(45deg, transparent 0 20px, oklch(0.78 0.15 70 / 0.05) 20px 21px);
}
.tv-inhall .ih-image video {
  width: 100%; height: 100%; object-fit: contain;
  display: block; position: relative; z-index: 1;
  border-radius: inherit; background: #000;
}
.tv-inhall .ih-image:has(video)::after { display: none; }

/* Photo grid (1–4 photos) — count-aware layout, staggered fade-in */
.tv-inhall .ih-photos {
  width: 100%; height: 100%; display: grid; gap: clamp(8px, 0.8cqw, 14px);
  position: relative; z-index: 1;
}
.tv-inhall .ih-photos--n1 { grid-template-columns: 1fr; grid-template-rows: 1fr; }
.tv-inhall .ih-photos--n2 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr; }
.tv-inhall .ih-photos--n3 {
  grid-template-columns: 1.4fr 1fr;
  grid-template-rows: 1fr 1fr;
}
.tv-inhall .ih-photos--n3 .ih-photo:nth-child(1) { grid-row: 1 / span 2; }
.tv-inhall .ih-photos--n4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.tv-inhall .ih-photo {
  position: relative; overflow: hidden;
  border-radius: 14px;
  background: oklch(0.18 0.02 250);
  box-shadow:
    0 18px 40px -22px oklch(0 0 0 / 0.65),
    inset 0 0 0 1px oklch(1 0 0 / 0.06);
  animation: ih-photo-in 700ms var(--ease-out) both;
}
.tv-inhall .ih-photo::before,
.tv-inhall .ih-photo::after {
  content: ''; position: absolute; inset: 0;
  background-image: var(--ih-src);
  background-repeat: no-repeat; background-position: center;
}
.tv-inhall .ih-photo::before {
  background-size: cover;
  filter: blur(28px) saturate(1.15) brightness(0.85);
  transform: scale(1.15);
  z-index: 0;
}
.tv-inhall .ih-photo::after {
  background-size: contain;
  z-index: 1;
}
.tv-inhall .ih-photos--n1 .ih-photo { border-radius: 18px; }
.tv-inhall .ih-photo:nth-child(2) { animation-delay: 90ms; }
.tv-inhall .ih-photo:nth-child(3) { animation-delay: 180ms; }
.tv-inhall .ih-photo:nth-child(4) { animation-delay: 270ms; }
.tv-inhall .ih-image:has(.ih-photos)::after { display: none; }
.tv-inhall .ih-image:has(.ih-photos) {
  background: transparent;
  padding: 0;
}
@keyframes ih-photo-in {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

/* Connection-lost overlay (added by JS over any TV state) */
.tv-conn {
  position: absolute; inset: 0; pointer-events: none; z-index: 10;
  background: oklch(0.13 0.02 250 / 0.85);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 120px;
  opacity: 0; transition: opacity var(--t-tv) var(--ease-out);
}
.tv-conn.is-shown { opacity: 1; }
.tv-conn .tag {
  display: inline-flex; align-items: center; gap: 14px;
  font-size: 16px; letter-spacing: 0.32em; text-transform: uppercase;
  color: var(--amber); margin-bottom: 24px;
}
.tv-conn .tag::before { content: ''; width: 10px; height: 10px; border-radius: 50%; background: var(--amber); animation: tvpulse 2.4s var(--ease-out) infinite; }
.tv-conn .msg {
  font-family: var(--ff-display);
  font-variation-settings: 'opsz' 96, 'SOFT' 60, 'wght' 400;
  font-size: clamp(40px, 4cqw, 72px); line-height: 1.15; color: var(--cream); letter-spacing: -0.015em;
  max-width: 70%;
}
.tv-conn .sub { margin-top: 18px; font-size: 18px; color: var(--cream-faint); }

/* ----------------------------------------------------------------------------
   AUTH PAGES (B1 admin / C1 worker share this template)
   ---------------------------------------------------------------------------- */
.auth { display: grid; grid-template-columns: 1fr 1fr; min-height: 100vh; min-height: 100dvh; background: var(--midnight); }
.auth__brand {
  padding: 64px; display: flex; flex-direction: column; justify-content: space-between;
  color: var(--cream); position: relative; overflow: hidden;
}
.auth__brand .tv-pattern { opacity: 0.5; }
.auth__brand .headline {
  font-family: var(--ff-display); font-size: clamp(48px, 5vw, 72px);
  line-height: 1.05; letter-spacing: -0.02em;
  font-variation-settings: 'opsz' 96, 'SOFT' 60, 'wght' 500;
  color: var(--cream); position: relative;
}
.auth__brand .headline em { color: var(--amber); font-style: italic; font-variation-settings: 'opsz' 96, 'SOFT' 100, 'wght' 400; }
.auth__brand .tagline { margin-top: 18px; color: var(--cream-mute); font-size: 16px; position: relative; }
.auth__brand .footnote { position: relative; font-family: var(--ff-mono); font-size: 12px; color: var(--cream-faint); }
.auth__form { background: var(--ink-50); padding: 64px; display: flex; flex-direction: column; justify-content: center; }
.auth__form h1 { font-size: 28px; color: var(--ink-900); margin-bottom: 8px; }
.auth__form p.lede { color: var(--ink-500); margin-bottom: 28px; font-size: 14px; }

/* Worker auth bumps everything up */
.auth--worker .auth__form h1 { font-size: 32px; margin-bottom: 24px; }
.auth--worker .auth__brand .headline { font-size: clamp(56px, 6vw, 80px); }

/* ----------------------------------------------------------------------------
   PORTING NOTES
   ============================================================================
   In Razor:
   - `<body class="screen screen--admin">` etc.
   - `_Layout.cshtml` per surface (TV / Admin / Worker).
   - This file = `wwwroot/css/design.css` linked in each layout.
   - Bootstrap 5: include after this file; the few utilities used (grid, flex,
     gap) work directly. Override `$primary` / `$accent` to point at the tokens
     above so any Bootstrap component you add inherits the brand.
   - Container queries (`cqw`) are used heavily on the TV surface so previews
     at any size scale typography correctly. Requires browsers from 2023+ — fine
     for kiosked TVs running Edge/Chromium.
   ============================================================================ */
