/* ==========================================================
   JU Passport — Design System
   Mobile-first app UI for the Jönköping University Kick-Off
   ========================================================== */

:root {
  /* Brand */
  --ju-navy: #002b49;
  --blue-600: #1a68cf;
  --blue-500: #2f88f7;
  --blue-400: #6aabff;
  --amber-500: #efb129;
  --amber-400: #ffca55;
  --green-500: #10b981;
  --green-400: #34d399;
  --red-500: #f04438;

  /* Surfaces */
  --bg: #080c12;
  --surface: #111a24;
  --surface-2: #17222e;
  --surface-3: #1f2c3a;
  --line: rgba(255, 255, 255, 0.07);
  --line-strong: rgba(255, 255, 255, 0.14);

  /* Text */
  --text: #edf2f8;
  --text-2: #9fadbe;
  --text-3: #64758a;

  /* Passport paper */
  --paper: #f7f4ec;
  --paper-2: #ece5d6;
  --paper-line: #d5cdba;
  --paper-ink: #2c3542;

  /* School accents */
  --school-HLK: #e6485c;
  --school-JIBS: #4a8fd8;
  --school-JTH: #2ba98f;
  --school-HHJ: #e8a33d;
  --school-OTHER: #9575e6;

  /* Radii */
  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 16px;
  --r-lg: 20px;
  --r-xl: 26px;
  --r-full: 999px;

  /* Elevation */
  --sh-1: 0 1px 2px rgba(0, 0, 0, 0.45);
  --sh-2: 0 10px 24px -10px rgba(0, 0, 0, 0.65);
  --sh-3: 0 28px 56px -20px rgba(0, 0, 0, 0.8);

  /* Motion */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --spring: cubic-bezier(0.34, 1.38, 0.64, 1);

  /* Layout */
  --app-w: 440px;
  --nav-h: 60px;
  --bar-h: 54px;
  --gutter: 16px;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);

  --font-ui: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-display: 'Outfit', -apple-system, BlinkMacSystemFont, sans-serif;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}

html {
  height: 100%;
  -webkit-text-size-adjust: 100%;
}

body {
  min-height: 100%;
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.45;
  color: var(--text);
  background: var(--bg);
  overflow-x: hidden;
  overscroll-behavior-y: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body::before {
  /* Ambient light — painted once, never scrolls (no repaint cost on mobile) */
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(120% 60% at 50% -10%, rgba(47, 136, 247, 0.16) 0%, transparent 60%),
    radial-gradient(90% 50% at 110% 100%, rgba(239, 177, 41, 0.07) 0%, transparent 55%);
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
  touch-action: manipulation;
}

a {
  color: inherit;
  text-decoration: none;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

/* Chrome (bars, labels, buttons) shouldn't feel like a web page */
.app-bar,
.tab-bar,
.seg,
.chip,
.eyebrow,
.tab {
  -webkit-user-select: none;
  user-select: none;
}

/* ==========================================================
   BOOT SPLASH — hides the in-browser JSX compile flash
   ========================================================== */
#boot {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 24px calc(40px + var(--safe-b));
  background:
    radial-gradient(120% 70% at 50% 32%, rgba(47, 136, 247, 0.18) 0%, transparent 60%),
    radial-gradient(90% 50% at 50% 100%, rgba(239, 177, 41, 0.08) 0%, transparent 55%),
    var(--bg);
  transition: opacity 0.4s var(--ease), visibility 0.4s;
}

#boot.gone {
  opacity: 0;
  visibility: hidden;
}

/* Brand centred in the viewport, credit pinned near the bottom */
#boot .boot-center {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  animation: bootIn 0.5s var(--ease) both;
}

@keyframes bootIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

#boot .boot-credit {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--text-3);
  animation: bootIn 0.5s var(--ease) 0.15s both;
}

#boot .boot-metadia {
  display: block;
  width: 64px;
  height: 17px;
  background: url("../img/metadia-light.svg") left center / contain no-repeat;
  opacity: 0.72;
}

/* Official Jönköping University artwork, white ("neg") versions for this dark
   UI. Referenced from CSS rather than <img> src so the paths stay correct in a
   subfolder install. ju-symbol is the mark alone, for small square slots;
   ju-logo is the stacked lockup including the wordmark. */
.ju-symbol,
.ju-lockup {
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

.ju-symbol {
  background-image: url("../img/ju-symbol.png");
}

.ju-lockup {
  background-image: url("../img/ju-logo.png");
}

#boot .boot-mark {
  width: 190px;
  height: 86px;
  animation: bootPulse 2s var(--ease) infinite;
}

#boot .boot-name {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
}

@keyframes bootPulse {
  0%, 100% { transform: scale(1); opacity: 0.85; }
  50% { transform: scale(1.06); opacity: 1; }
}

/* ==========================================================
   APP SHELL
   ========================================================== */
.app {
  position: relative;
  z-index: 1;
  max-width: var(--app-w);
  margin: 0 auto;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.app.wide {
  max-width: 1180px;
}

/* Top bar */
.app-bar {
  position: sticky;
  top: 0;
  z-index: 40;
  height: calc(var(--bar-h) + var(--safe-t));
  padding: var(--safe-t) var(--gutter) 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: rgba(8, 12, 18, 0.72);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.brand-mark {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
}

.brand-text {
  min-width: 0;
}

.brand-text strong {
  display: block;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1.15;
  white-space: nowrap;
}

.brand-text span {
  display: block;
  white-space: nowrap;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* Account chip / avatar */
.avatar-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 4px 0 12px;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line);
  font-size: 13px;
  font-weight: 700;
  transition: transform 0.15s var(--ease), background 0.15s var(--ease);
}

.avatar-btn:active {
  transform: scale(0.96);
  background: rgba(255, 255, 255, 0.1);
}

.avatar-btn .name {
  max-width: 90px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.avatar {
  width: 28px;
  height: 28px;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 800;
  color: #06131e;
  background: var(--av-color, var(--blue-400));
}

/* Scrollable screen area */
.screen {
  flex: 1;
  padding: 18px var(--gutter) calc(var(--nav-h) + var(--safe-b) + 28px);
  animation: screenIn 0.28s var(--ease);
}

/* No tab bar on the coordinator route — reclaim the space */
.app.no-nav .screen {
  padding-bottom: calc(var(--safe-b) + 32px);
}

/* ----------------------------------------------------------
   Single-screen passport: the whole booklet has to be visible
   at once, on any phone, with no vertical scrolling. The screen
   claims exactly the space between the bars and every part of
   the passport flexes inside it.
   ---------------------------------------------------------- */
.screen.fit {
  /* flex-basis would win over height on a flex item, and the tab bar is fixed
     (so it claims no flow space) — pin the height explicitly instead */
  flex: 0 0 auto;
  height: calc(100vh - var(--bar-h) - var(--safe-t) - var(--nav-h) - var(--safe-b));
  height: calc(100dvh - var(--bar-h) - var(--safe-t) - var(--nav-h) - var(--safe-b));
  padding-top: 14px;
  padding-bottom: 14px;
  /* Everything is sized to fit, so this never scrolls on a phone in portrait.
     It stays `auto` rather than `hidden` so that a viewport too short for the
     minimums (landscape, split screen) degrades to scrolling instead of
     silently clipping the stamps. */
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}

.passport-view {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1.6dvh, 18px);
}

.passport-view .hero,
.passport-view > .btn {
  flex: 0 0 auto;
}

.passport-view .booklet {
  flex: 1 1 auto;
  min-height: 0;
  margin-top: 0;
  display: flex;
  flex-direction: column;
}

.passport-view .booklet-head {
  flex: 0 0 auto;
}

.passport-view .page {
  flex: 1 1 auto;
  /* The stamps are the point of the screen — never let them be squeezed away */
  min-height: 172px;
  display: flex;
}

.passport-view .stamp-grid {
  flex: 1;
  min-height: 0;
  grid-template-rows: 1fr 1fr;
  align-content: stretch;
}

@keyframes screenIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* ==========================================================
   TYPOGRAPHY HELPERS
   ========================================================== */
.eyebrow {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
}

.screen-head {
  margin-bottom: 16px;
}

.screen-head h2 {
  font-size: 22px;
  font-weight: 800;
}

.screen-head p {
  margin-top: 4px;
  font-size: 13.5px;
  color: var(--text-2);
}

.head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.section-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 22px 2px 10px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-3);
}

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

/* ==========================================================
   CARDS
   ========================================================== */
.card {
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-2);
}

.card-pad {
  padding: 16px;
}

/* ==========================================================
   BUTTONS
   ========================================================== */
.btn {
  min-height: 48px;
  width: 100%;
  padding: 0 18px;
  border-radius: var(--r-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-family: var(--font-display);
  font-size: 15.5px;
  font-weight: 700;
  transition: transform 0.14s var(--spring), opacity 0.15s var(--ease), background 0.15s var(--ease);
}

.btn:active {
  transform: scale(0.975);
}

.btn:disabled {
  opacity: 0.45;
  transform: none;
}

.btn-primary {
  color: #06131e;
  background: linear-gradient(170deg, var(--amber-400), var(--amber-500));
  box-shadow: 0 8px 20px -8px rgba(239, 177, 41, 0.6);
}

.btn-blue {
  color: #fff;
  background: linear-gradient(170deg, var(--blue-500), var(--blue-600));
  box-shadow: 0 8px 20px -8px rgba(47, 136, 247, 0.6);
}

.btn-ghost {
  color: var(--text);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 14.5px;
}

.btn-danger {
  color: #fff;
  background: rgba(240, 68, 56, 0.16);
  border: 1px solid rgba(240, 68, 56, 0.4);
  font-size: 14.5px;
}

/* Small, inline actions */
.chip {
  min-height: 34px;
  padding: 0 12px;
  border-radius: var(--r-full);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-2);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--line);
  transition: transform 0.14s var(--ease), color 0.14s var(--ease);
}

.chip:active {
  transform: scale(0.95);
}

.chip.solid {
  color: #06131e;
  background: var(--amber-400);
  border-color: transparent;
}

.chip.accent {
  color: var(--amber-400);
  background: rgba(239, 177, 41, 0.12);
  border-color: rgba(239, 177, 41, 0.28);
}

/* School tag */
.tag {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 8px;
  border-radius: 6px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: var(--tag-color, var(--text-2));
  background: color-mix(in srgb, var(--tag-color, #888) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--tag-color, #888) 34%, transparent);
}

.tag.HLK { --tag-color: var(--school-HLK); }
.tag.JIBS { --tag-color: var(--school-JIBS); }
.tag.JTH { --tag-color: var(--school-JTH); }
.tag.HHJ { --tag-color: var(--school-HHJ); }
.tag.OTHER { --tag-color: var(--school-OTHER); }
.tag.ok { --tag-color: var(--green-400); }
.tag.gold { --tag-color: var(--amber-400); }

/* ==========================================================
   PROGRESS HERO
   ========================================================== */
.hero {
  padding: 18px;
  border-radius: var(--r-xl);
  background:
    radial-gradient(120% 130% at 100% 0%, rgba(47, 136, 247, 0.16), transparent 60%),
    linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
  box-shadow: var(--sh-2);
}

/* Competition-closed variant: cooler, no blue call-to-action tint */
.hero-closed {
  background:
    radial-gradient(120% 130% at 100% 0%, rgba(159, 173, 190, 0.1), transparent 60%),
    linear-gradient(180deg, var(--surface-2), var(--surface));
  border-color: var(--line-strong);
}

.hero-closed .ring .fill {
  stroke: var(--text-3);
}

/* Closed onboarding screen */
.closed-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  padding: 5px 12px;
  border-radius: var(--r-full);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-2);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line-strong);
}

.closed-welcome h1 {
  margin-top: 12px;
}

/* The credit footer must sit above the tab bar, so the welcome block fills
   the remaining space rather than claiming the full height. */
.closed-flow .slide-welcome {
  flex: 1;
  min-height: 0;
}

.closed-flow .onboard-foot {
  align-items: center;
}

.hero-top {
  display: flex;
  align-items: center;
  gap: 16px;
}

.hero-copy {
  flex: 1;
  min-width: 0;
}

.hero-copy h2 {
  font-size: 19px;
  font-weight: 800;
}

.hero-copy p {
  margin-top: 3px;
  font-size: 13px;
  color: var(--text-2);
}

/* Progress ring */
.ring {
  position: relative;
  width: 78px;
  height: 78px;
  flex-shrink: 0;
}

.ring svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.ring .track {
  stroke: rgba(255, 255, 255, 0.08);
}

.ring .fill {
  stroke: url(#ringGrad);
  stroke-linecap: round;
  transition: stroke-dashoffset 0.9s var(--ease);
}

.ring-label {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.ring-label b {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 800;
}

.ring-label span {
  margin-top: 2px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

.hero-actions {
  margin-top: 16px;
  display: flex;
  gap: 10px;
}

.hero-actions .btn-ghost {
  width: auto;
  flex-shrink: 0;
  padding: 0 16px;
}

/* ==========================================================
   PASSPORT BOOKLET
   ========================================================== */
.booklet {
  margin-top: 18px;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: linear-gradient(180deg, #143050, #0d2038);
  border: 1px solid rgba(255, 255, 255, 0.09);
  box-shadow: var(--sh-3);
}

.booklet-head {
  padding: 14px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.booklet-head .eyebrow {
  color: rgba(255, 202, 85, 0.8);
}

.booklet-head strong {
  display: block;
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  margin-top: 2px;
}

.booklet-id {
  text-align: right;
  white-space: nowrap;
  font-family: 'SFMono-Regular', ui-monospace, monospace;
  font-size: 10.5px;
  color: rgba(255, 255, 255, 0.45);
  letter-spacing: 0.05em;
}

/* Paper page holding the stamps */
.page {
  position: relative;
  padding: 16px 14px 18px;
  background:
    repeating-linear-gradient(90deg, rgba(0, 43, 73, 0.028) 0 1px, transparent 1px 11px),
    repeating-linear-gradient(0deg, rgba(0, 43, 73, 0.022) 0 1px, transparent 1px 13px),
    linear-gradient(180deg, var(--paper) 0%, var(--paper-2) 100%);
}

.page::after {
  /* Machine-readable strip: the detail that sells the passport */
  content: 'P<SWEJU<<KICKOFF<<2026<<CAMPUS<STAMP<VISA<<<<<<<<';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 5px 14px 6px;
  font-family: 'SFMono-Regular', ui-monospace, monospace;
  font-size: 8.5px;
  letter-spacing: 0.08em;
  color: rgba(44, 53, 66, 0.32);
  background: rgba(255, 255, 255, 0.5);
  border-top: 1px solid var(--paper-line);
  white-space: nowrap;
  overflow: hidden;
  pointer-events: none;
}

.stamp-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px 8px;
  padding-bottom: 20px;
}

/* Labels take the space they need; the seal absorbs whatever is left,
   so six slots always fit the page without clipping or scrolling */
.slot {
  display: grid;
  grid-template-rows: 1fr auto auto;
  justify-items: center;
  align-items: center;
  row-gap: clamp(3px, 0.7dvh, 6px);
  min-height: 0;
  background: none;
  border: none;
  padding: 0;
  transition: transform 0.16s var(--spring);
}

.slot:active {
  transform: scale(0.94);
}

.seal {
  position: relative;
  height: 100%;
  width: auto;
  aspect-ratio: 1;
  max-width: 100%;
  max-height: clamp(48px, 12dvh, 120px);
  min-height: 42px;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
}

/* Icon scales with the seal rather than sitting at a fixed 26px */
.seal svg {
  width: 42%;
  height: 42%;
}

/* Locked slot */
.seal.locked {
  border: 1.5px dashed rgba(44, 53, 66, 0.4);
  background: rgba(255, 255, 255, 0.45);
  box-shadow: inset 0 1px 3px rgba(44, 53, 66, 0.06);
}

.seal.locked .slot-num {
  font-family: var(--font-display);
  font-size: clamp(13px, 2dvh, 17px);
  font-weight: 800;
  color: rgba(44, 53, 66, 0.5);
}

/* Unlocked ink seal */
.seal.inked {
  color: var(--ink);
  border: 2px solid currentColor;
  box-shadow: inset 0 0 0 1px currentColor;
  transform: rotate(var(--rot, -4deg));
  opacity: 0.92;
  animation: stampDown 0.45s var(--spring) both;
}

.seal.inked::before {
  content: '';
  position: absolute;
  inset: 5px;
  border-radius: var(--r-full);
  border: 1px solid currentColor;
  opacity: 0.5;
}

@keyframes stampDown {
  0% { transform: scale(2.1) rotate(18deg); opacity: 0; }
  60% { opacity: 0.95; }
  100% { transform: scale(1) rotate(var(--rot, -4deg)); opacity: 0.92; }
}

.slot-name {
  /* Two-line box keeps the timestamps on one baseline across the grid */
  min-height: 2.5em;
  font-size: clamp(9px, 1.3dvh, 10.5px);
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  color: var(--paper-ink);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.slot-meta {
  font-family: 'SFMono-Regular', ui-monospace, monospace;
  font-size: 9px;
  font-weight: 600;
  color: rgba(44, 53, 66, 0.5);
}

/* ==========================================================
   ONBOARDING / FORMS
   ========================================================== */
/* ----------------------------------------------------------
   Paged onboarding: one screenful per step, with the action
   pinned to the bottom instead of buried under a long scroll.
   ---------------------------------------------------------- */
.screen.onboard {
  flex: 0 0 auto;
  height: calc(100vh - var(--bar-h) - var(--safe-t) - var(--nav-h) - var(--safe-b));
  height: calc(100dvh - var(--bar-h) - var(--safe-t) - var(--nav-h) - var(--safe-b));
  padding-top: 10px;
  /* Clear of the tab bar — the primary button sat almost on top of it */
  padding-bottom: 26px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.onboard-flow {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.onboard-top {
  flex: 0 0 auto;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.onboard-top .flip {
  transform: rotate(180deg);
}

/* Only this area scrolls, and only when a step needs it. The bottom edge
   fades out so longer steps read as "more below" rather than cut off. */
.onboard-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding-top: 8px;
  padding-bottom: 20px;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent 100%);
  transition: padding-bottom 0.2s var(--ease);
}

.onboard-body:focus-within {
  -webkit-mask-image: none;
  mask-image: none;
  padding-bottom: 110px;
}

.onboard-body.dir-fwd .slide {
  animation: slideFromRight 0.3s var(--ease);
}

.onboard-body.dir-back .slide {
  animation: slideFromLeft 0.3s var(--ease);
}

@keyframes slideFromRight {
  from { opacity: 0; transform: translateX(22px); }
  to { opacity: 1; transform: none; }
}

@keyframes slideFromLeft {
  from { opacity: 0; transform: translateX(-22px); }
  to { opacity: 1; transform: none; }
}

/* Welcome step is vertically centred; the others start at the top */
.slide-welcome {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-bottom: 20px;
}

.slide-welcome .glyph {
  width: 176px;
  height: 80px;
  margin-bottom: 24px;
}

.slide-welcome .eyebrow {
  color: var(--amber-400);
}

.slide-welcome h1 {
  margin-top: 8px;
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.06;
}

.slide-welcome p {
  margin-top: 14px;
  font-size: 15px;
  line-height: 1.5;
  color: var(--text-2);
  max-width: 34ch;
}

/* Trailing margin would otherwise push a two-field step into scrolling */
.slide form .field:last-child,
.slide form .err:last-child {
  margin-bottom: 0;
}

/* Build credit — quiet by default, brightens on press */
.credit {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 22px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-3);
  transition: opacity 0.16s var(--ease);
}

.credit:active {
  opacity: 0.6;
}

/* Centred variant for the account sheet footer */
.credit-center {
  display: flex;
  justify-content: center;
  margin-top: 14px;
}

.metadia-mark {
  display: block;
  width: 62px;
  height: 17px;
  background: url("../img/metadia-light.svg") left center / contain no-repeat;
  opacity: 0.72;
}

.slide-title {
  font-size: 24px;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-bottom: 4px;
}

.slide-sub {
  font-size: 13.5px;
  color: var(--text-2);
  margin-bottom: 20px;
}

.slide .how {
  margin-top: 20px;
  margin-bottom: 0;
}

/* Footer: progress dots + the single primary action */
.onboard-foot {
  flex: 0 0 auto;
  padding-top: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.dots {
  display: flex;
  align-items: center;
  gap: 7px;
}

.dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border-radius: var(--r-full);
  background: rgba(255, 255, 255, 0.18);
  border: none;
  transition: width 0.25s var(--spring), background 0.25s var(--ease);
}

.dot.on {
  width: 22px;
  background: var(--amber-400);
}

.onboard-foot .btn {
  width: 100%;
}

/* How it works — numbered instructions, not decorative icon tiles */
.how {
  list-style: none;
  margin: 0 0 22px;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.how li {
  position: relative;
  display: flex;
  gap: 14px;
  padding: 0 0 18px;
}

/* Connecting rail between the numbers */
.how li:not(:last-child)::before {
  content: '';
  position: absolute;
  left: 13px;
  top: 30px;
  bottom: 4px;
  width: 1.5px;
  background: linear-gradient(180deg, var(--line-strong), transparent);
}

.how li:last-child {
  padding-bottom: 0;
}

.how .n {
  width: 27px;
  height: 27px;
  flex-shrink: 0;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 800;
  color: var(--amber-400);
  background: rgba(239, 177, 41, 0.1);
  border: 1px solid rgba(239, 177, 41, 0.28);
}

.how b {
  display: block;
  font-family: var(--font-display);
  font-size: 15.5px;
  font-weight: 700;
  margin-top: 3px;
}

.how span {
  display: block;
  margin-top: 3px;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--text-2);
}

.field {
  margin-bottom: 15px;
  scroll-margin-top: 70px;
  scroll-margin-bottom: 140px;
}

.field > label {
  display: block;
  margin-bottom: 7px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text-2);
  transition: color 0.16s var(--ease);
}

.field:focus-within > label {
  color: var(--blue-400);
}

.input {
  width: 100%;
  height: 52px;
  padding: 0 16px;
  /* 16px keeps iOS from zooming the viewport on focus */
  font-size: 16px;
  line-height: 1.3;
  color: var(--text);
  background: rgba(13, 20, 31, 0.7);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-md);
  transition: border-color 0.16s var(--ease), box-shadow 0.16s var(--ease), background 0.16s var(--ease);
  appearance: none;
  scroll-margin-top: 80px;
  scroll-margin-bottom: 140px;
}

.input::placeholder {
  color: var(--text-3);
  font-size: 15px;
}

.input:focus {
  outline: none;
  border-color: var(--blue-400);
  background: rgba(18, 28, 44, 0.95);
  box-shadow: 0 0 0 3.5px rgba(47, 136, 247, 0.25), 0 4px 12px rgba(0, 0, 0, 0.35);
}

.hint {
  margin-top: 6px;
  font-size: 12px;
  color: var(--text-3);
}

.err {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 6px 0 16px;
  padding: 10px 14px;
  border-radius: var(--r-md);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  color: #ffb4ad;
  background: rgba(240, 68, 56, 0.14);
  border: 1px solid rgba(240, 68, 56, 0.35);
}

.err-body {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}

.err-retry-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 12px;
  border-radius: var(--r-full);
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  background: rgba(240, 68, 56, 0.35);
  border: 1px solid rgba(240, 68, 56, 0.6);
  cursor: pointer;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background 0.16s var(--ease), transform 0.14s var(--spring);
}

.err-retry-btn:active {
  transform: scale(0.94);
  background: rgba(240, 68, 56, 0.5);
}

.err-retry-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.spin {
  animation: spin 0.85s linear infinite;
}

/* Faculty picker — chips read as an app control, a <select> reads as a form */
.picker {
  /* Fixed columns beat ragged wrapping when the labels differ in length */
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.picker button {
  min-height: 42px;
  padding: 0 14px;
  border-radius: var(--r-full);
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-2);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line);
  transition: transform 0.14s var(--spring), color 0.16s var(--ease), background 0.16s var(--ease), border-color 0.16s var(--ease);
}

.picker button:active {
  transform: scale(0.95);
}

.picker button[aria-pressed='true'] {
  color: #06131e;
  background: var(--pick-color, var(--blue-400));
  border-color: transparent;
}

.picker button .sub {
  font-weight: 600;
  opacity: 0.75;
}

/* ==========================================================
   COORDINATOR PIN GATE (/admin)
   ========================================================== */
.lock {
  max-width: 320px;
  margin: 0 auto;
  padding-top: 8vh;
  text-align: center;
}

.lock-glyph {
  width: 62px;
  height: 62px;
  margin: 0 auto 18px;
  border-radius: 20px;
  display: grid;
  place-items: center;
  color: var(--amber-400);
  background: linear-gradient(160deg, #1d2a38, #131c26);
  border: 1px solid var(--line-strong);
  box-shadow: var(--sh-2);
}

.lock h1 {
  font-size: 23px;
  font-weight: 800;
}

.lock p {
  margin: 8px auto 22px;
  font-size: 13.5px;
  color: var(--text-2);
}

.input.pin {
  height: 58px;
  margin-bottom: 12px;
  text-align: center;
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-indent: 0.3em;
}

.lock .err {
  text-align: left;
}

.lock-back {
  margin-top: 18px;
}

/* ==========================================================
   SCANNER
   ========================================================== */
.scanner {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: #05080c;
  border: 1px solid var(--line);
  box-shadow: var(--sh-2);
}

#qr-video-region {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100%;
}

#qr-video-region video {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
  display: block;
}

/* html5-qrcode injects its own chrome — hide it, we draw our own */
#qr-video-region img,
#qr-video-region > div:not(#qr-shaded-region) > span,
#qr-video-region__dashboard_section_csr span,
#qr-video-region__header_message {
  display: none !important;
}

#qr-shaded-region {
  display: none !important;
}

.scan-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
}

.scan-frame {
  position: relative;
  width: 62%;
  aspect-ratio: 1;
}

.scan-frame i {
  position: absolute;
  width: 26px;
  height: 26px;
  border: 3px solid var(--amber-400);
  border-radius: 4px;
}

.scan-frame i:nth-child(1) { top: 0; left: 0; border-right: 0; border-bottom: 0; border-top-left-radius: 12px; }
.scan-frame i:nth-child(2) { top: 0; right: 0; border-left: 0; border-bottom: 0; border-top-right-radius: 12px; }
.scan-frame i:nth-child(3) { bottom: 0; left: 0; border-right: 0; border-top: 0; border-bottom-left-radius: 12px; }
.scan-frame i:nth-child(4) { bottom: 0; right: 0; border-left: 0; border-top: 0; border-bottom-right-radius: 12px; }

.scan-laser {
  position: absolute;
  left: 6%;
  right: 6%;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--amber-400), transparent);
  box-shadow: 0 0 12px rgba(255, 202, 85, 0.8);
  animation: laser 2.4s ease-in-out infinite;
}

@keyframes laser {
  0%, 100% { top: 8%; }
  50% { top: 92%; }
}

.scan-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 30px 28px;
  text-align: center;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
}

.scan-fallback .glyph {
  width: 50px;
  height: 50px;
  margin-bottom: 8px;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  color: var(--text-3);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--line);
}

.scan-fallback h4 {
  font-size: 16px;
  font-weight: 700;
}

.scan-fallback p {
  font-size: 13px;
  color: var(--text-2);
  max-width: 28ch;
}

.scan-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 14px;
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.75);
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9);
}

/* Inline field + button (admin reset) */
.inline-form {
  display: flex;
  gap: 8px;
}

.inline-form .input {
  flex: 1;
  min-width: 0;
}

.inline-form .btn {
  width: auto;
  flex-shrink: 0;
  padding: 0 18px;
  min-height: 50px;
}

/* ==========================================================
   LISTS (clues, winners)
   ========================================================== */
.list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px;
  text-align: left;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  overflow: hidden;
}

.row::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--rail, transparent);
}

.row.done {
  border-color: rgba(16, 185, 129, 0.24);
}

.row-icon {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: 13px;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 800;
  color: var(--rail, var(--text-2));
  background: color-mix(in srgb, var(--rail, #7b8a9c) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--rail, #7b8a9c) 26%, transparent);
}

.row-body {
  flex: 1;
  min-width: 0;
}

.row-title {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 14.5px;
  font-weight: 700;
}

.row-title span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.row-sub {
  margin-top: 1px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--rail, var(--text-3));
}

.row-text {
  margin-top: 5px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-2);
}

.row-end {
  flex-shrink: 0;
  color: var(--text-3);
}

/* Winners podium */
.podium {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  margin-bottom: 18px;
}

.pod {
  flex: 1;
  padding: 14px 8px 12px;
  border-radius: var(--r-lg);
  text-align: center;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
}

.pod.p1 {
  padding-top: 20px;
  padding-bottom: 18px;
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(239, 177, 41, 0.18), transparent 65%),
    linear-gradient(180deg, var(--surface-2), var(--surface));
  border-color: rgba(239, 177, 41, 0.32);
}

.pod .medal {
  font-size: 22px;
  line-height: 1;
}

.pod.p1 .medal {
  font-size: 28px;
}

.pod .who {
  margin-top: 8px;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 800;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pod .when {
  margin-top: 3px;
  font-family: 'SFMono-Regular', ui-monospace, monospace;
  font-size: 10px;
  color: var(--text-3);
}

.rank {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 800;
  color: var(--text-2);
  background: rgba(255, 255, 255, 0.07);
}

.rank.r1 { color: #2a1c00; background: linear-gradient(160deg, var(--amber-400), var(--amber-500)); }
.rank.r2 { color: #1b2027; background: linear-gradient(160deg, #e2e8ef, #b9c3cf); }
.rank.r3 { color: #24160a; background: linear-gradient(160deg, #e0a35f, #c07a3a); }

/* You-are-here banner */
.you-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  margin-bottom: 16px;
  border-radius: var(--r-lg);
  background:
    radial-gradient(120% 130% at 0% 0%, rgba(239, 177, 41, 0.18), transparent 60%),
    linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid rgba(239, 177, 41, 0.3);
}

.you-banner .big {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 800;
  color: var(--amber-400);
}

/* Empty state */
.empty {
  padding: 44px 24px;
  text-align: center;
}

.empty .glyph {
  width: 54px;
  height: 54px;
  margin: 0 auto 14px;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  color: var(--text-3);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--line);
}

.empty h4 {
  font-size: 16px;
  font-weight: 700;
}

.empty p {
  margin-top: 5px;
  font-size: 13px;
  color: var(--text-3);
}

/* Skeletons */
.skel {
  border-radius: var(--r-lg);
  background: linear-gradient(100deg, rgba(255, 255, 255, 0.04) 30%, rgba(255, 255, 255, 0.09) 50%, rgba(255, 255, 255, 0.04) 70%);
  background-size: 300% 100%;
  animation: shimmer 1.3s linear infinite;
}

@keyframes shimmer {
  from { background-position: 150% 0; }
  to { background-position: -150% 0; }
}

.skel-seal {
  height: 100%;
  width: auto;
  aspect-ratio: 1;
  max-width: 100%;
  max-height: clamp(48px, 12dvh, 120px);
  min-height: 42px;
  border-radius: var(--r-full);
  background: rgba(44, 53, 66, 0.08);
}

/* ==========================================================
   TAB BAR + FAB
   ========================================================== */
.tab-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  max-width: var(--app-w);
  margin: 0 auto;
  height: calc(var(--nav-h) + var(--safe-b));
  padding-bottom: var(--safe-b);
  display: flex;
  align-items: stretch;
  background: rgba(9, 14, 20, 0.86);
  backdrop-filter: saturate(160%) blur(16px);
  -webkit-backdrop-filter: saturate(160%) blur(16px);
  border-top: 1px solid var(--line);
}

/* Equal-weight groups either side of the FAB keep it dead centre,
   even though there are two tabs on the left and one on the right */
.tab-group {
  flex: 1;
  display: flex;
  align-items: stretch;
}

.tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--text-3);
  transition: color 0.16s var(--ease);
}

.tab i {
  display: grid;
  place-items: center;
  transition: transform 0.22s var(--spring);
}

.tab:active i {
  transform: scale(0.86);
}

.tab.on {
  color: var(--amber-400);
}

.tab.on i {
  transform: translateY(-1px);
}

.fab-slot {
  flex: 0 0 76px;
  display: grid;
  place-items: center;
}

.fab {
  width: 56px;
  height: 56px;
  margin-top: -22px;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  color: #06131e;
  background: linear-gradient(165deg, var(--amber-400), var(--amber-500));
  box-shadow: 0 10px 24px -8px rgba(239, 177, 41, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.4);
  border: 3px solid rgba(9, 14, 20, 0.9);
  transition: transform 0.18s var(--spring);
}

.fab:active {
  transform: scale(0.92);
}

.fab.on {
  box-shadow: 0 0 0 4px rgba(239, 177, 41, 0.18), 0 10px 24px -8px rgba(239, 177, 41, 0.7);
}

/* ==========================================================
   SHEETS & MODALS
   ========================================================== */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: rgba(3, 6, 10, 0.66);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: fade 0.2s var(--ease);
}

.scrim.center {
  align-items: center;
  padding: var(--gutter);
}

@keyframes fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

.sheet {
  width: 100%;
  max-width: var(--app-w);
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line-strong);
  border-bottom: 0;
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  box-shadow: var(--sh-3);
  animation: sheetUp 0.34s var(--spring);
  overflow: hidden;
}

.scrim.center .sheet {
  max-width: 420px;
  border-radius: var(--r-xl);
  border-bottom: 1px solid var(--line-strong);
  animation: popIn 0.3s var(--spring);
}

@keyframes sheetUp {
  from { transform: translateY(100%); }
  to { transform: none; }
}

@keyframes popIn {
  from { transform: scale(0.94); opacity: 0; }
  to { transform: none; opacity: 1; }
}

.grabber {
  width: 38px;
  height: 4px;
  margin: 10px auto 0;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.18);
  flex-shrink: 0;
}

.sheet-head {
  padding: 14px 16px 12px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-shrink: 0;
}

.sheet-head h3 {
  margin-top: 5px;
  font-size: 19px;
  font-weight: 800;
}

.icon-btn {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  color: var(--text-2);
  background: rgba(255, 255, 255, 0.07);
  transition: transform 0.15s var(--ease);
}

.icon-btn:active {
  transform: scale(0.9);
}

.sheet-body {
  padding: 0 16px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.sheet-foot {
  padding: 12px 16px calc(12px + var(--safe-b));
  flex-shrink: 0;
  border-top: 1px solid var(--line);
  background: rgba(9, 14, 20, 0.6);
}

/* Quiz */
.quiz-q {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.35;
  margin-bottom: 16px;
}

.options {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-bottom: 6px;
}

.option {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 54px;
  padding: 12px 14px;
  text-align: left;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text);
  background: rgba(255, 255, 255, 0.04);
  border: 1.5px solid var(--line);
  border-radius: var(--r-md);
  transition: transform 0.14s var(--spring), border-color 0.16s var(--ease), background 0.16s var(--ease);
}

.option:active {
  transform: scale(0.985);
}

.option .letter {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 9px;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 800;
  color: var(--text-2);
  background: rgba(255, 255, 255, 0.08);
  transition: all 0.16s var(--ease);
}

.option.sel {
  border-color: var(--blue-500);
  background: rgba(47, 136, 247, 0.1);
}

.option.sel .letter {
  color: #06131e;
  background: var(--blue-400);
}

.option.right {
  border-color: var(--green-500);
  background: rgba(16, 185, 129, 0.12);
}

.option.right .letter {
  color: #04231a;
  background: var(--green-400);
}

.option.wrong {
  border-color: rgba(240, 68, 56, 0.6);
  background: rgba(240, 68, 56, 0.1);
  animation: shake 0.35s var(--ease);
}

@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
}

.feedback {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 12px 13px;
  margin-bottom: 12px;
  border-radius: var(--r-sm);
  font-size: 13.5px;
  font-weight: 600;
}

.feedback.ok {
  color: #7ff0c4;
  background: rgba(16, 185, 129, 0.12);
  border: 1px solid rgba(16, 185, 129, 0.32);
}

.feedback.no {
  color: #ffb4ad;
  background: rgba(240, 68, 56, 0.12);
  border: 1px solid rgba(240, 68, 56, 0.32);
}

.feedback .clue {
  margin-top: 4px;
  font-size: 12.5px;
  font-weight: 500;
  opacity: 0.85;
}

/* Account sheet */
.account-id {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 14px;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line);
  margin-bottom: 14px;
}

.account-id .avatar {
  width: 46px;
  height: 46px;
  font-size: 19px;
}

.account-id .who strong {
  font-family: var(--font-display);
  font-size: 16px;
}

.account-id .who div {
  font-size: 12.5px;
  color: var(--text-3);
  word-break: break-all;
}

/* Winner celebration */
.celebrate {
  padding: 8px 20px 24px;
  text-align: center;
}

.celebrate .trophy {
  font-size: 62px;
  line-height: 1;
  animation: hover 1.8s ease-in-out infinite;
}

@keyframes hover {
  0%, 100% { transform: translateY(0) rotate(-3deg); }
  50% { transform: translateY(-9px) rotate(3deg); }
}

.celebrate h2 {
  margin-top: 14px;
  font-size: 26px;
  font-weight: 900;
  letter-spacing: -0.02em;
  background: linear-gradient(120deg, #fff3cf, var(--amber-400) 55%, #d59512);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.celebrate .rank-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 12px;
  padding: 7px 16px;
  border-radius: var(--r-full);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 800;
  color: var(--amber-400);
  background: rgba(239, 177, 41, 0.12);
  border: 1px solid rgba(239, 177, 41, 0.35);
}

.celebrate p {
  margin-top: 14px;
  font-size: 14px;
  color: var(--text-2);
}

.stub {
  margin: 18px 0;
  padding: 13px;
  border-radius: var(--r-md);
  background: rgba(0, 0, 0, 0.3);
  border: 1px dashed rgba(239, 177, 41, 0.35);
}

.stub .eyebrow {
  color: rgba(255, 202, 85, 0.7);
}

.stub strong {
  display: block;
  margin-top: 4px;
  font-family: 'SFMono-Regular', ui-monospace, monospace;
  font-size: 14px;
  color: var(--amber-400);
}

/* ==========================================================
   ALREADY CLAIMED DIALOG
   ========================================================== */
.already-claimed-dialog h2 {
  font-size: 21px;
  margin-top: 6px;
  background: linear-gradient(120deg, #ffffff, var(--amber-400) 75%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ==========================================================
   TOASTS — bottom anchored, clear of the thumb zone
   ========================================================== */
.toasts {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(var(--nav-h) + var(--safe-b) + 12px);
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 0 var(--gutter);
  pointer-events: none;
  max-height: 190px;
  overflow: hidden;
}

.toast {
  display: flex;
  align-items: center;
  gap: 9px;
  max-width: 400px;
  padding: 11px 15px;
  border-radius: var(--r-full);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  background: rgba(31, 44, 58, 0.96);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--line-strong);
  box-shadow: var(--sh-2);
  animation: toastIn 0.3s var(--spring);
}

.toast.success {
  color: #8df0c8;
  border-color: rgba(16, 185, 129, 0.4);
}

.toast.error {
  color: #ffb4ad;
  border-color: rgba(240, 68, 56, 0.4);
}

@keyframes toastIn {
  from { transform: translateY(14px) scale(0.96); opacity: 0; }
  to { transform: none; opacity: 1; }
}

/* ==========================================================
   ADMIN / MONITOR
   ========================================================== */
.admin-top {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 18px;
}

.admin-top .acts {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.kpis {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin-bottom: 18px;
}

.kpi {
  padding: 14px;
  border-radius: var(--r-md);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
}

.kpi .k {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
}

.kpi .v {
  margin-top: 4px;
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 800;
  line-height: 1.1;
}

.kpi .v-cap {
  font-size: 17px;
  font-weight: 700;
  color: var(--text-3);
}

/* Winner-limit panel state */
.limit-panel.is-closed {
  border-color: rgba(240, 68, 56, 0.32);
}

.limit-panel.is-closed .panel-head {
  border-bottom-color: rgba(240, 68, 56, 0.22);
}

.kpi.gold {
  border-color: rgba(239, 177, 41, 0.3);
}

.kpi.gold .v {
  color: var(--amber-400);
}

.kpi .v.small {
  font-size: 15px;
  color: var(--green-400);
}

.admin-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
}

.panel {
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line);
  overflow: hidden;
}

.panel-head {
  padding: 14px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border-bottom: 1px solid var(--line);
}

.panel-head h3 {
  font-size: 15px;
  font-weight: 800;
}

.panel-body {
  padding: 14px 16px;
}

.live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--green-400);
}

.live .dot {
  width: 7px;
  height: 7px;
  border-radius: var(--r-full);
  background: var(--green-400);
  box-shadow: 0 0 8px var(--green-400);
  animation: blip 1.6s var(--ease) infinite;
}

@keyframes blip {
  0%, 100% { transform: scale(0.85); opacity: 0.65; }
  50% { transform: scale(1.25); opacity: 1; }
}

.feed {
  max-height: 420px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
}

.feed-item {
  padding: 10px 12px;
  border-radius: var(--r-sm);
  font-size: 13px;
  background: rgba(0, 0, 0, 0.26);
  border: 1px solid var(--line);
  border-left: 3px solid transparent;
}

.feed-item.stamp {
  border-left-color: var(--amber-500);
  background: rgba(239, 177, 41, 0.05);
}

.feed-item.done {
  border-left-color: var(--green-500);
  background: rgba(16, 185, 129, 0.07);
}

.feed-item .t {
  margin-top: 3px;
  font-family: 'SFMono-Regular', ui-monospace, monospace;
  font-size: 10.5px;
  color: var(--text-3);
}

.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  text-align: left;
  white-space: nowrap;
}

table.data th {
  padding: 10px 14px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-3);
  background: rgba(0, 0, 0, 0.28);
  border-bottom: 1px solid var(--line);
}

table.data td {
  padding: 11px 14px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}

table.data tr:last-child td {
  border-bottom: 0;
}

.mono {
  font-family: 'SFMono-Regular', ui-monospace, monospace;
  font-size: 12px;
  color: var(--text-2);
}

.school-split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
}

.school-split > div {
  padding: 12px;
  border-radius: var(--r-sm);
  background: rgba(0, 0, 0, 0.26);
  border: 1px solid var(--line);
}

.school-split b {
  display: block;
  margin-top: 7px;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 800;
}

.school-split span {
  font-size: 11px;
  color: var(--amber-400);
}

/* Spot editor */
.spot-editor {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.spot-edit {
  padding: 14px;
  border-radius: var(--r-md);
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--line);
  transition: border-color 0.16s var(--ease);
}

.spot-edit.dirty {
  border-color: rgba(239, 177, 41, 0.4);
}

.spot-edit .field {
  margin-bottom: 10px;
}

.spot-edit .field > label {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 5px;
}

.spot-edit .input {
  height: 42px;
  font-size: 14.5px;
}

.spot-edit .input.area {
  height: auto;
  padding: 10px 12px;
  line-height: 1.4;
  resize: vertical;
  font-family: var(--font-ui);
}

.spot-edit .input.code {
  font-family: 'SFMono-Regular', ui-monospace, monospace;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.spot-edit .input.invalid {
  border-color: rgba(240, 68, 56, 0.55);
}

.spot-edit-head {
  display: flex;
  align-items: flex-end;
  gap: 10px;
}

.spot-edit-head .row-icon {
  margin-bottom: 10px;
}

.spot-edit-head .field {
  flex: 1;
  min-width: 0;
}

.spot-edit-grid {
  display: grid;
  grid-template-columns: 1fr 132px;
  gap: 10px;
}

.answers {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.answer {
  display: flex;
  align-items: center;
  gap: 9px;
}

.answer .input {
  flex: 1;
  min-width: 0;
}

.answer-pick {
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: var(--r-full);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 800;
  color: var(--text-3);
  background: rgba(255, 255, 255, 0.05);
  border: 1.5px solid var(--line-strong);
  transition: transform 0.14s var(--spring), background 0.16s var(--ease), color 0.16s var(--ease);
}

.answer-pick:active {
  transform: scale(0.9);
}

.answer.correct .answer-pick {
  color: #04231a;
  background: var(--green-400);
  border-color: var(--green-400);
}

.answer.correct .input {
  border-color: rgba(16, 185, 129, 0.4);
}

.spot-edit-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 2px;
}

.spot-edit-foot .hint {
  margin-top: 0;
}

.spot-edit-foot .chip:disabled {
  opacity: 0.4;
}

.danger {
  border-color: rgba(240, 68, 56, 0.28);
}

.danger .panel-head {
  border-bottom-color: rgba(240, 68, 56, 0.2);
}

.danger .panel-head h3 {
  color: #ff9d94;
}

/* ==========================================================
   RESPONSIVE — short viewports: compact the onboarding so each
   step still fits without scrolling on a small phone
   ========================================================== */
@media (max-height: 680px) {
  .slide-welcome .glyph {
    width: 148px;
    height: 66px;
    margin-bottom: 16px;
  }

  .slide-welcome h1 {
    font-size: 28px;
  }

  .slide-welcome p {
    margin-top: 10px;
    font-size: 14px;
  }

  .slide-title {
    font-size: 21px;
  }

  /* The supporting line is the first thing to go when space is tight */
  .slide-sub {
    display: none;
  }

  .slide .field {
    margin-bottom: 10px;
  }

  .slide .field > label {
    margin-bottom: 5px;
  }

  .slide .input {
    height: 46px;
  }

  .slide .picker button {
    min-height: 38px;
  }

  .slide .how {
    margin-top: 14px;
  }

  .how li {
    padding-bottom: 14px;
  }

  .how b {
    font-size: 14.5px;
  }

  .how span {
    font-size: 12.5px;
  }
}

/* ==========================================================
   RESPONSIVE — short viewports: compress the passport chrome so
   the six seals keep a usable size (SE, split screen, landscape)
   ========================================================== */
@media (max-height: 760px) {
  .passport-view .hero {
    padding: 13px 14px;
    border-radius: var(--r-lg);
  }

  .passport-view .ring {
    width: 62px;
    height: 62px;
  }

  .passport-view .ring-label b {
    font-size: 18px;
  }

  .passport-view .hero-top {
    gap: 13px;
  }

  .passport-view .hero-copy h2 {
    font-size: 17px;
  }

  .passport-view .hero-copy p {
    font-size: 12.5px;
  }

  .passport-view .hero-actions {
    margin-top: 12px;
  }

  .passport-view .hero-actions .btn {
    min-height: 42px;
    font-size: 14.5px;
  }

  .passport-view .booklet-head {
    padding: 10px 14px;
  }

  .passport-view .booklet-head strong {
    font-size: 13.5px;
  }

  .passport-view .page {
    padding: 10px 10px 14px;
  }

  .passport-view .stamp-grid {
    gap: 6px 6px;
    padding-bottom: 15px;
  }

  .passport-view .page::after {
    font-size: 7.5px;
    padding: 3px 12px 4px;
  }

  .passport-view > .btn {
    min-height: 44px;
  }
}

/* Very short: the hero drops to a single progress row — the scan
   button in the tab bar is the primary action anyway */
@media (max-height: 620px) {
  .passport-view .hero-actions {
    display: none;
  }

  .passport-view .slot-meta {
    display: none;
  }
}

/* Landscape: height is the scarce axis and width is plentiful, so the
   stamps run as a single row of six and the booklet drops its header */
@media (max-height: 520px) and (min-width: 560px) {
  .passport-view .booklet-head {
    display: none;
  }

  .passport-view .hero {
    padding: 10px 14px;
  }

  .passport-view .hero-copy p {
    display: none;
  }

  .passport-view .ring {
    width: 52px;
    height: 52px;
  }

  .passport-view .ring-label b {
    font-size: 16px;
  }

  .passport-view .page {
    min-height: 104px;
    padding: 10px 12px;
  }

  .passport-view .stamp-grid {
    grid-template-columns: repeat(6, 1fr);
    grid-template-rows: 1fr;
    padding-bottom: 0;
  }

  .passport-view .page::after {
    display: none;
  }

  .passport-view .slot-name {
    -webkit-line-clamp: 1;
    min-height: 1.3em;
  }
}

/* ==========================================================
   RESPONSIVE — small phones (iPhone SE and similar)
   ========================================================== */
@media (max-width: 360px) {
  :root {
    --gutter: 12px;
  }

  .hero-copy h2 {
    font-size: 17.5px;
  }

  .booklet-head .eyebrow {
    font-size: 9px;
    letter-spacing: 0.09em;
  }

  .booklet-head strong {
    font-size: 14px;
  }

  .booklet-id {
    font-size: 9.5px;
  }

  .stamp-grid {
    gap: 10px 6px;
  }

  .tab {
    font-size: 9.5px;
  }
}

/* ==========================================================
   RESPONSIVE — tablet & desktop (admin monitoring, projector)
   ========================================================== */
@media (min-width: 700px) {
  :root {
    --gutter: 22px;
  }

  .app.wide .screen {
    padding-bottom: 40px;
  }

  .admin-top {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
  }

  .kpis {
    grid-template-columns: repeat(4, 1fr);
  }
}

@media (min-width: 1000px) {
  .admin-cols {
    grid-template-columns: 1.6fr 1fr;
    align-items: start;
  }

  .feed {
    max-height: 560px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
