:root,
:root[data-theme="light"] {
  --bg: #f6f7f9;
  --bg-alt: #eef3f8;
  --bg-grad-1: rgba(37, 99, 235, 0.14);
  --bg-grad-2: rgba(14, 165, 167, 0.12);
  --bg-grad-3a: #fbfcfe;
  --bg-grad-3b: #f3f5f8;
  --orb-1: rgba(37, 99, 235, 0.15);
  --orb-2: rgba(14, 165, 167, 0.12);
  --grid-line: rgba(255, 255, 255, 0.25);
  --surface: rgba(255, 255, 255, 0.88);
  --surface-strong: rgba(255, 255, 255, 0.96);
  --surface-soft: rgba(255, 255, 255, 0.72);
  --surface-elev: rgba(255, 255, 255, 0.86);
  --surface-inverse: #111827;
  --line: rgba(15, 23, 42, 0.08);
  --line-strong: rgba(15, 23, 42, 0.14);
  --text: #172033;
  --text-strong: #0b1220;
  --text-on-accent: #ffffff;
  --muted: #667085;
  --placeholder: #98a2b3;
  --accent: #2563eb;
  --accent-strong: #1d4ed8;
  --accent-deep: #1e40af;
  --accent-2: #0ea5a7;
  --accent-soft: rgba(37, 99, 235, 0.1);
  --accent-soft-2: rgba(14, 165, 167, 0.1);
  --accent-glow: rgba(37, 99, 235, 0.22);
  --accent-focus: rgba(37, 99, 235, 0.4);
  --accent-focus-ring: rgba(37, 99, 235, 0.12);
  --success: #079455;
  --danger: #d92d20;
  --chip-bg: rgba(15, 23, 42, 0.04);
  --chip-text: #344054;
  --shadow-lg: 0 28px 60px rgba(15, 23, 42, 0.08);
  --shadow-md: 0 14px 32px rgba(15, 23, 42, 0.06);
  --shadow-sm: 0 8px 18px rgba(15, 23, 42, 0.04);
  --radius-xl: 30px;
  --radius-lg: 22px;
  --radius-md: 16px;
  --radius-sm: 12px;
  --content-width: 1440px;
  color-scheme: light;
  font-family: "Avenir Next", "SF Pro Display", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
}

:root[data-theme="dark"] {
  --bg: #07091a;
  --bg-alt: #0c1024;
  --bg-grad-1: rgba(99, 102, 241, 0.22);
  --bg-grad-2: rgba(14, 165, 167, 0.16);
  --bg-grad-3a: #060818;
  --bg-grad-3b: #0a0d1f;
  --orb-1: rgba(99, 102, 241, 0.30);
  --orb-2: rgba(14, 165, 167, 0.22);
  --grid-line: rgba(148, 163, 184, 0.06);
  --surface: rgba(20, 24, 45, 0.78);
  --surface-strong: rgba(24, 28, 52, 0.92);
  --surface-soft: rgba(20, 24, 45, 0.55);
  --surface-elev: rgba(28, 33, 60, 0.78);
  --surface-inverse: #f8fafc;
  --line: rgba(148, 163, 184, 0.14);
  --line-strong: rgba(148, 163, 184, 0.24);
  --text: #e6ecf7;
  --text-strong: #f6f8ff;
  --text-on-accent: #061027;
  --muted: #94a3b8;
  --placeholder: #64748b;
  --accent: #8aa6ff;
  --accent-strong: #6f8eff;
  --accent-deep: #4f6ad8;
  --accent-2: #2dd4bf;
  --accent-soft: rgba(138, 166, 255, 0.14);
  --accent-soft-2: rgba(45, 212, 191, 0.16);
  --accent-glow: rgba(138, 166, 255, 0.32);
  --accent-focus: rgba(138, 166, 255, 0.5);
  --accent-focus-ring: rgba(138, 166, 255, 0.18);
  --success: #34d399;
  --danger: #f87171;
  --chip-bg: rgba(148, 163, 184, 0.10);
  --chip-text: #cbd5e1;
  --shadow-lg: 0 30px 70px rgba(2, 6, 23, 0.55);
  --shadow-md: 0 18px 38px rgba(2, 6, 23, 0.42);
  --shadow-sm: 0 10px 22px rgba(2, 6, 23, 0.32);
  color-scheme: dark;
}

html { transition: background 360ms ease; }
body, .card, .reference-card, .flash-card .card-face, .checkbox, .header-titles, .hero-stat, .hero-panel, .modal-content, .nav-brand, .nav-link, .table, input, select, textarea, button.ghost, button.primary, .header-status, .user-chip, .hamburger, .floor-plan, .spec-table, .badge {
  transition: background-color 360ms ease, color 280ms ease, border-color 280ms ease, box-shadow 280ms ease;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  min-height: 100vh;
  color: var(--text);
  background:
    radial-gradient(circle at 10% 0%, var(--bg-grad-1), transparent 30%),
    radial-gradient(circle at 92% 10%, var(--bg-grad-2), transparent 24%),
    linear-gradient(180deg, var(--bg-grad-3a) 0%, var(--bg-grad-3b) 100%);
}

body.light, body.dark { color: var(--text); }

.app-background {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.bg-orb {
  position: absolute;
  border-radius: 999px;
  filter: blur(70px);
  opacity: 0.55;
}

.bg-orb-1 {
  top: -7rem;
  left: -6rem;
  width: 22rem;
  height: 22rem;
  background: var(--orb-1);
}

.bg-orb-2 {
  top: 12rem;
  right: -7rem;
  width: 24rem;
  height: 24rem;
  background: var(--orb-2);
}

.bg-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.3), transparent 78%);
}

#app {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  display: grid;
  /* Phase 2 QA (Profiles): bare `1fr` lets a grid column exceed the
     container when a child's min-content is wider (e.g. the Profiles
     role-filter <select> with a 21-char option). Using minmax(0, 1fr)
     caps the column at the container width so mobile sections never
     overflow the viewport. */
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr;
}

.app-header {
  position: sticky;
  top: 0;
  z-index: 30;
  width: min(100%, calc(var(--content-width) + 2rem));
  margin: 0 auto;
  padding: 1rem 1rem 0.8rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.header-titles {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
  flex: 1;
  padding: 0.85rem 1rem;
  border-radius: 1.4rem;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  backdrop-filter: blur(18px);
}

.header-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.7rem;
}

.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--accent);
}

.header-main {
  font-size: clamp(1.05rem, 1.35vw, 1.55rem);
  font-weight: 700;
  letter-spacing: -0.04em;
}

.header-sub {
  color: var(--muted);
  font-size: 0.86rem;
}

.header-status {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.65rem 0.9rem;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.82rem;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
}

.header-status::before {
  content: "";
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 999px;
  background: var(--success);
  box-shadow: 0 0 0 0.25rem rgba(7, 148, 85, 0.12);
}

.user-chip {
  display: inline-flex;
  align-items: center;
  min-height: 2.65rem;
  padding: 0.7rem 1rem;
  border-radius: 999px;
  background: var(--surface-inverse);
  color: var(--text-on-accent);
  font-size: 0.84rem;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
}

/* Header Sign out — always-visible affordance next to the user chip. Keeps
   the side-nav logout too so there are two discoverable paths on phones and
   desktops. Square-pill shape matches the user chip; outlined so it's
   obviously a button rather than a label. */
.header-logout {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  min-height: 2.65rem;
  padding: 0.55rem 0.95rem;
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line);
  font-size: 0.84rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: background 140ms ease, transform 140ms ease, box-shadow 140ms ease, border-color 140ms ease;
}
.header-logout:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
  border-color: var(--accent);
  color: var(--accent);
}
.header-logout:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.header-logout svg { flex: 0 0 auto; }
.header-logout.hidden { display: none; }
@media (max-width: 600px){
  /* Phone: icon-only so the header row doesn't wrap. The aria-label keeps
     the action nameable for screen readers. */
  .header-logout span { display: none; }
  .header-logout { padding: 0.55rem 0.8rem; }
}

.hamburger {
  width: 3rem;
  height: 3rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  display: grid;
  place-items: center;
  gap: 0.18rem;
  cursor: pointer;
  transition: transform 160ms ease, box-shadow 160ms ease, background 160ms ease;
}

.hamburger:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
  background: var(--surface-strong);
}

.hamburger span {
  display: block;
  width: 1.08rem;
  height: 2px;
  border-radius: 999px;
  background: var(--surface-inverse);
}

.side-nav {
  position: fixed;
  inset: 0 auto 0 0;
  width: min(88vw, 19.5rem);
  transform: translateX(-104%);
  transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1), background-color 360ms ease;
  overflow-y: auto;
  z-index: 60;
  padding: 1.1rem 1rem 1.4rem;
  background: var(--surface);
  border-right: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  backdrop-filter: blur(18px);
  display: flex;
  flex-direction: column;
}

/* Footer pinned to the bottom of the drawer — holds the Log out button so it
   sits below every nav section with visible separation. flex:1 on the last
   section above it isn't enough because sections have intrinsic height; use
   margin-top:auto on the footer itself instead. */
.nav-footer {
  margin-top: auto;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
}
.nav-link--logout {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: #b91c1c;
  font-weight: 600;
}
.nav-link--logout:hover,
.nav-link--logout:focus-visible {
  background: rgba(185, 28, 28, 0.08);
  color: #991b1b;
}
.nav-link--logout svg {
  flex-shrink: 0;
}
[data-theme="dark"] .nav-link--logout {
  color: #fca5a5;
}
[data-theme="dark"] .nav-link--logout:hover,
[data-theme="dark"] .nav-link--logout:focus-visible {
  background: rgba(252, 165, 165, 0.12);
  color: #fecaca;
}

.side-nav.open {
  transform: translateX(0);
}

.nav-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(7, 9, 26, 0.55);
  backdrop-filter: blur(2px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 260ms ease;
  z-index: 50;
}

.nav-backdrop.open {
  opacity: 1;
  pointer-events: auto;
}

body.nav-open {
  overflow: hidden;
}

.nav-brand {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  padding: 0.95rem;
  margin-bottom: 1.2rem;
  border-radius: 1.4rem;
  background: var(--surface-elev);
  border: 1px solid var(--line);
}

.nav-mark {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 1rem;
  background: linear-gradient(135deg, var(--accent-deep), var(--accent));
  color: #fff;
  font-weight: 700;
  letter-spacing: -0.04em;
}

.nav-brand-title {
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.nav-brand-copy {
  margin-top: 0.15rem;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.45;
}

.nav-section {
  margin-bottom: 1.2rem;
}

.nav-title {
  margin: 0 0 0.55rem;
  padding: 0 0.25rem;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

.nav-link {
  width: 100%;
  border: 1px solid transparent;
  border-radius: 1rem;
  background: transparent;
  color: var(--text);
  padding: 0.88rem 0.95rem;
  text-align: left;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: transform 160ms ease, background 160ms ease, border-color 160ms ease, color 160ms ease, box-shadow 160ms ease;
}

.nav-link:hover,
.nav-link.active {
  background: var(--accent-soft);
  border-color: var(--accent-focus);
  color: var(--accent);
  transform: translateX(2px);
  box-shadow: inset 0 0 0 1px var(--accent-soft);
}

.content {
  width: min(100%, var(--content-width));
  margin: 0 auto;
  padding: 0 1rem 2rem;
  display: grid;
  align-content: start;
  gap: 1rem;
}

.content-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(18rem, 0.95fr);
  gap: 1rem;
  padding: 0.35rem 0.2rem 0.1rem;
}

.hero-title {
  margin: 0.4rem 0 0.65rem;
  max-width: 13ch;
  font-size: clamp(2rem, 4vw, 4.1rem);
  line-height: 0.94;
  letter-spacing: -0.065em;
}

.hero-copy {
  margin: 0;
  max-width: 48rem;
  color: var(--muted);
  font-size: clamp(0.98rem, 1.15vw, 1.1rem);
  line-height: 1.7;
}

.hero-panel {
  display: grid;
  gap: 0.75rem;
  align-self: end;
}

.hero-stat {
  padding: 1rem 1.05rem;
  border-radius: 1.25rem;
  background: var(--surface-elev);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
}

.hero-stat span {
  display: block;
  color: var(--muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  margin-bottom: 0.3rem;
}

.hero-stat strong {
  font-size: 1rem;
  letter-spacing: -0.02em;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  backdrop-filter: blur(16px);
  padding: 1.35rem;
}

.section-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.95rem;
}

.section-header p,
.card p {
  color: var(--muted);
}

h1,
h2,
h3,
h4 {
  margin: 0;
  letter-spacing: -0.04em;
}

h1 {
  font-size: clamp(1.7rem, 2.4vw, 2.4rem);
}

h2 {
  font-size: clamp(1.2rem, 1.7vw, 1.65rem);
}

h3 {
  font-size: 1rem;
}

h4 {
  font-size: 0.95rem;
}

.controls,
.options-row,
.links-row,
.chips-row,
.badge-row,
.search-wrapper {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
}

.input-group {
  display: flex;
  flex-direction: column;
  gap: 0.42rem;
  margin-bottom: 0.95rem;
}

label {
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
}

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

input,
select,
textarea {
  width: 100%;
  padding: 0.92rem 1rem;
  color: var(--text);
  background: var(--input-bg, var(--surface-strong));
  border: 1px solid var(--input-border, var(--line-strong));
  border-radius: 1rem;
  outline: none;
  box-shadow: var(--input-shadow, none);
  transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease, transform 160ms ease;
}

:root[data-theme="light"] {
  --input-bg: #ffffff;
  --input-border: rgba(15, 23, 42, 0.22);
  --input-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 1px 2px rgba(15, 23, 42, 0.04);
}

:root[data-theme="dark"] {
  --input-bg: rgba(24, 28, 52, 0.92);
  --input-border: rgba(148, 163, 184, 0.28);
  --input-shadow: none;
}

input::placeholder,
textarea::placeholder {
  color: var(--placeholder);
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--accent-focus);
  box-shadow: 0 0 0 4px var(--accent-focus-ring);
}

textarea {
  min-height: 7rem;
  resize: vertical;
}

button {
  border: 0;
}

button.primary,
button.ghost,
button.text-link,
.nav-link {
  font-weight: 600;
}

button.primary,
button.ghost {
  min-height: 2.85rem;
  border-radius: 999px;
  padding: 0.75rem 1.1rem;
}

button.primary {
  color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--accent-strong) 65%, var(--accent-deep));
  box-shadow: 0 14px 28px var(--accent-glow);
  cursor: pointer;
  transition: transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
}

button.primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 18px 36px var(--accent-glow);
  filter: saturate(1.04);
}

button.primary:disabled,
button.ghost:disabled,
input:disabled,
select:disabled,
textarea:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

button.ghost {
  background: var(--surface-strong);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--line);
  cursor: pointer;
}

button.btn-sm {
  min-height: 2.2rem;
  padding: 0.45rem 0.85rem;
  font-size: 0.82rem;
}

button.text-link {
  padding: 0;
  background: transparent;
  color: var(--accent);
  cursor: pointer;
}

.checkbox {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.82rem 0.95rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 1rem;
  color: var(--text);
}

.checkbox input {
  width: auto;
  margin: 0;
}

.grid.two,
.card-grid,
.compact-grid,
.three-col {
  display: grid;
  gap: 0.9rem;
}

.grid.two {
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.card-grid {
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  grid-auto-rows: 17rem;
  align-items: stretch;
}

.compact-grid {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.three-col {
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

/* Flip-card outer button — sized container, no own visual */
.flash-card {
  position: relative;
  display: block;
  width: 100%;
  min-height: 16.5rem;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  perspective: 1400px;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: left;
}

.flash-card .fav-star {
  position: absolute;
  top: 0.55rem;
  right: 0.55rem;
  z-index: 5;
  width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-elev);
  color: var(--muted);
  cursor: pointer;
  transition: transform 140ms ease, color 140ms ease, background 140ms ease, border-color 140ms ease;
}
.flash-card .fav-star svg {
  width: 1.05rem;
  height: 1.05rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linejoin: round;
}
.flash-card .fav-star:hover {
  color: #f5b301;
  border-color: #f5b301;
  transform: scale(1.06);
}
.flash-card .fav-star.is-active {
  color: #f5b301;
  border-color: #f5b301;
  background: rgba(245,179,1,0.12);
}
.flash-card .fav-star.is-active svg {
  fill: #f5b301;
  stroke: #f5b301;
}
.flash-card .fav-star:focus-visible {
  outline: 2px solid var(--accent-focus);
  outline-offset: 2px;
}

.home-block {
  margin-top: 1.5rem;
}
.home-block:first-of-type {
  margin-top: 0.5rem;
}
.home-block h3 {
  margin: 0 0 0.75rem;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
}

.flash-card .card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: inherit;
  transform-style: preserve-3d;
  transition: transform 520ms cubic-bezier(.2,.85,.3,1);
}

.flash-card.is-flipped .card-inner {
  transform: rotateY(180deg);
}

.flash-card .card-face {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  padding: 1.2rem 1.25rem 1.3rem;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  overflow: hidden;
}

.flash-card .card-front {
  align-items: center;
  justify-content: center;
  text-align: center;
  background: var(--surface-elev);
}

.flash-card--batch .card-front {
  background: var(--accent-soft);
  border-color: var(--accent-focus);
}

.flash-card--full .card-front {
  background: var(--accent-soft-2);
}

.flash-card .card-back {
  transform: rotateY(180deg);
  overflow-y: auto;
  background: var(--surface-elev);
}

.flash-card--batch .card-back {
  background: var(--accent-soft);
  border-color: var(--accent-focus);
}

.flash-card .card-front h3 {
  font-size: 1.4rem;
  letter-spacing: -0.025em;
  margin: 0.25rem 0;
}

.flash-card .card-front .card-section {
  margin-top: 0.2rem;
}

.flash-card .flip-hint {
  margin-top: auto;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--muted);
  opacity: 0.8;
}

.flash-card:hover .card-face {
  box-shadow: var(--shadow-lg);
}

.flash-card:hover .card-front {
  transform: translateZ(0);
}

.flash-card:focus-visible {
  outline: 3px solid var(--accent-focus);
  outline-offset: 4px;
  border-radius: var(--radius-lg);
}

/* Reference card stays a static card, not a flip */
.reference-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  min-height: 100%;
  padding: 1.15rem 1.2rem 1.25rem;
  border-radius: var(--radius-lg);
  background: var(--surface-elev);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
}

.flash-card h3 {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.25;
  letter-spacing: -0.02em;
}

.reference-card h4 {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.25;
  letter-spacing: -0.02em;
}

.card-titles {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.15rem;
}

.card-section {
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}

.card-tip {
  margin: 0;
  padding: 0.65rem 0.8rem;
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: 0.55rem;
  color: var(--text);
  font-size: 0.84rem;
  line-height: 1.5;
}

.flash-card .card-back p,
.reference-card p {
  margin: 0.35rem 0;
  line-height: 1.55;
}

.spec-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0.15rem 0 0.25rem;
  background: var(--surface-soft);
  border-radius: 0.7rem;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--line);
}

.spec-table tr + tr td {
  border-top: 1px solid var(--line);
}

.spec-table td {
  padding: 0.55rem 0.75rem;
  font-size: 0.85rem;
  vertical-align: top;
}

.spec-table td.spec-ing {
  color: var(--text);
  font-weight: 500;
  width: 72%;
}

/* Measure column reads as a quiet unit tag next to the ingredient name —
   smaller font + lower weight so the eye lands on the ingredient first. */
.spec-table td.spec-measure {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  font-weight: 600;
  width: 28%;
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  padding-top: 0.7rem; /* nudge to align baseline with the larger ing text */
}

/* Test-card row layout — quantity column is narrower than ingredient because
   a measure is almost always < 8 chars while ingredients can get long. */
.test-card .grid.two {
  grid-template-columns: 1fr 0.55fr;
}
.test-card .input-group-qty input { font-variant-numeric: tabular-nums; }

.spec-heading {
  margin: 0.65rem 0 0.25rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}

.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.32rem 0.65rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.badge-batch {
  background: var(--accent-soft);
  color: var(--accent);
}

.badge-full {
  background: var(--accent-soft-2);
  color: var(--accent-2);
}

.badge-cat {
  background: var(--chip-bg);
  color: var(--chip-text);
}

.reference-card .badge {
  position: absolute;
  top: 1rem;
  right: 1rem;
}

.reference-card h4 {
  margin-right: 5.2rem;
}

.badge-chip,
.chip {
  display: inline-flex;
  align-items: center;
  min-height: 1.85rem;
  padding: 0.32rem 0.65rem;
  border-radius: 999px;
  background: var(--chip-bg);
  color: var(--chip-text);
  font-size: 0.76rem;
}

.hint {
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.55;
}

/* Test timer — large, sticky, accent-coloured bar that only appears when a test is running */
.test-timer {
  color: var(--muted);
  font-size: 0.86rem;
  line-height: 1.55;
}
.test-timer:not(:empty) {
  position: sticky;
  top: 0.5rem;
  z-index: 20;
  margin: 0.6rem 0 1rem;
  padding: 0.85rem 1.1rem;
  border-radius: 14px;
  background: linear-gradient(135deg, var(--accent, #ff6b6b), var(--accent-2, #f78cff));
  color: #fff;
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  font-variant-numeric: tabular-nums;
}

#searchBar {
  z-index: 15;
}

.search-wrapper input[type="search"] {
  flex: 1 1 20rem;
}

.table {
  width: 100%;
  overflow-x: auto;
  border-radius: 1.3rem;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--line);
}

.table table {
  width: 100%;
  border-collapse: collapse;
}

.table th,
.table td {
  padding: 1rem;
  text-align: left;
  border-bottom: 1px solid var(--line);
  font-size: 0.88rem;
}

.table th {
  color: var(--muted);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.batch-swatches {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 0.85rem;
  margin: 0.15rem 0 0.1rem;
  border-radius: 0.85rem;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--line);
  flex-wrap: wrap;
}

.swatch-row {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.swatch {
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 999px;
  border: 2px solid rgba(255, 255, 255, 0.95);
  box-shadow: 0 1px 4px rgba(15, 23, 42, 0.18), 0 0 0 1px rgba(15, 23, 42, 0.08);
}

details {
  margin-top: 0.75rem;
  border-top: 1px solid var(--line);
  padding-top: 0.75rem;
}

summary {
  cursor: pointer;
  font-weight: 600;
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(2, 6, 23, 0.45);
  backdrop-filter: blur(10px);
}

.modal.active {
  display: flex;
}

.modal-content {
  width: min(100%, 36rem);
  padding: 1.5rem;
  border-radius: 1.5rem;
  background: var(--surface-strong);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  color: var(--text);
}

.hidden {
  display: none !important;
}

.floor-plans {
  display: grid;
  gap: 1.2rem;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
}

.floor-plan {
  margin: 0;
  padding: 1rem;
  border-radius: var(--radius-lg);
  background: var(--surface-elev);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
}

.floor-plan figcaption {
  margin-top: 0.75rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.floor-plan-image {
  display: grid;
  place-items: center;
  min-height: 18rem;
  border-radius: 1rem;
  background: linear-gradient(135deg, var(--accent-soft), var(--accent-soft-2));
  border: 1px dashed var(--line-strong);
  overflow: hidden;
}

.floor-plan-image img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
}

.floor-plan-placeholder {
  color: var(--muted);
  font-size: 0.85rem;
  text-align: center;
  padding: 1rem;
}

main > section {
  scroll-margin-top: 7rem;
  /* Phase 2 QA (Profiles mobile): section-as-grid-item gets an implicit
     min-width: auto which equals min-content. When the section's children
     (e.g. a <select> with a long option label) exceed the column width,
     the section grows wider than its grid track and spills past the
     viewport. Resetting to 0 makes the section shrink to its track. */
  min-width: 0;
}

@media (max-width: 1023px) {
  .content-hero {
    grid-template-columns: 1fr;
    padding-top: 0.2rem;
  }

  .hero-title {
    max-width: 15ch;
  }

  .header-status {
    display: none;
  }
}

@media (min-width: 1024px) {
  .app-header {
    padding-top: 1rem;
  }

  .side-nav {
    width: min(22rem, 92vw);
  }
}

@media (max-width: 767px) {
  .app-header {
    padding: 0.9rem 0.8rem 0.7rem;
  }

  .header-actions {
    gap: 0.55rem;
  }

  .header-titles {
    padding: 0.78rem 0.9rem;
    border-radius: 1.2rem;
  }

  .header-main {
    font-size: 1rem;
  }

  .header-sub {
    font-size: 0.76rem;
  }

  .user-chip {
    padding: 0.55rem 0.8rem;
    font-size: 0.74rem;
  }

  .content {
    padding: 0 0.8rem 1.4rem;
  }

  .card {
    border-radius: 1.45rem;
    padding: 1.05rem;
  }

  .content-hero {
    gap: 0.85rem;
  }

  .hero-panel {
    gap: 0.55rem;
  }



}

/* ========== Login Splash ========== */
body.logged-out #app { display: none !important; }
body.logged-in  #loginSplash { display: none !important; }

.login-splash {
  position: relative;
  z-index: 2;
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: 1.4rem clamp(1rem, 4vw, 3rem) 1.6rem;
  gap: 1.4rem;
}

.login-splash-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.splash-brand {
  display: flex;
  align-items: center;
  gap: 0.95rem;
}

.splash-mark {
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: 1.05rem;
  background: linear-gradient(135deg, var(--accent-deep), var(--accent));
  color: #fff;
  font-weight: 800;
  letter-spacing: -0.04em;
  box-shadow: 0 14px 30px var(--accent-glow);
}

.splash-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 0.18rem;
}

.splash-brand-name {
  font-size: clamp(1.05rem, 1.6vw, 1.4rem);
  font-weight: 800;
  letter-spacing: -0.025em;
  color: var(--text-strong);
}

.login-splash-body {
  display: grid;
  place-items: center;
  width: 100%;
}

.login-splash-card {
  width: min(100%, 38rem);
  padding: clamp(1.4rem, 3vw, 2.4rem);
  border-radius: var(--radius-xl);
  background: var(--surface-strong);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  backdrop-filter: blur(20px);
}

.login-splash-headline h1 {
  margin: 0 0 0.45rem;
  font-size: clamp(1.7rem, 3.2vw, 2.4rem);
  letter-spacing: -0.04em;
  color: var(--text-strong);
}

.login-splash-headline p {
  margin: 0 0 1.4rem;
  color: var(--muted);
  line-height: 1.6;
  max-width: 32rem;
}

.splash-form .links-row { margin-bottom: 0.9rem; }
.splash-form .options-row { margin-bottom: 0.9rem; }
.splash-form button.primary { width: 100%; }
.splash-form .hint { margin-top: 0.7rem; }
.splash-form .hint.is-error { color: #ff6b6b; font-weight: 600; }

.password-wrap {
  position: relative;
}
.password-wrap input {
  padding-right: 3rem;
}
.password-toggle {
  position: absolute;
  top: 50%;
  right: 0.55rem;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.4rem;
  height: 2.4rem;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  border-radius: 999px;
  transition: color 140ms ease, background 140ms ease;
}
.password-toggle:hover {
  color: var(--text);
  background: var(--surface-elev);
}
.password-toggle .eye-hide { display: none; }
.password-toggle.is-showing .eye-show { display: none; }
.password-toggle.is-showing .eye-hide { display: block; }
.password-toggle:focus-visible {
  outline: 2px solid var(--accent-focus);
  outline-offset: 2px;
}

input.is-error,
select.is-error,
textarea.is-error {
  border-color: #ff6b6b !important;
  background: rgba(255, 107, 107, 0.08);
}
.checkbox.is-error {
  border-color: #ff6b6b;
  background: rgba(255, 107, 107, 0.1);
  color: #ff6b6b;
}
.checkbox.is-error span { color: #ff6b6b; }

.login-splash-footer {
  text-align: center;
  font-size: 0.74rem;
  color: var(--muted);
  letter-spacing: 0.03em;
}

/* ========== Spec Test Multi-choice ========== */
.test-card {
  min-height: auto;
  perspective: none;
  cursor: default;
  padding: 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-elev);
  margin-bottom: 1rem;
}
.test-card > .badge {
  padding: 0.12rem 0.45rem;
  font-size: 0.56rem;
  letter-spacing: 0.04em;
  line-height: 1.15;
}
.mc-row {
  display: grid;
  gap: 1rem;
  margin-top: 0.9rem;
}
.mc-group label {
  display: block;
  margin-bottom: 0.45rem;
}
.mc-options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.mc-btn {
  padding: 0.55rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--surface-strong);
  color: var(--text);
  font-size: 0.82rem;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.mc-btn:hover {
  border-color: var(--accent-focus);
  background: var(--surface-elev);
}
.mc-btn.selected {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
.mc-btn.mc-correct {
  background: rgba(93, 242, 196, 0.15);
  border-color: rgba(93, 242, 196, 0.6);
  color: #5df2c4;
}
.mc-btn.mc-wrong {
  background: rgba(255, 107, 107, 0.15);
  border-color: rgba(255, 107, 107, 0.6);
  color: #ff6b6b;
}

@media (max-width: 600px) {
  .login-splash {
    padding: 0.9rem 0.9rem 1.1rem;
    gap: 0.85rem;
  }
  .login-splash-top {
    gap: 0.7rem;
  }
  .login-splash-card {
    padding: 1.15rem 1.1rem 1.25rem;
    border-radius: 1.4rem;
  }
  .login-splash-headline h1 {
    font-size: 1.55rem;
    margin-bottom: 0.3rem;
  }
  .login-splash-headline p {
    font-size: 0.85rem;
    margin-bottom: 1rem;
    line-height: 1.5;
  }
  .splash-form .input-group {
    margin-bottom: 0.7rem;
  }
  .splash-form input,
  .splash-form select,
  .splash-form textarea {
    padding: 0.78rem 0.85rem;
    border-radius: 0.85rem;
  }
  .splash-form .password-wrap input {
    padding-right: 2.6rem;
  }
  .splash-form .options-row {
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
  }
  .splash-form .checkbox {
    padding: 0.65rem 0.85rem;
    border-radius: 0.85rem;
    font-size: 0.85rem;
  }
  .splash-form .links-row {
    margin-bottom: 0.8rem;
  }
  .splash-form button.primary {
    padding: 0.85rem 1rem;
    border-radius: 0.95rem;
    font-size: 0.95rem;
  }
  .splash-mark {
    width: 2.4rem;
    height: 2.4rem;
    border-radius: 0.85rem;
    font-size: 0.9rem;
  }
  .splash-eyebrow {
    font-size: 0.6rem;
  }
  .splash-brand-name {
    font-size: 0.95rem;
  }
  .login-splash-footer {
    font-size: 0.68rem;
  }
}

/* ---------- Edit pencil on flash cards (Phase 2) ---------- */
.flash-card .edit-pencil {
  position: absolute;
  top: 0.55rem;
  left: 0.55rem;
  z-index: 5;
  width: 2rem;
  height: 2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-elev);
  color: var(--muted);
  cursor: pointer;
  transition: transform 140ms ease, color 140ms ease, background 140ms ease, border-color 140ms ease;
}
.flash-card .edit-pencil svg {
  width: 1rem;
  height: 1rem;
  fill: currentColor;
}
.flash-card .edit-pencil:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: scale(1.06);
}
.flash-card .edit-pencil:focus-visible {
  outline: 2px solid var(--accent-focus);
  outline-offset: 2px;
}

/* ---------- Photo button on flash-card back face ---------- */
/* A pill-style "View photo" button rendered INSIDE the card-back. Sits at
   the bottom of the spec panel, below the service tip. Only visible once
   the card is flipped (lives inside .card-back, which only the flipped
   card shows). Click pops a lightbox lightbox so staff can see a reference
   image of the drink without crowding the spec table. */
.flash-card .card-photo-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.5rem;
  padding: 0.4rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface-elev);
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 500;
  cursor: pointer;
  align-self: center;
  transition: color 140ms ease, border-color 140ms ease, background 140ms ease, transform 140ms ease;
}
.flash-card .card-photo-btn svg {
  flex-shrink: 0;
}
.flash-card .card-photo-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: rgba(116, 124, 255, 0.08);
  transform: translateY(-1px);
}
.flash-card .card-photo-btn:focus-visible {
  outline: 2px solid var(--accent-focus);
  outline-offset: 2px;
}
/* The back face uses flex column layout; push the photo button to the
   bottom area so it sits under the tip naturally. */
.flash-card .card-back {
  display: flex;
  flex-direction: column;
}
.flash-card .card-back .card-photo-btn {
  margin-top: auto;
  margin-bottom: 0.25rem;
}

/* =========================================================================
   T2-06 Spaced-repetition flash cards: grade buttons, Due badge, Due chip,
   Home "cards due today" tile.
   ========================================================================= */

/* Grade row under "View photo" on the back face. */
.flash-card .card-grade-row {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding-top: 0.5rem;
  margin-top: 0.4rem;
  border-top: 1px dashed rgba(255, 255, 255, 0.14);
  align-items: stretch;
}
.flash-card .card-grade-label {
  font-size: 0.72rem;
  color: var(--muted, #9aa1b7);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.flash-card .card-grade-btns {
  display: grid;
  /* Wave 2 Marcus-v5 #1: 4-column Again/Hard/Good/Easy row. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.35rem;
}
.flash-card .card-grade-btn {
  appearance: none;
  border: 1px solid currentColor;
  border-radius: 999px;
  padding: 0.45rem 0.35rem;
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.01em;
  background: transparent;
  cursor: pointer;
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  transition: background 120ms ease, transform 120ms ease;
}
.flash-card .card-grade-btn:active { transform: scale(0.97); }
.flash-card .card-grade-hotkey {
  display: inline-block;
  font-size: 0.66rem;
  opacity: 0.7;
  border: 1px solid currentColor;
  border-radius: 4px;
  padding: 0 0.28rem;
  font-weight: 500;
  line-height: 1.2;
}
.flash-card .card-grade-again  { color: #e25757; background: rgba(226,87,87,0.14); }
.flash-card .card-grade-again:hover  { background: rgba(226,87,87,0.28); }
.flash-card .card-grade-hard   { color: #e49a2b; background: rgba(228,154,43,0.14); }
.flash-card .card-grade-hard:hover   { background: rgba(228,154,43,0.28); }
.flash-card .card-grade-good   { color: #2fae65; background: rgba(47,174,101,0.12); }
.flash-card .card-grade-good:hover   { background: rgba(47,174,101,0.28); }
.flash-card .card-grade-easy   { color: #5b9cff; background: rgba(91,156,255,0.14); }
.flash-card .card-grade-easy:hover   { background: rgba(91,156,255,0.28); }
/* Legacy 3-button colours kept for anyone still wiring .card-grade-medium. */
.flash-card .card-grade-medium { color: #e49a2b; background: rgba(228,154,43,0.14); }
.flash-card .card-grade-medium:hover { background: rgba(228,154,43,0.28); }
.flash-card .card-grade-btn:focus-visible {
  outline: 2px solid var(--accent, #5b9cff);
  outline-offset: 2px;
}

/* Suspend button shown only on leech cards. */
.flash-card .card-suspend-btn {
  align-self: flex-start;
  appearance: none;
  background: rgba(226, 87, 87, 0.14);
  color: #f4a7a7;
  border: 1px solid rgba(226, 87, 87, 0.55);
  border-radius: 999px;
  padding: 0.35rem 0.8rem;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  margin-top: 0.35rem;
}
.flash-card .card-suspend-btn:hover { background: rgba(226, 87, 87, 0.28); }

/* Mastery + leech badges on the title row. */
.flash-card .badge-mastery {
  background: rgba(91, 156, 255, 0.12);
  color: #a7c8ff;
  border: 1px solid rgba(91, 156, 255, 0.45);
  font-weight: 600;
}
.flash-card .badge-leech {
  background: rgba(226, 87, 87, 0.18);
  color: #ff9b9b;
  border: 1px solid rgba(226, 87, 87, 0.6);
  font-weight: 600;
}

/* SM-2 grade toast — bottom-centre inline notice after a grade. */
.bk-sr-toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%) translateY(8px);
  padding: 0.75rem 1.2rem;
  background: rgba(15, 18, 32, 0.95);
  color: #e8ecf8;
  border: 1px solid rgba(91, 156, 255, 0.45);
  border-radius: 999px;
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  box-shadow: 0 14px 36px rgba(5, 8, 20, 0.55);
  opacity: 0;
  transition: opacity 220ms ease, transform 220ms ease;
  pointer-events: none;
  z-index: 1200;
  max-width: 92vw;
  text-align: center;
}
.bk-sr-toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
body.light .bk-sr-toast {
  background: rgba(255,255,255,0.98);
  color: #18223f;
  border-color: rgba(91, 156, 255, 0.45);
}

/* Amber "Due" badge sits in the card's top titles row. */
.flash-card .badge-due {
  background: rgba(228, 154, 43, 0.18);
  color: #f0b75a;
  border: 1px solid rgba(228, 154, 43, 0.55);
  font-weight: 600;
  letter-spacing: 0.03em;
}

/* Amber left-border on due cards (front face). */
.flash-card.is-due {
  border-left: 4px solid #e49a2b;
  box-shadow: 0 0 0 1px rgba(228, 154, 43, 0.28);
}
.flash-card.is-due.is-flipped {
  box-shadow: 0 20px 48px rgba(8, 10, 22, 0.55), 0 0 0 1px rgba(228, 154, 43, 0.5);
}

/* "Due for review" chip above the flash-card grid. */
.due-chip {
  grid-column: 1 / -1;
  display: flex;
  justify-content: flex-start;
  margin-bottom: 0.4rem;
}
.due-chip-btn {
  appearance: none;
  background: rgba(228, 154, 43, 0.16);
  border: 1px solid rgba(228, 154, 43, 0.55);
  color: #f0b75a;
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.due-chip-btn:hover { background: rgba(228, 154, 43, 0.28); }
.due-chip-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #e49a2b;
  box-shadow: 0 0 0 3px rgba(228, 154, 43, 0.25);
}

/* Home "cards due today" tile — button variant of .home-stat-tile. */
button.home-stat-tile {
  appearance: none;
  border: inherit;
  background: inherit;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: left;
  transition: transform 120ms ease, border-color 120ms ease;
}
button.home-stat-tile:hover { transform: translateY(-2px); }
button.home-stat-tile:focus-visible {
  outline: 2px solid var(--accent, #5b9cff);
  outline-offset: 2px;
}
.home-stat-tile--due {
  border-left: 4px solid #e49a2b !important;
  background: linear-gradient(180deg, rgba(228,154,43,0.12), rgba(228,154,43,0.03)) !important;
}
.home-stat-tile--due strong { color: #f0b75a; }

/* Lightbox overlay for the reference photo */
.drink-photo-overlay {
  position: fixed;
  inset: 0;
  background: rgba(8, 10, 22, 0.82);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 1rem;
}
.drink-photo-card {
  position: relative;
  background: var(--surface-strong);
  border: 1px solid var(--line);
  border-radius: 1rem;
  padding: 1.25rem 1.25rem 1rem;
  max-width: min(640px, 100%);
  max-height: 90vh;
  overflow: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
}
.drink-photo-card h3 {
  margin: 0 0 0.7rem;
  font-size: 1.1rem;
  color: var(--text-strong);
  padding-right: 2rem;
}
.drink-photo-card img {
  display: block;
  max-width: 100%;
  max-height: 70vh;
  border-radius: 0.75rem;
  object-fit: contain;
  background: rgba(0, 0, 0, 0.15);
}
/* Cropped view uses CSS `object-view-box` (Chrome 104+, Safari 16+). The img
   gets an inset() that tells the browser which region of the source to
   display; aspect-ratio is set so the img box matches the crop's shape.
   Older browsers that don't support object-view-box gracefully degrade to
   showing the full image — never broken, just uncropped. */
.drink-photo-card .drink-photo-cropped {
  display: block;
  width: 100%;
  max-width: 480px;
  max-height: 70vh;
  object-fit: cover;
  border-radius: 0.75rem;
  background: rgba(0, 0, 0, 0.25);
  margin: 0 auto;
}
.drink-photo-close {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  width: 2rem;
  height: 2rem;
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  border-radius: 999px;
}
.drink-photo-close:hover {
  color: var(--text-strong);
  background: rgba(255, 255, 255, 0.06);
}

/* ---------- Admin venue multi-select ---------- */
/* Compact "Apply to multiple venues" drawer that expands below the primary
   venue <select>. Managers can tick multiple venues so a single Save writes
   the same recipe (or photo update) to every venue they manage in one go. */
.admin-venue-multi {
  margin-top: 0.55rem;
}
.admin-venue-multi summary {
  cursor: pointer;
  display: inline-flex;
  font-size: 0.85rem;
}
.admin-venue-multi-body {
  margin-top: 0.6rem;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 0.65rem;
  background: var(--surface-soft);
}
.admin-venue-multi-toolbar {
  display: flex;
  gap: 0.35rem;
  margin-bottom: 0.55rem;
}
.admin-venue-multi-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.3rem 0.5rem;
  max-height: 240px;
  overflow-y: auto;
  padding: 0.25rem;
}
.admin-venue-opt {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.35rem 0.5rem;
  border-radius: 0.5rem;
  font-size: 0.8rem;
  cursor: pointer;
}
.admin-venue-opt:hover {
  background: rgba(116, 124, 255, 0.06);
}
.admin-venue-opt input[type="checkbox"] {
  width: 1rem !important;
  height: 1rem !important;
  padding: 0 !important;
  flex-shrink: 0;
  accent-color: var(--accent);
}

/* ---------- Admin drink categories checklist ---------- */
/* Replaces the single-category <select> with a chip-style checkbox grid so
   a drink can belong to multiple categories (e.g. Classic Margarita lives
   on the classic / house / bottomless menus). The first ticked category is
   still used as the "primary" for badge display + storage routing. */
.admin-category-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0.4rem;
  margin-top: 0.4rem;
}
.admin-category-opt {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 0.65rem;
  background: var(--surface-soft);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}
.admin-category-opt:hover {
  border-color: var(--accent);
  background: rgba(116, 124, 255, 0.06);
}
.admin-category-opt input[type="checkbox"] {
  width: 1rem !important;
  height: 1rem !important;
  padding: 0 !important;
  flex-shrink: 0;
  accent-color: var(--accent);
}
.admin-category-opt span {
  font-size: 0.85rem;
  color: var(--text);
}
.admin-category-opt:has(input:checked),
/* Chrome <105 fallback — :has() selector is Chrome 105+. Admin code
   mirrors the state by adding .is-checked to the label whenever its
   child checkbox changes (wired in js/app.js admin category handler). */
.admin-category-opt.is-checked {
  border-color: var(--accent);
  background: rgba(116, 124, 255, 0.1);
}

/* ---------- Admin drink photo uploader ---------- */
/* Thumb + Upload / Remove controls above the URL field in the Admin recipe
   form. The thumb doubles as a live preview — pasting a URL or uploading
   a file updates it in real time. */
.admin-photo-group .admin-photo-row {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  margin-bottom: 0.5rem;
}
.admin-photo-preview {
  width: 96px;
  height: 96px;
  border-radius: 0.7rem;
  border: 1px dashed var(--line);
  background: var(--surface-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex-shrink: 0;
}
.admin-photo-preview.has-photo {
  border-style: solid;
  background: rgba(0, 0, 0, 0.2);
}
.admin-photo-preview img {
  max-width: 100%;
  max-height: 100%;
  object-fit: cover;
}
.admin-photo-placeholder {
  font-size: 0.7rem;
  color: var(--muted);
  text-align: center;
  padding: 0.3rem;
}
.admin-photo-controls {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  flex: 1;
}
.admin-photo-upload-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  /* match .btn-sm.ghost styling */
}

/* ---------- Food section ---------- */
/* Per-venue food menu. Items are grouped by section (Canapés, Buffet, Mains,
   Burgers, etc.) with allergen chips (V / VG / NGCI) on every card. Managers
   get Edit/Delete buttons via the manager-only toolbar. */
.food-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 1rem;
}
.food-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  justify-content: space-between;
  margin-bottom: 1rem;
}
.food-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}
.food-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.78rem;
  color: var(--muted);
}
.food-section {
  margin-bottom: 1.3rem;
}
.food-section h3 {
  margin: 0 0 0.55rem;
  font-size: 1rem;
  color: var(--text-strong);
}
.food-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 0.7rem;
}
.food-card {
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  background: var(--surface-soft);
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.food-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0.5rem;
}
.food-card h4 {
  margin: 0;
  font-size: 0.95rem;
  color: var(--text-strong);
}
.food-description {
  margin: 0;
  font-size: 0.82rem;
  color: var(--text);
  line-height: 1.35;
}
.food-note {
  margin: 0;
  font-size: 0.75rem;
  color: var(--accent);
  font-style: italic;
}
.food-price {
  font-size: 0.78rem;
  color: var(--muted);
}
.food-card-actions {
  display: flex;
  gap: 0.35rem;
  justify-content: flex-end;
  margin-top: 0.25rem;
}
/* Allergen chip — short code pill. Colour per allergen so the eye catches
   them fast. V = green, VG = teal, NGCI = amber. */
.food-allergens {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}
/* Allergen chips: WCAG 1.4.3 minimum contrast.
   Previous colours failed AA (1.94–2.73:1) on the light-mode card surface.
   Round-2 fix: in light mode we force a darker brand-ink (4.5:1+ on
   rgba(15,23,42,1) card and on white); in dark mode we keep the bright
   foreground but over a stronger tinted background. Border bumped to
   the same stronger tint so the chip shape holds at small font sizes. */
.food-allergen {
  display: inline-flex;
  align-items: center;
  padding: 0.18rem 0.55rem;
  font-size: 0.72rem; /* raised from 0.68rem — smallest body text we ship */
  font-weight: 700;
  letter-spacing: 0.05em;
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.24);
  color: var(--text);
  border: 1px solid rgba(148, 163, 184, 0.42);
}
/* Dark mode (default theme) — keep the bright chip on strong tint */
.food-allergen--v    { background: rgba(34, 197, 94, 0.22);  color: #86efac; border-color: rgba(34, 197, 94, 0.55); }
.food-allergen--vg   { background: rgba(20, 184, 166, 0.22); color: #5eead4; border-color: rgba(20, 184, 166, 0.55); }
.food-allergen--ngci { background: rgba(245, 158, 11, 0.26); color: #fcd34d; border-color: rgba(245, 158, 11, 0.6); }
/* Light mode override — darker ink for AA contrast */
body.light .food-allergen--v    { background: #dcfce7; color: #15803d; border-color: #86efac; }
body.light .food-allergen--vg   { background: #ccfbf1; color: #0f766e; border-color: #5eead4; }
body.light .food-allergen--ngci { background: #fef3c7; color: #b45309; border-color: #fcd34d; }

/* Food edit modal */
.food-edit-modal {
  max-width: min(540px, 92vw);
  max-height: 90vh;
  overflow: auto;
}
.food-allergen-picker {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0.45rem;
  margin-top: 0.35rem;
}
.food-allergen-opt {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 0.65rem;
  cursor: pointer;
}
.food-allergen-opt input[type="checkbox"] {
  width: 1rem !important;
  height: 1rem !important;
  padding: 0 !important;
  flex-shrink: 0;
}
.food-allergen-label {
  font-size: 0.78rem;
  color: var(--muted);
}

@media (max-width: 520px) {
  .food-grid {
    grid-template-columns: 1fr;
  }
  .food-head {
    flex-direction: column;
    gap: 0.5rem;
  }
}

/* ---------- Admin spec rows + form actions (Phase 1) ---------- */
.spec-rows { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.5rem; }
.spec-row {
  display: grid;
  grid-template-columns: 2fr 1fr auto;
  gap: 0.5rem;
  align-items: center;
}
.spec-row input {
  width: 100%;
}
.spec-row .spec-remove {
  width: 2.2rem;
  padding: 0;
  font-size: 1.1rem;
  line-height: 1;
}
.form-actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}

/* ---------- Colour code editor (Phase 4) ---------- */
.colour-section {
  margin-bottom: 1.75rem;
}
.colour-section h3 {
  margin: 0 0 0.75rem;
  font-size: 1.05rem;
}
.colour-section h3 .hint {
  font-size: 0.7rem;
  font-weight: 400;
  margin-left: 0.4rem;
}
.colour-rows {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.colour-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 0.85rem;
  align-items: center;
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-soft);
}
.colour-row .swatch-row {
  display: flex;
  gap: 0.3rem;
}
.colour-row .swatch {
  width: 1.2rem;
  height: 1.2rem;
  border-radius: 999px;
  border: 1px solid var(--line);
}
.colour-row-text {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.colour-row-text strong { color: var(--text-strong); }
.colour-row-actions {
  display: flex;
  gap: 0.4rem;
  flex-shrink: 0;
}
.colour-row input {
  padding: 0.45rem 0.6rem;
  border-radius: 0.6rem;
  border: 1px solid var(--line);
  background: var(--surface-strong);
  color: var(--text);
}
.colour-add {
  display: grid;
  grid-template-columns: 1fr 1.5fr auto;
  gap: 0.5rem;
  margin-top: 0.6rem;
}
.colour-add input {
  padding: 0.55rem 0.7rem;
  border-radius: 0.6rem;
  border: 1px solid var(--line);
  background: var(--surface-strong);
  color: var(--text);
}
@media (max-width: 600px) {
  .colour-row { grid-template-columns: auto 1fr; }
  .colour-row-actions { grid-column: 1 / -1; justify-content: flex-end; }
  .colour-add { grid-template-columns: 1fr; }
  .spec-row { grid-template-columns: 1fr; }
}

/* ---------- Spec test corrections panel (Phase 5) ---------- */
.correction-panel {
  margin-top: 1rem;
  padding: 0.85rem 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid rgba(255,107,107,0.35);
  background: rgba(255,107,107,0.07);
}
.correction-panel--ok {
  border-color: rgba(93,242,196,0.45);
  background: rgba(93,242,196,0.08);
}
.correction-panel h5 {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.correction-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.15rem;
  padding: 0.4rem 0;
  border-top: 1px solid var(--line);
}
.correction-row:first-of-type { border-top: none; }
.correction-label {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--text-strong);
}
.correction-your, .correction-right {
  font-size: 0.85rem;
}
.correction-your .hint, .correction-right .hint {
  margin-right: 0.25rem;
}
.correction-right strong { color: var(--success); }

/* ---------- Spec test summary panel (T2-07) ---------- */
.test-summary {
  margin: 0 0 1rem;
  padding: 1rem 1.1rem;
  border-radius: var(--radius-lg, 14px);
  border: 1px solid var(--line);
  background: var(--surface-elev);
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.test-summary .ts-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.test-summary .ts-score-val {
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.test-summary .ts-score-sub {
  margin-top: 0.2rem;
  font-size: 0.82rem;
  color: var(--muted);
}
.test-summary .ts-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.test-summary .ts-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  color: var(--muted);
  cursor: pointer;
}
.test-summary .ts-body {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 1rem;
}
@media (max-width: 640px) {
  .test-summary .ts-body { grid-template-columns: 1fr; }
}
.test-summary h5 {
  margin: 0 0 0.5rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
}
.test-summary .ts-field-row {
  display: grid;
  grid-template-columns: 90px 52px 1fr;
  align-items: center;
  gap: 0.6rem;
  padding: 0.28rem 0;
  font-size: 0.88rem;
}
.test-summary .ts-field-label { color: var(--text); }
.test-summary .ts-field-count {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.test-summary .ts-field-bar {
  display: block;
  height: 6px;
  border-radius: 3px;
  background: var(--surface-strong, rgba(255,255,255,0.06));
  overflow: hidden;
}
.test-summary .ts-field-bar-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #5df2c4, var(--accent, #5df2c4));
  transition: width 220ms ease;
}
.test-summary .ts-hardest-list {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.88rem;
  color: var(--text);
}
.test-summary .ts-hardest-list li { padding: 0.15rem 0; }

/* T2-07 optional: hide .test-card that have no mistakes when the toggle is on.
   A card with mistakes owns a non-ok correction-panel; we keep those visible. */
#testArea.test-only-incorrect .test-card:not(:has(.correction-panel:not(.correction-panel--ok))) {
  display: none;
}

/* === Account list (Admin tab) === */
.account-list {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  margin-top: 0.5rem;
}
.account-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-soft);
  transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
}
.account-row:hover {
  background: var(--surface-elev);
  border-color: var(--line-strong);
}
.account-row-main {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}
.account-row-main strong {
  color: var(--text-strong);
  font-size: 0.95rem;
}
.account-row-main .hint {
  font-size: 0.78rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.account-row-actions {
  display: flex;
  gap: 0.4rem;
  flex-shrink: 0;
}

/* === Profile grid + stat tiles === */
.profile-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}
.profile-section {
  padding: 1rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface-elev);
}
.profile-section h3 {
  margin: 0 0 0.6rem;
  color: var(--text-strong);
  font-size: 1rem;
}
.profile-section .input-group { margin-bottom: 0.55rem; }
.profile-section .stats-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.55rem;
}
.profile-section .stats-grid .reference-card {
  padding: 0.85rem;
  text-align: center;
}
.profile-section .stats-grid .reference-card h4 {
  margin: 0 0 0.2rem;
  font-size: 1.4rem;
  color: var(--text-strong);
}
.profile-last-test {
  font-size: 0.85rem !important;
  font-weight: 500 !important;
  line-height: 1.3;
  word-break: break-word;
}

/* === T1-05: Role badge on update feed (anti-spoof) ===
   Renders next to the author name so a Venue Manager who renames themselves
   to "Head Office" can't pass as HQ — the *role* chip still says Venue
   Manager because it's resolved live from the user record, not snapshotted
   at publish time. Colours cluster by seniority tier so the signal is
   readable at a glance. */
.update-role-badge {
  display: inline-block;
  padding: 0.08rem 0.45rem;
  margin-left: 0.3rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  vertical-align: 1px;
  background: rgba(148, 163, 184, 0.2);
  color: #475569;
  border: 1px solid rgba(148, 163, 184, 0.45);
}
.update-role-badge[data-role="Owner"],
.update-role-badge[data-role="BK Manager 1"] {
  background: rgba(234, 179, 8, 0.18);
  color: #92620b;
  border-color: rgba(234, 179, 8, 0.55);
}
.update-role-badge[data-role="Head Office"] {
  background: rgba(147, 51, 234, 0.18);
  color: #6b21a8;
  border-color: rgba(147, 51, 234, 0.5);
}
.update-role-badge[data-role="Location Manager"] {
  background: rgba(59, 130, 246, 0.18);
  color: #1d4ed8;
  border-color: rgba(59, 130, 246, 0.5);
}
.update-role-badge[data-role="Venue GM"],
.update-role-badge[data-role="Venue Manager"] {
  background: rgba(20, 184, 166, 0.18);
  color: #0f766e;
  border-color: rgba(20, 184, 166, 0.5);
}
.update-role-badge[data-role="Staff"] {
  background: rgba(148, 163, 184, 0.22);
  color: #475569;
  border-color: rgba(148, 163, 184, 0.5);
}

/* === Updates edit/delete buttons === */
.update-card { position: relative; }
.update-actions {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  display: flex;
  gap: 0.3rem;
  opacity: 0;
  transition: opacity 120ms ease;
}
.update-card:hover .update-actions,
.update-card:focus-within .update-actions {
  opacity: 1;
}
.update-actions .btn-sm {
  padding: 0.3rem 0.55rem;
  font-size: 0.72rem;
}
/* Global .danger variant. Needs an explicit border + transparent background
   because `button { border: 0 }` strips the default outline, so a bare
   `.btn-sm.danger` (without .ghost) otherwise looks like pink floating text. */
.btn-sm.danger,
button.danger {
  color: #b91c1c;
  background: transparent;
  border: 1px solid rgba(185, 28, 28, 0.4);
  border-radius: 999px;
  cursor: pointer;
}
.btn-sm.danger:hover,
button.danger:hover {
  background: rgba(185, 28, 28, 0.1);
  border-color: rgba(185, 28, 28, 0.6);
}
[data-theme="dark"] .btn-sm.danger,
[data-theme="dark"] button.danger {
  color: #fca5a5;
  border-color: rgba(252, 165, 165, 0.4);
}
[data-theme="dark"] .btn-sm.danger:hover,
[data-theme="dark"] button.danger:hover {
  background: rgba(252, 165, 165, 0.12);
}

/* === Home "View all updates" overflow link === */
.home-view-all-updates {
  display: block;
  margin: 0.85rem auto 0;
  padding: 0.4rem 0.8rem;
  font-size: 0.9rem;
}

/* === Skip-to-content link === */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0.5rem;
  z-index: 1000;
  padding: 0.6rem 1rem;
  background: var(--accent);
  color: #fff;
  border-radius: 8px;
  text-decoration: none;
  font-weight: 600;
}
.skip-link:focus {
  left: 0.5rem;
  outline: 2px solid var(--accent-strong);
  outline-offset: 2px;
}

/* === Flash-card keyboard focus === */
.flash-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 14px;
}

/* === Mobile responsiveness (≤ 720px) === */
@media (max-width: 720px) {
  .section-header {
    flex-direction: column;
    align-items: stretch;
    gap: 0.6rem;
  }
  .section-header .controls {
    width: 100%;
    flex-wrap: wrap;
  }
  .section-header .controls > * { flex: 1 1 auto; }

  /* .grid.two already collapses via auto-fit; no override needed for admin */

  .profile-grid {
    grid-template-columns: 1fr;
  }
  .profile-section .stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .account-row {
    flex-direction: column;
    align-items: stretch;
    gap: 0.55rem;
  }
  .account-row-actions {
    justify-content: flex-end;
  }

  /* Always show update actions on touch (no hover). On narrow screens
     the absolute-positioned top-right placement overlaps the audience
     badge — flow them naturally at the bottom of the card instead. */
  .update-actions { opacity: 1; }
  @media (max-width: 520px) {
    .update-actions {
      position: static;
      justify-content: flex-end;
      margin-top: 0.5rem;
    }
  }
}

/* === Tap targets (≥ 44×44px on touch / coarse pointers) === */
@media (pointer: coarse), (max-width: 720px) {
  .mc-btn,
  button.primary,
  button.ghost {
    min-height: 44px;
  }
  /* Round-3 R3-7: raise from 36px to meet WCAG 2.5.5. The "btn-sm" name is
     retained for layout purposes (tighter padding, smaller font) — the hit
     area is now a minimum 44×44 via min-width/min-height. */
  .btn-sm {
    min-height: 44px;
    min-width: 44px;
  }
  /* Round-3 R3-8: flash-card corner controls (fav-star, edit-pencil,
     card-photo-btn) were 32×32 on desktop and shrank to ~25.6px on phone.
     Force the outer hit area to 44×44 on touch while keeping the inner
     SVG at its designed size. */
  .flash-card .fav-star,
  .flash-card .edit-pencil {
    min-width: 44px;
    min-height: 44px;
    width: 44px;
    height: 44px;
  }
  .flash-card .fav-star svg,
  .flash-card .edit-pencil svg {
    width: 18px;
    height: 18px;
  }
  .flash-card .card-photo-btn {
    min-height: 44px;
    padding: 0.6rem 1rem;
  }
}

/* === Venue switcher (top bar) ===
   Shown only when a user has access to more than one venue. Replaces the
   "Hospitality Training OS" eyebrow so Owner / HO / multi-venue managers
   can pick which location they're looking at without digging into menus. */
.venue-switcher {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin-bottom: 0.15rem;
}
.venue-switcher[hidden] { display: none; }
.venue-switcher-label {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--accent);
}
.venue-switcher select {
  appearance: none;
  -webkit-appearance: none;
  background: linear-gradient(135deg, rgba(79, 155, 255, 0.15), rgba(38, 179, 164, 0.12));
  border: 1px solid var(--line);
  color: var(--text);
  border-radius: 999px;
  padding: 0.3rem 1.8rem 0.3rem 0.8rem;
  font-size: 0.82rem;
  font-weight: 600;
  max-width: 100%;
  cursor: pointer;
  background-image:
    linear-gradient(135deg, rgba(79, 155, 255, 0.15), rgba(38, 179, 164, 0.12)),
    linear-gradient(45deg, transparent 46%, currentColor 46%, currentColor 54%, transparent 54%),
    linear-gradient(-45deg, transparent 46%, currentColor 46%, currentColor 54%, transparent 54%);
  background-position: 0 0, calc(100% - 14px) 50%, calc(100% - 8px) 50%;
  background-size: 100% 100%, 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.venue-switcher select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* When switcher is visible, the static eyebrow drops out so we don't double up. */
.venue-switcher:not([hidden]) ~ .eyebrow { display: none; }

/* =========================================================================
   Per-section search inputs (Colours, Glasses) — narrow, pill-shaped, sit
   in each section's `.controls` slot instead of the removed global bar.
   ========================================================================= */
.section-search {
  min-height: 2.3rem;
  padding: 0.4rem 0.8rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-strong);
  color: var(--text);
  font-size: 0.85rem;
  min-width: 200px;
}
.section-search:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* =========================================================================
   Glass cards — photo upload + empty slot
   ========================================================================= */
.glass-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.glass-photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: 0.7rem;
  overflow: hidden;
  background: var(--surface-strong);
  display: flex;
  align-items: center;
  justify-content: center;
}
.glass-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.glass-photo-empty {
  border: 1px dashed var(--line);
}
.glass-photo-actions {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.glass-photo-upload {
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

/* =========================================================================
   Floor Plan editor (Tables section)
   ========================================================================= */
.fp-tabs {
  display: flex;
  gap: 0.35rem;
  background: var(--surface-strong);
  padding: 0.3rem;
  border-radius: 0.7rem;
  margin-bottom: 0.85rem;
  overflow-x: auto;
}
.fp-tab {
  background: transparent;
  border: 0;
  color: var(--muted);
  padding: 0.5rem 0.9rem;
  border-radius: 0.55rem;
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
  white-space: nowrap;
}
.fp-tab.active {
  background: var(--accent-soft);
  color: var(--accent);
}
.fp-tab:hover:not(.active) { color: var(--text); }

.fp-edit-toolbar {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 0.75rem;
}
.fp-edit-toolbar .hint { margin-left: auto; }

.fp-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  background: #3b4860;
  background-image:
    linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
  background-size: 4% 4%;
  border-radius: 0.85rem;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--line), 0 6px 18px rgba(15,23,42,.12);
  user-select: none;
  touch-action: none;
}
[data-theme="light"] .fp-stage {
  background: #cbd5e1;
}
.fp-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255,255,255,0.6);
}

.fp-table {
  position: absolute;
  transform: translate(-50%, -50%);
  min-width: 44px;
  padding: 0.2rem 0.4rem 0.25rem;
  background: #fff;
  color: #0f172a;
  text-align: center;
  border: 2px solid var(--fp-colour, #64748b);
  border-radius: 0.5rem;
  box-shadow: 0 3px 8px rgba(0,0,0,.2);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  transition: transform 140ms ease, box-shadow 140ms ease;
  touch-action: none;
}
.fp-table:hover {
  transform: translate(-50%, -50%) scale(1.15);
  box-shadow: 0 8px 18px rgba(0,0,0,.4);
  z-index: 5;
}
.fp-table.fp-table-round {
  border-radius: 999px;
  min-width: 46px;
  width: 46px;
  height: 46px;
  padding: 0;
  justify-content: center;
  gap: 0;
}
.fp-table.editable {
  cursor: grab;
}
.fp-table.editable:active, .fp-table.dragging { cursor: grabbing; }
.fp-table-number {
  font-size: 0.78rem;
  font-weight: 700;
  line-height: 1;
}
.fp-seat-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.35rem;
  background: #64748b;
  color: #fff;
  border-radius: 999px;
  font-size: 0.65rem;
  font-weight: 800;
  line-height: 1;
}
.fp-table-round .fp-table-number { font-size: 0.72rem; }
.fp-table-round .fp-seat-count {
  min-width: 1rem;
  height: 1rem;
  font-size: 0.58rem;
}

.fp-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.85rem;
  margin-top: 0.85rem;
  padding: 0.7rem 0.85rem;
  background: var(--surface-strong);
  border-radius: 0.7rem;
  font-size: 0.78rem;
}
.fp-legend-item {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}
.fp-sw {
  width: 0.8rem;
  height: 0.8rem;
  border-radius: 0.2rem;
  display: inline-block;
}

.fp-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.6rem;
}
.fp-stat {
  background: var(--surface-strong);
  padding: 0.55rem 0.85rem;
  border-radius: 0.65rem;
  min-width: 110px;
}
.fp-stat .label {
  color: var(--muted);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.fp-stat .val {
  font-size: 1.05rem;
  font-weight: 700;
  margin-top: 0.15rem;
}
.fp-stat-total {
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  color: #fff;
}
.fp-stat-total .label { color: rgba(255,255,255,0.85); }

/* ---- Features (walls / rooms / markers / voids) ---- */
.fp-feature {
  position: absolute;
  z-index: 1;
  border-radius: 0.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #e2e8f0;
  user-select: none;
  touch-action: none;
}
.fp-feature.editable { cursor: grab; }
.fp-feature.editable:active, .fp-feature.dragging { cursor: grabbing; }

.fp-wall {
  background: #8899aa;
  border-radius: 1px;
}
.fp-room {
  background: #2d3a4d;
  border: 2px solid #8899aa;
  color: #94a3b8;
  padding: 0.35rem 0.55rem;
}
.fp-room-label { line-height: 1.15; }

.fp-marker {
  background: var(--fp-feature-colour, #334155);
  color: #fff;
  padding: 0.45rem 0.65rem;
  min-width: 3rem;
  line-height: 1.15;
}
.fp-marker[style*="--fp-feature-colour:#7c3aed"] { color: #fff; }
.fp-marker-label { display: block; }

.fp-void {
  border: 2px solid #64748b;
  background:
    repeating-linear-gradient(
      45deg,
      transparent, transparent 8px,
      rgba(100,116,139,0.25) 8px, rgba(100,116,139,0.25) 10px
    );
  color: rgba(226,232,240,0.75);
}
.fp-void-label {
  font-size: 0.85rem;
  letter-spacing: 0.08em;
  line-height: 1.2;
}

/* ---- Resize handles on features (edit mode only) ---- */
.fp-resize-handle {
  position: absolute;
  width: 10px;
  height: 10px;
  background: #fff;
  border: 2px solid var(--accent);
  border-radius: 2px;
  z-index: 10;
  cursor: nwse-resize;
  touch-action: none;
  box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.fp-h-nw { top: -6px; left: -6px; cursor: nwse-resize; }
.fp-h-ne { top: -6px; right: -6px; cursor: nesw-resize; }
.fp-h-sw { bottom: -6px; left: -6px; cursor: nesw-resize; }
.fp-h-se { bottom: -6px; right: -6px; cursor: nwse-resize; }
.fp-wall .fp-h-nw { top: -5px; left: -5px; width: 8px; height: 8px; }
.fp-wall .fp-h-se { bottom: -5px; right: -5px; width: 8px; height: 8px; }

/* Snap glow — fires briefly when a dragged table lands on a sibling's axis */
.fp-table.fp-snapped {
  box-shadow: 0 0 0 3px rgba(88, 200, 255, 0.55), 0 3px 8px rgba(0,0,0,.2);
}

/* Draw-wall mode — stage becomes a crosshair canvas */
.fp-stage.fp-drawing {
  cursor: crosshair;
}
.fp-stage.fp-drawing .fp-table,
.fp-stage.fp-drawing .fp-feature { pointer-events: none; }
.fp-draw-ghost {
  background: var(--accent) !important;
  opacity: 0.6;
  pointer-events: none;
}

/* Toolbar "active" state — highlights Draw Wall when it's armed */
.fp-edit-toolbar button.active {
  background: var(--accent-soft);
  color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* Form hint — replaces the removed X/Y/W/H fields with a one-line pointer */
.fp-form-hint {
  margin: 0 0 0.5rem;
  color: var(--muted);
  font-size: 0.78rem;
}
.fp-form-full { grid-column: 1 / -1; }

/* ---- Edit modal ---- */
.fp-edit-modal-content {
  max-width: 560px;
  width: min(560px, calc(100vw - 2rem));
}
.fp-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  margin: 1rem 0 1.25rem;
}
.fp-form-grid .input-group {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.fp-form-grid .input-group span {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-weight: 600;
}
.fp-form-grid .input-group input,
.fp-form-grid .input-group select {
  width: 100%;
}
.fp-form-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
}
@media (max-width: 520px) {
  .fp-form-grid { grid-template-columns: 1fr; }
}

/* =========================================================================
   Methods checklist (Settings → Test Options)
   ========================================================================= */
.method-checklist {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.4rem 0.8rem;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--surface-strong);
  max-height: 16rem;
  overflow-y: auto;
}
.method-check {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.85rem;
  padding: 0.2rem 0;
  cursor: pointer;
}
.method-check input[type="checkbox"] {
  /* Important needed: the global `input { width:100% }` rule at the top
     of this file beats us on specificity cascade in some browsers when
     the checkbox has native appearance. Phase 2 QA caught this — on mobile
     the checkbox was stretching to the full label width (~213px) and
     pushing the label text far to the right. */
  width: 1rem !important;
  height: 1rem !important;
  flex-shrink: 0;
  padding: 0 !important;
  accent-color: var(--accent);
}
.method-check span { line-height: 1.2; }
.method-add-row {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.55rem;
}
.method-add-row input {
  flex: 1 1 auto;
}

/* =========================================================================
   Batching Calculator
   ========================================================================= */
.batch-vol-row {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.batch-vol-row input {
  flex: 1 1 120px;
  min-width: 5rem;
}
.batch-vol-row select {
  flex: 0 1 8rem;
}
.batch-calc-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  border-radius: 0.7rem;
  background: var(--surface-strong);
  margin: 1rem 0 0.75rem;
}
.batch-calc-summary > div {
  display: flex;
  flex-direction: column;
  min-width: 120px;
}
.batch-calc-summary strong {
  font-size: 1.1rem;
  margin-top: 0.15rem;
}
.batch-calc-summary .hint {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0;
}
.batch-calc-table th {
  text-align: left;
  padding: 0.45rem 0.75rem;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.batch-calc-table th.spec-measure { text-align: right; }

/* =========================================================================
   Bottles catalogue
   ========================================================================= */
.bottles-toolbar {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.bottle-card {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.bottle-photo {
  width: 100%;
  aspect-ratio: 3 / 4;
  border-radius: 0.7rem;
  overflow: hidden;
  background: #f8fafc;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
}
[data-theme="dark"] .bottle-photo {
  background: #e8edf4;
}
/* Contain the whole bottle inside the card — no zoom/crop. Lets the eye see
   the shape + label at a glance, which is the actual recognition cue. */
.bottle-photo img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}
.bottle-photo-empty { border: 1px dashed var(--line); }
.bottle-actions {
  display: flex;
  gap: 0.4rem;
  margin-top: auto;
}
.bottle-card h4 { margin-bottom: 0.1rem; }
.bottle-category {
  margin: 0.15rem 0 0.25rem;
  font-size: 0.65rem;
  letter-spacing: 0.08em;
}
.bottle-location {
  margin: 0.15rem 0 0.25rem;
  padding: 0.3rem 0.55rem;
  background: var(--surface-strong);
  border-radius: 0.5rem;
  font-size: 0.82rem;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 0.35rem;
  line-height: 1.25;
}
.bottle-location-icon { font-size: 0.82rem; line-height: 1; }
.bottle-notes {
  margin: 0.15rem 0;
  font-size: 0.82rem;
  color: var(--muted);
  line-height: 1.35;
}

/* Bottle edit modal */
.bottle-edit-modal-content {
  max-width: 640px;
  width: min(640px, calc(100vw - 2rem));
}
.bottle-edit-grid {
  display: grid;
  grid-template-columns: minmax(0, 180px) 1fr;
  gap: 1rem;
  margin: 1rem 0 1.25rem;
}
.bottle-edit-photo {
  width: 100%;
  aspect-ratio: 3 / 4;
  border-radius: 0.7rem;
  overflow: hidden;
  background: #f8fafc;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
  color: #64748b;
  font-size: 0.82rem;
}
[data-theme="dark"] .bottle-edit-photo { background: #e8edf4; }
.bottle-edit-photo img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}
.bottle-edit-photo-empty { border: 1px dashed var(--line); }
.bottle-edit-fields {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.bottle-edit-fields .input-group {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.bottle-edit-fields .input-group span {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-weight: 600;
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.bottle-edit-fields .hint-inline {
  font-style: normal;
  color: var(--muted);
  letter-spacing: 0;
  text-transform: none;
  font-weight: 400;
}
.bottle-edit-actions {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
}
@media (max-width: 560px) {
  .bottle-edit-grid { grid-template-columns: 1fr; }
}

/* =========================================================================
   Data tab — Hospitality Groups accordion (Owner / Global Admin only)
   ========================================================================= */
.group-toolbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}
.group-list {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.group-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-elev);
  overflow: hidden;
}
.group-card[open] {
  box-shadow: 0 14px 32px rgba(15, 23, 42, 0.08);
}
.group-card.paused {
  border-color: rgba(185, 28, 28, 0.35);
  background: rgba(185, 28, 28, 0.04);
}
.group-card > summary {
  list-style: none;
  cursor: pointer;
  padding: 1rem 1.2rem;
  user-select: none;
}
.group-card > summary::-webkit-details-marker { display: none; }
.group-card > summary::before {
  content: '▸';
  display: inline-block;
  margin-right: 0.55rem;
  color: var(--muted);
  transition: transform 160ms ease;
}
.group-card[open] > summary::before {
  transform: rotate(90deg);
}
.group-summary {
  display: inline-flex;
  width: calc(100% - 1.2rem);
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.group-summary-main h3 { margin: 0; font-size: 1.08rem; }
.group-summary-main .hint { margin: 0.2rem 0 0; }
.group-summary-right {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-shrink: 0;
}
.status-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.status-active {
  background: rgba(34, 197, 94, 0.15);
  color: #166534;
}
.status-paused {
  background: rgba(185, 28, 28, 0.15);
  color: #b91c1c;
}
[data-theme="dark"] .status-active { color: #86efac; }
[data-theme="dark"] .status-paused { color: #fca5a5; }

.group-body {
  padding: 0 1.2rem 1.25rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.group-sub {
  margin: 0.5rem 0 0.4rem;
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.group-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 0.65rem;
  margin-top: 0.75rem;
}
.group-stats-grid .stat-tile {
  padding: 0.85rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-strong);
  text-align: center;
}
.group-stats-grid .stat-tile h4 {
  margin: 0 0 0.15rem;
  font-size: 1.25rem;
}
.group-stats-grid .stat-tile .hint {
  margin: 0;
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.brand-block {
  padding: 0.85rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface-strong);
  margin-bottom: 0.55rem;
}
.brand-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}
.brand-actions {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.brand-actions-footer { margin-top: 0.15rem; }
.venue-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.venue-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.35rem 0.55rem;
  border: 1px dashed var(--line);
  border-radius: 0.6rem;
  background: var(--surface-elev);
  font-size: 0.9rem;
}
.venue-list li.hint {
  border-style: solid;
  background: transparent;
  color: var(--muted);
  justify-content: flex-start;
}
.group-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--line);
}

.raw-accounts {
  margin-top: 1.25rem;
  border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
  padding: 0.75rem 1rem;
  background: var(--surface-strong);
}
.raw-accounts summary {
  cursor: pointer;
  list-style: none;
  padding: 0.25rem 0;
}
.raw-accounts summary::-webkit-details-marker { display: none; }
.raw-accounts[open] summary { margin-bottom: 0.6rem; }
.raw-accounts summary::before {
  content: '▸';
  display: inline-block;
  margin-right: 0.5rem;
  color: var(--muted);
}
.raw-accounts[open] summary::before { content: '▾'; }

@media (max-width: 720px) {
  .group-summary { flex-direction: column; align-items: flex-start; }
  .group-summary-right { width: 100%; justify-content: space-between; }
  .group-actions { flex-direction: column; }
  .group-actions .btn-sm { width: 100%; }
}

/* ======================================================================
   V21 — Phone layout overhaul
   ======================================================================
   The old mobile experience showed one large "flash card" per row because
   .card-grid was set to minmax(260px, 1fr) and min-height 16.5rem — each
   card ate more than half the viewport. V21 swaps the single column for a
   2-column tile grid under 520px so users can scan a menu in a glance, and
   tightens the flash-card's internal layout so the essentials (name, glass,
   ingredient/method) fit without overflow at tile scale. Hero and section
   header are tuned for one-hand use, and every tappable control is >= 44px.
   ====================================================================== */
@media (max-width: 520px) {
  /* ---- 2-column tile grid ---- */
  .card-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: 12.5rem;
    gap: 0.6rem;
  }
  .compact-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.6rem;
  }

  /* ---- Flash card at tile size ---- */
  .flash-card {
    min-height: 12.5rem;
    font-size: 0.82rem;
  }
  .flash-card .card-face {
    padding: 0.75rem 0.7rem 0.85rem;
    gap: 0.4rem;
    border-radius: 0.95rem;
  }
  .flash-card h3 {
    font-size: 0.95rem;
    line-height: 1.2;
  }
  .flash-card .card-front h3 {
    /* Centre-only cards: keep name prominent but let glass/ice line peek */
    font-size: 1rem;
  }
  .flash-card .flip-hint {
    font-size: 0.6rem;
    letter-spacing: 0.08em;
  }
  .flash-card .fav-star,
  .flash-card .edit-pencil {
    width: 1.6rem;
    height: 1.6rem;
    top: 0.35rem;
  }
  .flash-card .fav-star { right: 0.35rem; }
  .flash-card .edit-pencil { left: 0.35rem; }
  .flash-card .fav-star svg,
  .flash-card .edit-pencil svg {
    width: 0.85rem;
    height: 0.85rem;
  }
  .flash-card .card-back p {
    font-size: 0.75rem;
    line-height: 1.35;
  }

  /* ---- Hero shrinks so the grid is above the fold ---- */
  .content-hero {
    display: none;
  }
  .hero-title { font-size: 1.2rem; }
  .hero-copy { font-size: 0.82rem; }

  /* ---- Section headers stack, controls full-width ---- */
  .section-header {
    flex-direction: column;
    align-items: stretch;
    gap: 0.55rem;
  }
  .section-header h2 { font-size: 1.3rem; }
  .section-header p { font-size: 0.8rem; }
  .section-header .controls { width: 100%; }
  .section-header .controls select,
  .section-header .controls input {
    width: 100%;
    min-height: 44px;
  }

  /* ---- Search bar full-width ---- */
  #searchBar { padding: 0.75rem; }
  #searchInput { min-height: 44px; font-size: 0.95rem; }

  /* ---- Cards (the container, not the flash-cards) ---- */
  .card { padding: 0.9rem; border-radius: 1.2rem; }
  .home-block h3 { font-size: 0.95rem; }
}

/* ---- Narrower phones (iPhone SE etc.) stay 2-col but tighter ---- */
@media (max-width: 360px) {
  .card-grid { gap: 0.45rem; grid-auto-rows: 11.5rem; }
  .flash-card .card-face { padding: 0.6rem 0.55rem 0.7rem; }
  .flash-card h3 { font-size: 0.88rem; }
  .flash-card .card-front h3 { font-size: 0.92rem; }
}

/* ---- Drawer footer (Log out pinned) mobile polish ---- */
@media (max-width: 720px) {
  .nav-footer {
    padding-top: 0.75rem;
    margin-top: auto;
  }
  .nav-link--logout {
    justify-content: flex-start;
    min-height: 44px;
  }
}

/* ---- Universal tap target pass: every clickable in the drawer ---- */
.side-nav .nav-link { min-height: 44px; }

/* ---- V21 fix: badge + venue switcher at tile scale ---- */
@media (max-width: 520px) {
  /* The "Full Spec" / "Batch Spec" badge was taller and wider than the tile
     itself on mobile — shrink padding and font so it fits comfortably.       */
  .flash-card .badge {
    padding: 0.22rem 0.45rem;
    font-size: 0.62rem;
    letter-spacing: 0.04em;
    max-width: 100%;
  }
  .flash-card .card-front .card-section {
    gap: 0.25rem;
    flex-wrap: wrap;
    justify-content: center;
  }

  /* Header titles + venue switcher: the pill was compressed to 42px because
     header-actions hogged width. Let the title column breathe and the pill
     grow to content. */
  .header-titles {
    min-width: 0;
    flex: 1 1 auto;
    padding: 0.55rem 0.7rem;
  }
  .venue-switcher {
    width: 100%;
  }
  .venue-switcher select {
    width: 100%;
    max-width: 100%;
  }
  .header-actions {
    flex-shrink: 0;
  }
  .user-chip {
    max-width: 7.5rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ---- Home favourites tile sizing so empty-state prompt doesn't stretch ---- */
@media (max-width: 520px) {
  #homeFavouritesGrid:empty::before {
    content: none;
  }
}

/* ---- V21 fix #2: badges fit inside the tile without colliding with edit
   pencil / fav star. The front face has two badges ("Full Spec" + category)
   stacked in .card-titles — on mobile they used to wrap wider than the tile,
   clipping the first letter. Shrink harder, wrap vertically, and reserve
   gutters either side for the absolutely-positioned icons. */
@media (max-width: 520px) {
  .flash-card .card-front {
    align-items: stretch;
    text-align: center;
    justify-content: flex-start;
    padding-top: 2.2rem;        /* leave room for pencil + fav star */
  }
  .flash-card .card-titles {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.25rem;
    justify-content: center;
    margin-top: 0;
    margin-bottom: 0.4rem;
  }
  .flash-card .badge,
  .flash-card .badge-cat,
  .flash-card .badge-full {
    padding: 0.2rem 0.4rem;
    font-size: 0.58rem;
    letter-spacing: 0.05em;
    border-radius: 0.55rem;
    line-height: 1.1;
  }
  .flash-card h3 {
    font-size: 0.9rem;
    margin-top: 0.2rem;
  }
  .flash-card .flip-hint {
    margin-top: auto;
  }
}

/* ---- V21 fix #3: flipped (back) face also needs icon gutter on mobile ---- */
@media (max-width: 520px) {
  .flash-card .card-back {
    padding-top: 2.2rem;
  }
  .flash-card .card-back .card-titles {
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.25rem;
  }
  .flash-card .card-back h3 {
    font-size: 0.88rem;
  }
  /* Spec table — two narrow columns aren't helpful at tile scale; stack. */
  .flash-card .card-back .spec-table {
    font-size: 0.72rem;
  }
  .flash-card .card-back .spec-table td {
    padding: 0.12rem 0.25rem;
  }
}

/* ======================================================================
   V21 — Mobile flash-card "expand when tapped"
   ======================================================================
   Default tile in the 2-col mobile grid is deliberately small so a user can
   scan a menu at a glance. Tapping a tile adds .is-flipped, which on mobile
   lifts the card out of the grid, centres it over the viewport and scales it
   up so the spec is easy to read. A backdrop behind it dims the rest. Tap
   the enlarged card again to flip back and drop into place.

   Implementation notes:
   • The existing flip transform lives on .card-inner (`rotateY(180deg)`), so
     we're free to use transform on the parent .flash-card to move/zoom it.
   • We use position:fixed on the card so it escapes the grid's layout and
     sits above every other element.
   • Backdrop is pure CSS via `body:has(.flash-card.is-flipped)::after` —
     modern browsers (Safari ≥15.4, Chrome ≥105, FF ≥121) support `:has()`.
   ====================================================================== */
/* ======================================================================
   V21 — Phone flash-card: small tiles + expand-on-flip
   ======================================================================
   Tiles are ~11rem so the 2-col grid scans at a glance. Tapping a tile
   flips it AND the card escapes the grid to become a content-fit modal
   card centred over the viewport with a dim backdrop behind. Tap again
   to close.

   Fixes that took several iterations to get right:
   • .card-face base has position:absolute/inset:0 — we override to
     position:relative on the back so it stops collapsing the flow.
   • .card-inner base has height:100% — we set it to auto so the back's
     content-height propagates up to the .flash-card.
   • section.card carries backdrop-filter:blur(16px) which creates a new
     containing block for position:fixed. :has() drops it while open.
   • .card-back has its own `transform: rotateY(180deg)` — we reset that
     AND the parent .card-inner's transform so we show the back face
     directly (no 3D animation when enlarged).
   ====================================================================== */
@media (max-width: 520px) {
  /* --- Grid tiles (non-flipped state) --- */
  .card-grid {
    grid-auto-rows: 11rem;
    gap: 0.55rem;
  }
  .flash-card {
    min-height: 11rem;
  }
  /* Solid back-face bg at tile size so if a card is mid-flip-animation
     (briefly) the content still reads as opaque. */
  [data-theme="dark"] .flash-card .card-back {
    background: #2b3357;
    border-color: #4a5596;
  }
  .flash-card .card-back {
    background: #ffffff;
  }

  /* --- section.card frosted-glass trap: disable while any card is open.
         Duplicate rule keyed on `.has-flipped-card` body class is the
         Chrome <105 fallback, since :has() lands in Chrome 105.  --- */
  section.card:has(.flash-card.is-flipped),
  body.has-flipped-card section.card {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  /* --- Escape to fixed, content-fit, centred over viewport --- */
  .flash-card.is-flipped {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(22rem, calc(100vw - 1.5rem));
    max-width: calc(100vw - 1.5rem);
    height: auto;
    max-height: calc(100vh - 2rem);
    min-height: 0;
    z-index: 1000;
    border-radius: 1.4rem;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
    perspective: none;
    animation: flashCardPop 200ms ease-out both;
  }

  /* --- Kill the 3D flip machinery in expanded state --- */
  .flash-card.is-flipped .card-inner {
    transform: none;
    transition: none;
    transform-style: flat;
    height: auto;         /* base is 100% — breaks content-fit sizing */
    min-height: 0;
  }
  .flash-card.is-flipped .card-front {
    display: none;
  }
  .flash-card.is-flipped .card-back {
    position: relative;   /* base is position:absolute via .card-face */
    transform: none;      /* base has rotateY(180deg) */
    inset: auto;
    border-radius: 1.4rem;
    min-height: 0;
    backface-visibility: visible;
    -webkit-backface-visibility: visible;
    opacity: 1;
  }

  /* --- Expanded content sizing --- */
  .flash-card.is-flipped .card-face {
    padding: 2.4rem 1.15rem 1.25rem;
    overflow-y: auto;
    border-radius: 1.4rem;
  }
  .flash-card.is-flipped h3,
  .flash-card.is-flipped .card-back h3 {
    font-size: 1.25rem;
    margin-top: 0.3rem;
  }
  .flash-card.is-flipped .spec-table {
    font-size: 0.95rem;
  }
  .flash-card.is-flipped .spec-table td {
    padding: 0.35rem 0.5rem;
  }
  .flash-card.is-flipped .badge,
  .flash-card.is-flipped .badge-cat,
  .flash-card.is-flipped .badge-full {
    font-size: 0.72rem;
    padding: 0.28rem 0.6rem;
  }
  .flash-card.is-flipped .fav-star,
  .flash-card.is-flipped .edit-pencil {
    width: 2rem;
    height: 2rem;
    top: 0.65rem;
  }
  .flash-card.is-flipped .fav-star { right: 0.65rem; }
  .flash-card.is-flipped .edit-pencil { left: 0.65rem; }
  .flash-card.is-flipped .fav-star svg,
  .flash-card.is-flipped .edit-pencil svg {
    width: 1rem;
    height: 1rem;
  }

  /* Flip animation: card opens from its tile position with a rotate+scale
     so it visibly "turns over" while growing. Keeps the metaphor of a
     flash card flip even though the enlarged state isn't a 3D flip. */
  @keyframes flashCardPop {
    from {
      opacity: 0;
      transform: translate(-50%, -50%) rotateY(-75deg) scale(0.85);
    }
    60% {
      opacity: 1;
      transform: translate(-50%, -50%) rotateY(8deg) scale(1.02);
    }
    to {
      opacity: 1;
      transform: translate(-50%, -50%) rotateY(0deg) scale(1);
    }
  }

  /* NO backdrop dim per V21 user spec — the rest of the screen stays at
     full brightness. Click-outside-to-close is wired at the document
     level in app.js, so a visible overlay isn't needed. We still prevent
     background scroll while a card is open so the user isn't scrolling
     the grid beneath the enlarged card. */
  body:has(.flash-card.is-flipped),
  body.has-flipped-card {
    overflow: hidden;
  }
}

/* ---- V21 fix: denser colour-code rows so more fit per page on phone ----
   Base .colour-row has 0.85rem padding + 1.2rem swatches. For training
   on a phone you want a quick scan — shrink padding, swatches, gaps, and
   drop the "Edit/Delete" buttons onto the name row (no wrap) so each row
   is a single line instead of two. Fits ~12 rows in a phone viewport. */
@media (max-width: 720px) {
  .colour-section {
    margin-bottom: 1.1rem;
  }
  .colour-section h3 {
    margin: 0 0 0.5rem;
    font-size: 0.95rem;
  }
  .colour-rows {
    gap: 0.3rem;
  }
  .colour-row {
    padding: 0.4rem 0.6rem;
    gap: 0.55rem;
    grid-template-columns: auto 1fr auto;
  }
  .colour-row .swatch {
    width: 0.95rem;
    height: 0.95rem;
  }
  .colour-row .swatch-row {
    gap: 0.2rem;
  }
  .colour-row-text {
    font-size: 0.82rem;
    line-height: 1.2;
  }
  .colour-row-text strong {
    font-size: 0.85rem;
  }
  .colour-row-text .hint {
    font-size: 0.7rem;
  }
  .colour-row-actions {
    grid-column: auto;
    justify-content: flex-end;
  }
  .colour-row-actions .btn-sm {
    padding: 0.25rem 0.5rem;
    font-size: 0.7rem;
    min-height: 28px;
  }
}

/* ---- V21 fix: Home page layout
   --------------------------------
   The 2-col grid I forced on mobile for flash-cards also hit the Home
   page's Team Updates feed (which uses .compact-grid). Revert that to
   single-column so update cards are readable full-width, and give the
   section headings proper breathing room. Favourites on home still uses
   .card-grid (flash-card grid) which stays 2-col per previous rules. */
@media (max-width: 520px) {
  /* Overturn my earlier .compact-grid 2-col override — update cards look
     awful wrapped to 4 lines in a half-width column. Applies to BOTH the
     Home page's feed AND the standalone Updates page's feed (the second
     one was missed in the original fix and caught in Phase 2 QA). */
  #homeUpdatesFeed.compact-grid,
  #updatesFeed.compact-grid {
    grid-template-columns: 1fr;
    gap: 0.55rem;
  }
  .home-block {
    margin-top: 1.1rem;
  }
  .home-block:first-of-type {
    margin-top: 0.35rem;
  }
  .home-block h3 {
    font-size: 1rem;
    margin-bottom: 0.45rem;
    padding: 0 0.1rem;
  }
  /* Section-header on Home was also stacking weirdly — pin it tight. */
  #home .section-header {
    margin-bottom: 0.3rem;
  }
  #home .section-header h2 {
    font-size: 1.35rem;
  }
  #home .section-header p {
    font-size: 0.78rem;
    margin: 0.1rem 0 0;
  }
  /* The update card itself — make sure badge + actions don't collide. */
  #homeUpdatesFeed .update-card {
    padding: 0.85rem 0.95rem;
  }
}

/* ======================================================================
   V21 — Team Dashboard mobile
   ======================================================================
   Desktop: 4-tile stat summary + 7-col table.
   Phone: 2×2 stat tiles, and the table collapses into a stacked-card list
   where each row becomes a self-contained block with labelled fields.
   The labels come from CSS ::before and the table's data- attributes —
   since the renderer already emits a real <table>, we use positional
   nth-child + inferred labels from the header row.
   ====================================================================== */
@media (max-width: 600px) {
  /* Stat summary — compact 2×2 instead of big stacked cards */
  #teamSummary.card-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: auto;
    gap: 0.55rem;
  }
  #teamSummary .reference-card {
    padding: 0.8rem 0.85rem;
    min-height: 0;
  }
  #teamSummary .reference-card h4 {
    font-size: 1.35rem;
    margin: 0 0 0.1rem;
  }
  #teamSummary .reference-card .hint,
  #teamSummary .reference-card p {
    font-size: 0.72rem;
  }

  /* Team table → stacked cards on phone */
  #teamTable {
    overflow: visible;
  }
  #teamTable table,
  #teamTable thead,
  #teamTable tbody,
  #teamTable tr,
  #teamTable td {
    display: block;
    width: 100%;
  }
  #teamTable thead {
    display: none;  /* Labels are injected per-cell via ::before */
  }
  #teamTable tr {
    margin-bottom: 0.6rem;
    padding: 0.75rem 0.85rem;
    border: 1px solid var(--line);
    border-radius: 0.9rem;
    background: var(--surface-soft);
  }
  #teamTable td {
    padding: 0.15rem 0;
    border: none;
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.6rem;
    font-size: 0.82rem;
  }
  /* Name is the headline of each card — no label, bigger font */
  #teamTable td:nth-of-type(1) {
    font-size: 0.98rem;
    font-weight: 600;
    color: var(--text-strong);
    margin-bottom: 0.25rem;
    padding-bottom: 0.35rem;
    border-bottom: 1px solid var(--line);
    justify-content: flex-start;
  }
  /* Labels for the remaining cells */
  #teamTable td:nth-of-type(2)::before { content: 'Role'; }
  #teamTable td:nth-of-type(3)::before { content: 'Venues'; }
  #teamTable td:nth-of-type(4)::before { content: 'Tests'; }
  #teamTable td:nth-of-type(5)::before { content: 'Average'; }
  #teamTable td:nth-of-type(6)::before { content: 'Training'; }
  #teamTable td:nth-of-type(7)::before { content: 'Last test'; }
  #teamTable td:nth-of-type(n+2)::before {
    color: var(--muted);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 500;
    flex-shrink: 0;
  }
  #teamTable .empty-row,
  #teamTable tr td[colspan] {
    display: block;
    text-align: center;
    color: var(--muted);
  }

  /* Section header on team dashboard compresses like others */
  #team .section-header h2 {
    font-size: 1.35rem;
  }
  #team .section-header p {
    font-size: 0.78rem;
  }
}

/* ======================================================================
   V21 — Profiles section (LM+ only)
   ======================================================================
   Browse-and-filter list of every account inside the current user's
   scope. Summary tiles per role at the top, then a role-grouped list of
   rows. Row click opens the existing account editor (adding stays in
   Admin per user spec).
   ====================================================================== */
.profiles-summary {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.55rem;
  margin-bottom: 1rem;
}
.profiles-summary-tile {
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 0.9rem;
  background: var(--surface-soft);
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.profiles-summary-tile strong {
  font-size: 1.5rem;
  color: var(--text-strong);
  line-height: 1;
}
.profiles-summary-tile span {
  font-size: 0.72rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.profiles-list { display: flex; flex-direction: column; gap: 1rem; }
.profiles-role-block h3 {
  margin: 0 0 0.45rem;
  font-size: 0.95rem;
  color: var(--text-strong);
}
.profiles-role-block h3 .hint {
  font-size: 0.75rem;
  font-weight: 400;
  margin-left: 0.35rem;
  color: var(--muted);
}
.profile-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.65rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  background: var(--surface-soft);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
  margin-bottom: 0.4rem;
}
.profile-row:hover {
  background: var(--surface-elev);
  border-color: var(--line-strong);
}
.profile-row-main { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.profile-row-main strong { font-size: 0.95rem; color: var(--text-strong); }
.profile-row-sub { font-size: 0.75rem; color: var(--muted); }
.profile-row-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  flex-shrink: 0;
  justify-content: flex-end;
  max-width: 55%;
}
.profile-chip {
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-size: 0.7rem;
  background: rgba(79, 155, 255, 0.08);
  color: var(--text);
  border: 1px solid rgba(79, 155, 255, 0.2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 16rem;
}
.profile-chip--group {
  background: rgba(38, 179, 164, 0.12);
  border-color: rgba(38, 179, 164, 0.3);
  font-weight: 600;
}
.account-activation-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.5rem;
  font-size: 0.72rem;
  font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
  letter-spacing: 0.05em;
  background: rgba(245, 158, 11, 0.15);
  border: 1px solid rgba(245, 158, 11, 0.4);
  color: #f59e0b;
  border-radius: 0.4rem;
  cursor: text;
  user-select: all;
  max-width: fit-content;
}
.account-row-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.35rem;
  align-items: center;
}
/* Password reveal control — tiny button + hidden-by-default chip */
.account-password {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
.acc-pw-toggle.btn-xs,
.btn-xs {
  padding: 0.2rem 0.55rem;
  font-size: 0.7rem;
  border-radius: 0.4rem;
  min-height: 0;
  line-height: 1.2;
}
.account-password-value {
  padding: 0.15rem 0.5rem;
  font-size: 0.72rem;
  font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
  letter-spacing: 0.03em;
  background: rgba(100, 116, 139, 0.15);
  border: 1px solid rgba(100, 116, 139, 0.35);
  color: var(--text);
  border-radius: 0.4rem;
  cursor: text;
  user-select: all;
}

/* Credential popup (shown after creating a new account) */
.credential-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0.5rem 0 1rem;
}
.credential-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 0.55rem;
  background: var(--surface-soft);
}
.credential-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  min-width: 7rem;
}
.credential-value {
  font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
  font-size: 0.9rem;
  color: var(--text);
  user-select: all;
  flex: 1;
  word-break: break-all;
}
.credential-value.credential-token {
  color: #f59e0b;
  letter-spacing: 0.05em;
}
.credential-actions {
  margin-top: 0.3rem;
}
.profile-chip--activation {
  background: rgba(245, 158, 11, 0.15);
  border-color: rgba(245, 158, 11, 0.4);
  color: #f59e0b;
  font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
  letter-spacing: 0.05em;
  cursor: text;
  user-select: all;      /* one click selects the whole code for easy copy */
}

@media (max-width: 520px) {
  .profiles-summary {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.4rem;
  }
  .profiles-summary-tile { padding: 0.55rem 0.7rem; }
  .profiles-summary-tile strong { font-size: 1.25rem; }
  .profile-row {
    flex-direction: column;
    align-items: stretch;
    gap: 0.4rem;
  }
  .profile-row-meta {
    max-width: 100%;
    justify-content: flex-start;
  }
  .profile-chip {
    font-size: 0.68rem;
    max-width: 100%;
  }
}

/* Nav "Manage" section — shown only if the user has any manage capability.
   The section heading inherits .nav-title so it visually matches siblings. */
.manage-section .nav-title {
  color: var(--accent);
}

/* ======================================================================
   V21 — Hamburger on the top-LEFT
   ======================================================================
   Moved the hamburger button out of .header-actions into the first slot
   of .app-header so it sits hard-left. Gives the menu icon prominence
   (where users expect it on mobile apps) and leaves room for venue pill
   and user chip to stretch across the right side. */
.hamburger--left {
  order: 0;
  flex-shrink: 0;
  margin-right: 0.1rem;
}
.app-header {
  gap: 0.75rem;
}

@media (max-width: 720px) {
  /* On phone, compress the header further so the hamburger, title pill,
     theme toggle and user chip all fit in a single row */
  .app-header {
    padding: 0.75rem 0.7rem 0.55rem;
    gap: 0.55rem;
  }
  .header-status {
    display: none;  /* Live Knowledge Base chip drops on phone */
  }
  .header-titles {
    padding: 0.55rem 0.75rem;
  }
}

/* ---- V21: Admin account search bar above the Existing Accounts list ---- */
.account-search {
  width: 100%;
  padding: 0.65rem 0.85rem;
  margin-bottom: 0.6rem;
  border-radius: 0.75rem;
  border: 1px solid var(--line);
  background: var(--surface-strong);
  color: var(--text);
  font-size: 0.9rem;
}
.account-search:focus {
  outline: 2px solid var(--accent-focus);
  outline-offset: 1px;
}

/* ======================================================================
   V21 — Clients drill-down (venue → tier → employees)
   ======================================================================
   Each venue in a brand block is a collapsible <details> card. Inside, two
   nested <details> tiers (Manager level / Staff) hold the employees with
   Edit/Delete. "+ Add" at each tier jumps to Admin pre-filled. */
.venue-drill-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 0.35rem;
}
.venue-drill {
  border: 1px solid var(--line);
  border-radius: 0.8rem;
  background: var(--surface-soft);
  overflow: hidden;
}
.venue-drill[open] {
  background: var(--surface-elev);
}
.venue-drill > summary {
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 0.9rem;
  cursor: pointer;
  font-size: 0.88rem;
}
.venue-drill > summary::-webkit-details-marker { display: none; }
.venue-drill > summary::after {
  content: '›';
  font-size: 1.2rem;
  color: var(--muted);
  transform: rotate(90deg);
  transition: transform 160ms ease;
}
.venue-drill[open] > summary::after {
  transform: rotate(270deg);
}
.venue-drill-label {
  font-weight: 600;
  color: var(--text-strong);
}
.venue-drill-body {
  padding: 0.3rem 0.7rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.venue-drill-actions {
  padding-top: 0.25rem;
  border-top: 1px solid var(--line);
  display: flex;
  gap: 0.4rem;
}

.venue-tier {
  border: 1px solid var(--line);
  border-radius: 0.65rem;
  background: var(--surface);
}
.venue-tier > summary {
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  font-size: 0.85rem;
}
.venue-tier > summary::-webkit-details-marker { display: none; }
.venue-tier > summary::after {
  content: '＋';
  color: var(--muted);
  transition: transform 160ms ease;
}
.venue-tier[open] > summary::after {
  content: '−';
}
.venue-tier-body {
  padding: 0.35rem 0.75rem 0.6rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.emp-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.6rem;
  border-radius: 0.55rem;
  background: var(--surface-soft);
  border: 1px solid var(--line);
}
.emp-main {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0;
}
.emp-main strong {
  font-size: 0.85rem;
  color: var(--text-strong);
}
.emp-main .hint {
  font-size: 0.7rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.emp-actions {
  display: flex;
  gap: 0.3rem;
  flex-shrink: 0;
}
.emp-actions .btn-sm {
  padding: 0.2rem 0.5rem;
  font-size: 0.7rem;
  min-height: 28px;
}
.venue-tier-add {
  align-self: flex-start;
  margin-top: 0.2rem;
}

/* ======================================================================
   V21 — Settings / Profiles / Clients mobile fit
   ======================================================================
   The three manager surfaces all spilled off-screen on phone. Stack the
   filter/search controls, tighten padding, let long brand/venue blocks
   breathe without horizontal scroll. */
@media (max-width: 640px) {
  /* Settings: the tile grid was 2-up — collapse to 1-up on small phones */
  #settings .grid.two {
    grid-template-columns: 1fr;
  }
  #settings .card {
    padding: 0.9rem;
  }
  #settings .input-group select,
  #settings .input-group input,
  #settings .input-group textarea {
    width: 100%;
  }
  #settings h3 {
    font-size: 0.95rem;
  }

  /* Profiles: controls stack, chips drop to newline, summary 2-col */
  #profiles .section-header .controls {
    flex-direction: column;
    gap: 0.45rem;
  }
  #profiles .section-header .controls > * {
    width: 100%;
  }

  /* Clients: the group card body has horizontal padding that, combined
     with nested venue details, can overflow. Shrink paddings. */
  #dataTab .group-card,
  #dataTab .brand-block {
    padding: 0.55rem 0.7rem;
  }
  #dataTab .group-body {
    padding: 0.55rem 0.25rem 0.75rem;
  }
  #dataTab .group-actions {
    flex-direction: column;
    align-items: stretch;
    gap: 0.35rem;
  }
  #dataTab .group-actions .btn-sm {
    width: 100%;
  }
  #dataTab .section-header .controls {
    flex-direction: column;
    gap: 0.45rem;
  }
  #dataTab .section-header .controls select {
    width: 100%;
  }
  /* Venue drill body: tighter tiers */
  .venue-drill-body { padding: 0.3rem 0.45rem 0.65rem; }
  .venue-tier-body { padding: 0.3rem 0.45rem 0.55rem; }
  .emp-row {
    flex-direction: column;
    align-items: stretch;
    gap: 0.35rem;
  }
  .emp-actions {
    justify-content: flex-end;
  }
}

/* ======================================================================
   V21 — Table Numbers (floor plan) compaction for phone
   ======================================================================
   The floor plan stage is 16:10 aspect-ratio which on a narrow phone can
   leave tables too small to tap and the edit toolbar overflows. On phone:
   • Stage widens to 4:3 so tables sit bigger relative to the viewport
   • Edit toolbar wraps to two lines with each control full-width
   • Floor tabs scroll horizontally instead of wrapping
   • Tables get a slightly larger min size + font bump so they're tappable
   • Legend + stats stack under the stage
   ====================================================================== */
@media (max-width: 600px) {
  /* Stage: taller aspect so tables aren't crushed by width */
  .fp-stage {
    aspect-ratio: 4 / 5;
    border-radius: 0.75rem;
  }
  /* Floor tabs: horizontal scroll strip, no wrap */
  .fp-tabs {
    overflow-x: auto;
    overflow-y: hidden;
    white-space: nowrap;
    flex-wrap: nowrap;
    gap: 0.3rem;
    padding-bottom: 0.4rem;
    margin-bottom: 0.4rem;
    scrollbar-width: thin;
  }
  .fp-tab {
    flex-shrink: 0;
    padding: 0.4rem 0.7rem;
    font-size: 0.78rem;
  }
  /* Edit toolbar wraps + fills row */
  .fp-edit-toolbar {
    flex-wrap: wrap;
    gap: 0.35rem;
    padding: 0.6rem;
  }
  .fp-edit-toolbar > * {
    flex: 1 1 45%;
    min-width: 0;
  }
  .fp-edit-toolbar .hint {
    margin-left: 0;
    flex: 1 1 100%;
    order: 99;
  }
  .fp-edit-toolbar button,
  .fp-edit-toolbar select,
  .fp-edit-toolbar input {
    min-height: 40px;
    font-size: 0.82rem;
  }
  /* Bigger tappable tables on phone */
  .fp-table {
    min-width: 54px;
    padding: 0.3rem 0.5rem 0.35rem;
  }
  .fp-table.fp-table-round {
    min-width: 52px;
    width: 52px;
    height: 52px;
  }
  .fp-table-number {
    font-size: 0.88rem;
  }
  .fp-seat-count {
    min-width: 1.3rem;
    height: 1.3rem;
    font-size: 0.72rem;
  }
  /* Legend + stats stack compactly under the stage */
  .fp-legend,
  .fp-stats {
    font-size: 0.8rem;
    padding: 0.6rem 0.75rem;
  }
  .fp-stats {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.35rem;
  }
  /* Section header compresses like other manager surfaces */
  #tables .section-header {
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
  }
  #tables .section-header h2 {
    font-size: 1.3rem;
  }
  #tables .section-header p {
    font-size: 0.78rem;
  }
  #tables .section-header > :last-child {
    width: 100%;
    display: flex;
    justify-content: flex-end;
  }
}

/* ==========================================================================
   Apple-style Edit-Layout inspector (v11 finish).
   Translucent card with hairline dividers; stroke-only tile icons; subtle
   accent-tinted hover; destructive actions tucked inside a "More" disclosure.
   ========================================================================== */
.fp-edit-toolbar {
  margin: 0.6rem 0 1.1rem;
}
.fp-inspector {
  background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02));
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 18px;
  padding: 1rem 1.1rem;
  box-shadow: 0 10px 24px -18px rgba(0,0,0,0.6), 0 1px 0 rgba(255,255,255,0.05) inset;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
[data-theme="light"] .fp-inspector {
  background: linear-gradient(180deg, rgba(255,255,255,0.92), rgba(255,255,255,0.72));
  border-color: rgba(15,23,42,0.08);
  box-shadow: 0 10px 24px -18px rgba(15,23,42,0.15), 0 1px 0 rgba(255,255,255,0.6) inset;
}
.fp-inspector-row {
  display: grid;
  grid-template-columns: minmax(160px, 220px) 1fr;
  gap: 1.3rem;
  align-items: center;
}
.fp-inspector-row--floor { align-items: center; }
.fp-inspector-label {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.fp-inspector-title {
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
}
.fp-inspector-sub {
  font-size: 0.78rem;
  color: var(--muted);
  letter-spacing: -0.005em;
}
.fp-inspector-divider {
  height: 1px;
  margin: 0.85rem 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.08), transparent);
}
[data-theme="light"] .fp-inspector-divider {
  background: linear-gradient(90deg, transparent, rgba(15,23,42,0.09), transparent);
}
.fp-inspector-tiles {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.fp-tile {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  width: 72px;
  min-height: 72px;
  padding: 0.55rem 0.4rem;
  border-radius: 14px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  color: var(--text);
  cursor: pointer;
  transition: transform 180ms ease, border-color 180ms ease, background 180ms ease, box-shadow 180ms ease;
}
[data-theme="light"] .fp-tile {
  background: rgba(255,255,255,0.85);
  border-color: rgba(15,23,42,0.08);
}
.fp-tile:hover {
  transform: translateY(-1px);
  border-color: var(--accent);
  background: rgba(59, 130, 246, 0.08);
  box-shadow: 0 4px 14px -8px rgba(59,130,246,0.35);
}
.fp-tile:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.fp-tile.active,
.fp-tile[aria-pressed="true"] {
  border-color: var(--accent);
  background: rgba(59, 130, 246, 0.14);
  color: var(--accent);
}
.fp-tile-icon {
  width: 22px;
  height: 22px;
  color: currentColor;
}
.fp-tile-label {
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: inherit;
}
.fp-inspector-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.5rem;
  align-items: center;
  position: relative;
}
.fp-link-btn {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 0.45rem 0.8rem;
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--accent);
  border-radius: 10px;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
  letter-spacing: -0.005em;
}
.fp-link-btn:hover { background: rgba(59, 130, 246, 0.08); }
.fp-link-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.fp-more { position: relative; }
.fp-more summary {
  list-style: none;
  cursor: pointer;
}
.fp-more summary::-webkit-details-marker { display: none; }
.fp-more[open] > summary { background: rgba(59, 130, 246, 0.10); }
.fp-more-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 0.3rem);
  min-width: 220px;
  background: var(--surface);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 12px;
  padding: 0.35rem;
  box-shadow: 0 18px 40px -18px rgba(0,0,0,0.6), 0 1px 0 rgba(255,255,255,0.04) inset;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
[data-theme="light"] .fp-more-menu {
  background: #fff;
  border-color: rgba(15,23,42,0.08);
  box-shadow: 0 18px 40px -18px rgba(15,23,42,0.2);
}
.fp-more-item {
  appearance: none;
  background: transparent;
  border: 0;
  text-align: left;
  padding: 0.55rem 0.7rem;
  border-radius: 8px;
  font-size: 0.88rem;
  color: var(--text);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.fp-more-item:hover { background: rgba(59, 130, 246, 0.08); }
.fp-more-item--danger { color: #e1555c; }
.fp-more-item--danger:hover { background: rgba(225,85,92,0.1); }

@media (max-width: 720px){
  .fp-inspector { padding: 0.9rem; border-radius: 16px; }
  .fp-inspector-row { grid-template-columns: 1fr; gap: 0.6rem; }
  .fp-inspector-actions { justify-content: flex-start; }
  .fp-tile { width: 68px; min-height: 68px; }
  .fp-more-menu { right: auto; left: 0; }
}

/* Original Tables-V2 reset banner continues below. */
/* (v7: removed the Expand / fp-landscape takeover block. The Tables list
   makes the rotated-fullscreen escape hatch redundant — a bartender now
   finds a table by searching a number instead of squinting at the plan.
   Selector `body.fp-landscape-open` is still stripped defensively by
   showSection() so legacy state can't lock the viewport.) */
.fp-stage-wrap {
  position: relative;
}

/* ==========================================================================
   Tables V2 — search, zone chips, list-first layout.
   Replaces the old "floor plan is the only surface" model with a fast
   bartender-focused UI: type a number or pick a zone, get the answer.
   ========================================================================== */
.tables-toolbar {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) 2fr;
  gap: 0.9rem;
  align-items: center;
  margin: 0.6rem 0 0.9rem;
}
.tables-search {
  position: relative;
  display: flex;
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0 0.9rem;
  min-height: 2.9rem;
  transition: border-color 140ms ease, box-shadow 140ms ease;
}
.tables-search:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.12);
}
.tables-search svg {
  flex: 0 0 auto;
  color: var(--muted);
  margin-right: 0.55rem;
}
.tables-search input {
  flex: 1 1 auto;
  border: 0;
  background: transparent;
  color: var(--text);
  font-size: 1rem;
  min-height: 2.6rem;
  outline: none;
}
.tables-search input::-webkit-search-cancel-button { display: none; }
.tables-search-clear {
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  width: 1.8rem;
  height: 1.8rem;
  border-radius: 999px;
}
.tables-search-clear:hover { background: var(--surface-elev); color: var(--text); }

.tables-zone-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  justify-content: flex-end;
}
.tables-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 140ms ease, background 140ms ease, transform 140ms ease;
}
.tables-chip:hover { transform: translateY(-1px); border-color: var(--accent); }
.tables-chip.is-active {
  background: var(--surface-inverse);
  color: var(--text-on-accent);
  border-color: var(--surface-inverse);
}
.tables-chip-swatch {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
}
.tables-chip-count {
  font-size: 0.78rem;
  color: var(--muted);
  background: var(--surface-elev);
  padding: 0.08rem 0.5rem;
  border-radius: 999px;
  min-width: 1.5rem;
  text-align: center;
}
.tables-chip.is-active .tables-chip-count {
  background: rgba(255,255,255,0.18);
  color: var(--text-on-accent);
}

.tables-layout {
  display: grid;
  grid-template-columns: minmax(260px, 340px) 1fr;
  gap: 1.1rem;
  align-items: start;
}
.tables-list-wrap {
  max-height: 60vh;
  overflow-y: auto;
  padding-right: 0.4rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.tables-zone-group header {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0 0.1rem 0.3rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 0.45rem;
}
.tables-zone-group header h3 {
  font-size: 0.94rem;
  font-weight: 700;
  margin: 0;
  letter-spacing: -0.01em;
}
.tables-zone-group header .hint { font-size: 0.78rem; margin-left: auto; }
.tables-zone-dot {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.15);
}
.tables-zone-group ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.tables-row {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 0.7rem;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: border-color 140ms ease, transform 140ms ease, background 140ms ease;
}
.tables-row:hover { transform: translateX(2px); border-color: var(--accent); background: var(--surface-elev); }
.tables-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tables-row-num {
  flex: 0 0 auto;
  width: 2.3rem;
  height: 2.3rem;
  border-radius: 12px;
  display: grid;
  place-items: center;
  color: white;
  font-weight: 800;
  font-size: 0.95rem;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.15);
}
.tables-row-meta { display: flex; flex-direction: column; gap: 0.1rem; }
.tables-row-meta strong { font-size: 0.95rem; }
.tables-row-meta .hint { font-size: 0.78rem; }

.tables-empty {
  padding: 1.2rem;
  border: 1px dashed var(--line);
  border-radius: 14px;
  color: var(--muted);
  background: var(--surface);
}
.tables-empty strong { display: block; margin-bottom: 0.3rem; color: var(--text); }

/* Stage search feedback — pulse matched tables, dim the rest.
   Dim opacity lifted to 0.4 (Sofia v7 P2) so a single matched table on a
   pale-floor background still clears WCAG 1.4.3 minimum contrast. */
.fp-table.is-dimmed { opacity: 0.4; filter: saturate(0.5); }
.fp-table.is-flagged { animation: tables-pulse 1.6s ease-in-out infinite; z-index: 2; outline: 2px solid rgba(59, 130, 246, 0.9); outline-offset: 2px; }
.fp-table.is-jumped {
  animation: tables-jump 1.6s ease-out 1;
  z-index: 3;
  scroll-margin-top: 120px;
}
@keyframes tables-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.55); }
  50%      { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
}
@keyframes tables-jump {
  0%   { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.85); transform: scale(1); }
  20%  { box-shadow: 0 0 0 18px rgba(59, 130, 246, 0); transform: scale(1.15); }
  100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); transform: scale(1); }
}
@media (prefers-reduced-motion: reduce){
  .fp-table.is-flagged, .fp-table.is-jumped { animation: none; outline: 2px solid var(--accent); outline-offset: 2px; }
}

/* Mobile — stack list on top, stage below. Search + chips become 1-column.
   Marcus-v7 P1: removed the nested-scroll max-height (conflicted with page
   scroll on phones) and bumped tap targets to ≥48px (Apple HIG + WCAG 2.5.5). */
@media (max-width: 720px){
  .tables-toolbar { grid-template-columns: 1fr; }
  .tables-zone-chips { justify-content: flex-start; }
  .tables-layout { grid-template-columns: 1fr; }
  .tables-list-wrap { max-height: none; padding-right: 0; }
  .tables-row { min-height: 48px; padding: 0.7rem 0.8rem; }
  .tables-row-num { width: 2.75rem; height: 2.75rem; font-size: 1rem; }
  .tables-chip { min-height: 40px; padding: 0.5rem 1rem; }
}
@media (max-width: 600px){
  /* Venue-switcher label is redundant next to an already-obvious dropdown at
     phone widths — Sofia + Marcus v7 P1. Keep the `aria-label` on the select
     so screen readers still name the control. */
  .venue-switcher-label { display: none; }
}

/* Screen-reader-only utility class for aria-live status regions.
   Standard "visually hidden but focusable" pattern. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Visible renderer-failure banner — only shown to users with manager-level
   access (staff see a clean boot regardless). Keeps the blast radius of any
   future renderer regression small: admins notice, staff don't. */
.render-diag-banner {
  background: #7a0f19;
  color: #fff;
  padding: 0.9rem 1.2rem 0.9rem 1rem;
  border-bottom: 1px solid #5a0a12;
  font-size: 0.9rem;
  position: relative;
}
.render-diag-banner strong { display: block; margin-bottom: 0.35rem; }
.render-diag-banner ul { margin: 0; padding-left: 1.1rem; }
.render-diag-banner code { background: rgba(255,255,255,0.12); padding: 0 0.3rem; border-radius: 4px; font-size: 0.82rem; }
.render-diag-close {
  position: absolute;
  top: 0.6rem;
  right: 0.7rem;
  background: transparent;
  border: 0;
  color: #fff;
  cursor: pointer;
  font-size: 1rem;
  opacity: 0.75;
}
.render-diag-close:hover { opacity: 1; }

@media (max-width: 720px) {
}

/* ======================================================================
   V21 — Floor plan overhaul
   ======================================================================
   • Door glyph with swing direction
   • Step / elevation marker with diagonal stripes + cm label
   • Visual colour picker (swatch grid) replaces free-form hex input
   • Zone manager modal for add / rename / recolour / delete
   • Grouped toolbar: Add group + Floor group, each row of icon-first buttons
   ====================================================================== */

/* ---- Door feature (SVG glyph with rotation by .fp-door-dir-*) ---- */
.fp-feature.fp-door {
  background: transparent;
  border: none;
  box-shadow: none;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #e2e8f0;
  transform: translate(-50%, -50%);
}
.fp-door .fp-door-icon {
  width: 100%;
  height: 100%;
  display: block;
}
.fp-door-dir-n .fp-door-icon { transform: rotate(0deg); }
.fp-door-dir-e .fp-door-icon { transform: rotate(90deg); }
.fp-door-dir-s .fp-door-icon { transform: rotate(180deg); }
.fp-door-dir-w .fp-door-icon { transform: rotate(270deg); }
/* P0-4: double-door rendering now lives in the SVG itself — see
   renderFeature() in floorPlan.js. The old filter:drop-shadow hack was
   invisible at real sizes and has been removed. */
.fp-door-label {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translate(-50%, 0.2rem);
  font-size: 0.65rem;
  color: #e2e8f0;
  background: rgba(0,0,0,0.5);
  padding: 0.1rem 0.35rem;
  border-radius: 0.3rem;
  white-space: nowrap;
  pointer-events: none;
}
[data-theme="light"] .fp-door {
  color: #1e293b;
}
[data-theme="light"] .fp-door-label {
  color: #1e293b;
  background: rgba(255,255,255,0.7);
}

/* ---- Step / elevation feature ---- */
.fp-feature.fp-step {
  background: repeating-linear-gradient(
    45deg,
    rgba(251, 191, 36, 0.35) 0 6px,
    rgba(251, 191, 36, 0.55) 6px 12px
  );
  border: 1px solid rgba(251, 191, 36, 0.9);
  border-radius: 0.3rem;
  color: #78350f;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translate(-50%, -50%);
  padding: 0.15rem 0.3rem;
  font-weight: 700;
}
.fp-step-stripes {
  display: none; /* the bg already provides the stripes; keep node for future */
}
.fp-step-label {
  font-size: 0.7rem;
  color: #1f2937;
  background: rgba(255,255,255,0.75);
  padding: 0.1rem 0.4rem;
  border-radius: 0.3rem;
  white-space: nowrap;
  letter-spacing: 0.02em;
}
[data-theme="dark"] .fp-step-label {
  color: #fde68a;
  background: rgba(15,23,42,0.75);
}

/* ---- Visual colour picker (shared by feature + zone editor) ---- */
.fp-colour-picker {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  width: 100%;
}
.fp-swatch-grid {
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  gap: 0.3rem;
}
.fp-swatch {
  appearance: none;
  border: 2px solid transparent;
  border-radius: 0.35rem;
  width: 100%;
  aspect-ratio: 1;
  cursor: pointer;
  padding: 0;
  transition: transform 100ms ease, border-color 100ms ease;
}
.fp-swatch:hover {
  transform: scale(1.08);
}
.fp-swatch.is-selected {
  border-color: #fff;
  box-shadow: 0 0 0 2px var(--accent);
}
[data-theme="light"] .fp-swatch.is-selected {
  border-color: #0f172a;
}
.fp-hex-input {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.75rem;
}
.fp-hex-input span {
  color: var(--muted);
}
.fp-hex-input input {
  padding: 0.4rem 0.55rem;
  border-radius: 0.4rem;
  border: 1px solid var(--line);
  background: var(--surface-strong);
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, monospace;
}

/* ---- Zone manager modal ---- */
.fp-zone-list {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  max-height: 52vh;
  overflow-y: auto;
  padding: 0.2rem;
  margin-bottom: 0.75rem;
}
.fp-zone-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    "swatch name delete"
    "picker picker picker";
  gap: 0.45rem 0.55rem;
  align-items: center;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  background: var(--surface-soft);
}
.fp-zone-row .fp-sw {
  grid-area: swatch;
  width: 1.3rem;
  height: 1.3rem;
  border-radius: 0.3rem;
  border: 1px solid var(--line);
}
.fp-zone-row .fp-zone-name {
  grid-area: name;
  padding: 0.35rem 0.55rem;
  border-radius: 0.4rem;
  border: 1px solid var(--line);
  background: var(--surface-strong);
  color: var(--text);
}
.fp-zone-row .fp-zone-delete {
  grid-area: delete;
  min-height: 32px;
}
.fp-zone-row .fp-colour-picker {
  grid-area: picker;
}
.fp-zone-add-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  align-items: center;
  padding: 0.6rem 0.7rem;
  border: 1px dashed var(--line);
  border-radius: 0.6rem;
  background: var(--surface-soft);
  margin-bottom: 0.75rem;
}
.fp-zone-add-row input[type="text"] {
  flex: 1 1 10rem;
  min-width: 0;
  padding: 0.45rem 0.6rem;
  border-radius: 0.4rem;
  border: 1px solid var(--line);
  background: var(--surface-strong);
  color: var(--text);
}
.fp-zone-add-row .fp-colour-picker {
  flex: 1 1 14rem;
}
.fp-zone-add-row button {
  flex-shrink: 0;
}

/* ---- Grouped toolbar ---- */
.fp-edit-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 0.75rem 0.9rem;
  margin-bottom: 0.65rem;
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  background: var(--surface-soft);
}
.fp-toolbar-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.55rem;
  border-radius: 0.65rem;
  background: var(--surface);
  border: 1px solid var(--line);
}
.fp-toolbar-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-right: 0.2rem;
}
.fp-toolbar-hint {
  flex: 1 1 100%;
  font-size: 0.72rem;
  color: var(--muted);
  margin-top: 0.2rem;
}
.fp-tool-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.55rem;
  font-size: 0.78rem;
  min-height: 32px;
}
.fp-tool-icon {
  font-size: 0.95rem;
  line-height: 1;
  color: var(--accent);
}
.fp-tool-btn.active,
.fp-tool-btn[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}
.fp-tool-btn.active .fp-tool-icon {
  color: var(--accent-strong);
}

/* ---- Hidden-field helpers in the edit modal ---- */
.fp-door-only.hidden,
.fp-step-only.hidden,
.fp-marker-only.hidden {
  display: none !important;
}

/* ---- Mobile polish for the toolbar ---- */
@media (max-width: 600px) {
  .fp-edit-toolbar {
    gap: 0.4rem;
    padding: 0.55rem;
  }
  .fp-toolbar-group {
    flex: 1 1 100%;
    justify-content: flex-start;
  }
  .fp-toolbar-group .fp-tool-btn {
    flex: 1 1 auto;
  }
  .fp-swatch-grid {
    grid-template-columns: repeat(6, 1fr);
  }
  .fp-zone-row {
    grid-template-columns: auto 1fr auto;
    padding: 0.5rem 0.55rem;
  }
  .fp-zone-add-row {
    flex-direction: column;
    align-items: stretch;
  }
  .fp-zone-add-row input[type="text"],
  .fp-zone-add-row .fp-colour-picker {
    flex: 1 1 100%;
  }
}

/* ======================================================================
   V21 — Floor plan V2 polish pass
   ======================================================================
   P1-6  SVG icons in the toolbar (overrides Unicode glyph rules)
   P1-8  Step default height bumped → label pill no longer swamps stripes
   P1-9  Door label never clips at the stage edge (smart positioning)
   P1-10 Duplicate flash animation on the new object
   P1-11 Tap targets ≥ 44px on mobile (buttons + resize handles)
   P1-12 Toolbar hint inline on desktop, own-line on mobile
   P1-19 Landscape takeover keeps the edit toolbar reachable
   P1-20 Edit-layout is the primary manager CTA (accent tint)
   P1-21 Delete Floor has a visual separator from the Floor group
   P1-16 Hex input `.is-error` state
   ====================================================================== */

/* P1-6 — the toolbar icon is now an SVG, not a text glyph. Make sure the
   sizing + colour match the button text. */
.fp-tool-icon {
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
  color: var(--accent);
}
.fp-tool-btn.active .fp-tool-icon,
.fp-tool-btn[aria-pressed="true"] .fp-tool-icon {
  color: var(--accent-strong);
}
.fp-tool-btn-danger .fp-tool-icon {
  color: #ef4444;
}

/* P1-8 — step label adapts to step size. Thin steps shift the label above
   the stripes; tall enough steps keep it inline centered. Stripes are always
   visible because the label is small + padded. */
.fp-feature.fp-step {
  padding: 0.1rem 0.25rem;
  min-height: 14px;
}
.fp-step-label {
  font-size: 0.68rem;
  padding: 0.08rem 0.35rem;
  border-radius: 0.3rem;
  backdrop-filter: blur(2px);
}

/* P1-9 — door label sits BELOW when there's room, but flips ABOVE when the
   door is near the stage bottom edge. Smart placement via CSS custom prop
   `--door-label-flip` set via JS when the door is below 85% Y.
   Fallback: always below, but `overflow: visible` on the door wrapper so
   the label isn't clipped (the stage still clips, but with a 0.2rem margin
   that we give it via the label's transform). */
.fp-feature.fp-door {
  overflow: visible;
}
.fp-door-label {
  top: 100%;
  transform: translate(-50%, 0.15rem);
  pointer-events: none;
  max-width: 12rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* P1-10 — brief pulsing ring on a just-duplicated object so the user sees
   where the clone landed. */
.fp-just-duplicated {
  animation: fpDuplicatePulse 900ms ease-out both;
  z-index: 10;
}
@keyframes fpDuplicatePulse {
  0%   { box-shadow: 0 0 0 0 rgba(79, 155, 255, 0.6); }
  50%  { box-shadow: 0 0 0 10px rgba(79, 155, 255, 0.0); }
  100% { box-shadow: 0 0 0 0 rgba(79, 155, 255, 0.0); }
}

/* P1-11 — tap targets. Desktop stays compact, mobile bumps to 44px for
   toolbar buttons AND resize handles. Compound selectors (`.cls.cls`) bump
   specificity above the earlier `.fp-edit-toolbar button` rule (0,1,1). */
.fp-tool-btn.fp-tool-btn {
  min-height: 36px;
}
@media (max-width: 720px), (pointer: coarse) {
  .fp-edit-toolbar .fp-tool-btn.fp-tool-btn {
    min-height: 44px;
    padding: 0.5rem 0.75rem;
  }
  .fp-stage .fp-resize-handle {
    width: 16px;
    height: 16px;
    margin: -3px;  /* visually stay aligned with the corner */
  }
  .fp-zone-row .fp-zone-delete {
    min-height: 44px;
    min-width: 44px;
  }
}

/* P1-12 — toolbar hint inline on desktop, own-line on mobile. */
.fp-toolbar-hint {
  flex: 0 1 auto;
  margin-left: auto;
}
@media (max-width: 720px) {
  .fp-toolbar-hint {
    flex: 1 1 100%;
    margin-left: 0;
  }
}

/* P1-19 — in landscape-rotated phone mode, keep the edit toolbar visible.
   The older rule hid every sibling of .fp-stage-wrap; scope it so the
   toolbar stays on screen when edit mode is on. */
@media (max-width: 900px) and (orientation: landscape) {
  #tables.fp-landscape .fp-edit-toolbar {
    display: flex !important;
    position: fixed;
    top: 0.5rem;
    left: 0.5rem;
    right: 0.5rem;
    z-index: 100;
    max-height: 45vh;
    overflow-y: auto;
    background: rgba(15, 23, 42, 0.95);
  }
}

/* P1-20 — the "Edit layout" button is the primary manager CTA. Use accent
   styling so it stands apart from "Expand" next to it. */
#fpEditToggle {
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
#fpEditToggle:hover {
  background: var(--accent-soft);
}

/* P1-21 — Delete Floor gets a visual divider so it's not just another ghost
   button in a row. `button.danger` sets `border: 1px solid` — the double-
   class selector below bumps specificity to (0,2,0) so our dashed divider
   wins on both border-style and border-color. */
.fp-tool-btn-danger.fp-tool-btn-danger {
  margin-left: 0.5rem;
  border-top-style: solid;
  border-right-style: solid;
  border-bottom-style: solid;
  border-left-style: dashed;
  border-left-width: 1px;
  border-left-color: var(--line);
  padding-left: 0.75rem;
}
@media (max-width: 720px) {
  .fp-tool-btn-danger.fp-tool-btn-danger {
    margin-left: 0;
    border-left-style: solid;
    margin-top: 0.4rem;
    border-top-style: dashed;
    border-top-width: 1px;
    border-top-color: var(--line);
    padding-top: 0.5rem;
    padding-left: 0.75rem;
    flex: 1 1 100% !important;
  }
}

/* P1-16 — hex input error tint when the user types garbage. */
.fp-hex-input input.is-error,
.fp-zone-add-row input.is-error,
#fpfNumber.is-error,
#fpfNewZoneName.is-error,
#fpPromptInput.is-error {
  border-color: #ef4444;
  box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.18);
}

/* Palette is now 12 entries — switch mobile from 6 to 4 columns so each
   swatch stays ≥ 48px (tap-target friendly). */
.fp-swatch-grid {
  grid-template-columns: repeat(6, 1fr);
}
@media (max-width: 520px) {
  .fp-swatch-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 0.4rem;
  }
  .fp-swatch {
    min-height: 40px;
  }
}

/* ======================================================================
   V21.3 — Home dashboard upgrade
   ======================================================================
   Replaced the sparse "Home" header + Updates + Favourites with a
   personalised dashboard: greeting hero, quick-action tiles, training
   stat tiles, then the existing Updates + Favourites blocks. Fills the
   desktop viewport without looking empty, and the hero compresses
   cleanly on phone.
   ====================================================================== */
.home-hero {
  padding: 1.25rem 1.35rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 1.1rem;
  background: linear-gradient(135deg, rgba(79, 155, 255, 0.12), rgba(38, 179, 164, 0.1));
  margin-bottom: 1.1rem;
}
.home-hero-copy .eyebrow {
  margin: 0 0 0.25rem;
  font-size: 0.65rem;
}
.home-hero-title {
  margin: 0 0 0.3rem;
  font-size: 1.6rem;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--text-strong);
}
.home-hero-sub {
  margin: 0;
  color: var(--muted);
  font-size: 0.9rem;
}

.home-quick-actions-block,
.home-stats-block {
  margin-top: 1rem;
}
.home-quick-actions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.7rem;
}
.home-qa-card {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.85rem 0.95rem;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  cursor: pointer;
  text-align: left;
  transition: background 120ms ease, border-color 120ms ease, transform 120ms ease;
  color: inherit;
}
.home-qa-card:hover {
  background: var(--surface-elev);
  border-color: var(--accent);
  transform: translateY(-1px);
}
.home-qa-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.home-qa-icon {
  display: grid;
  place-items: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 0.55rem;
  background: rgba(79, 155, 255, 0.15);
  color: var(--accent);
  flex-shrink: 0;
}
.home-qa-icon svg {
  width: 1.2rem;
  height: 1.2rem;
}
.home-qa-text {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0;
}
.home-qa-text strong {
  font-size: 0.95rem;
  color: var(--text-strong);
}
.home-qa-text .hint {
  font-size: 0.72rem;
}

.home-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0.6rem;
}
.home-stat-tile {
  padding: 0.8rem 0.95rem;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.home-stat-tile strong {
  font-size: 1.55rem;
  line-height: 1.1;
  color: var(--text-strong);
  letter-spacing: -0.01em;
}
.home-stat-label {
  font-size: 0.78rem;
  color: var(--text);
  font-weight: 500;
}
.home-stat-tile .hint {
  font-size: 0.7rem;
}

@media (max-width: 520px) {
  .home-hero {
    padding: 1rem 1rem 0.95rem;
    margin-bottom: 0.8rem;
  }
  .home-hero-title {
    font-size: 1.3rem;
  }
  .home-quick-actions {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
  }
  .home-qa-card {
    padding: 0.7rem 0.75rem;
  }
  .home-qa-icon {
    width: 1.9rem;
    height: 1.9rem;
  }
  .home-qa-text strong {
    font-size: 0.88rem;
  }
  .home-qa-text .hint {
    font-size: 0.68rem;
  }
  .home-stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
  }
  .home-stat-tile strong {
    font-size: 1.3rem;
  }
  .home-stat-label {
    font-size: 0.7rem;
  }
}

/* ======================================================================
   V21.3 — Flash card back-face badge collision fix (desktop + tablet)
   ======================================================================
   On viewports wider than 520px the back face kept the same top-left
   badge alignment as the legacy layout, but the edit pencil (top:0.55rem
   left:0.55rem, ~2rem wide) overlapped the first badge on the back —
   so users saw "ULL SPEC" with the leading F clipped. Centering the
   back-face titles matches the front's centered look AND avoids the
   pencil. Mobile already centers via existing rules.
   ====================================================================== */
@media (min-width: 521px) {
  .flash-card .card-back .card-titles {
    justify-content: center;
    text-align: center;
    padding: 0 2.2rem;  /* clear space for pencil (left) + fav star (right) */
  }
  .flash-card .card-back h3 {
    padding: 0 1.2rem;   /* don't let long titles touch the icons */
  }
}

/* ======================================================================
   V21.3 — Phone header restructure (venue bar on top)
   ======================================================================
   Before: on phones the venue switcher lived inside .header-titles and the
   long venue label ("Manahatta - Manahatta Greek Street (Leeds)") wrapped
   into 4 lines, pushing the header ~200px tall before any app content
   appeared. Now the header stacks into two rows on phones:
       Row 1:  full-width venue bar (the switcher pill stretches edge-to-edge)
       Row 2:  hamburger │ name+role │ theme + user chip
   The redundant big-text venue repeat in .header-main is hidden on phones
   since the pill already shows it.
   Kicks in at the same 600px breakpoint as the other phone tweaks so the
   narrow iPad in portrait keeps the desktop arrangement.
   ====================================================================== */
@media (max-width: 600px) {
  .app-header {
    display: grid;
    /* minmax(0, 1fr) (not bare 1fr) lets the middle column shrink below
       its content's intrinsic size. Phase 2 QA caught that with bare
       1fr, the venue row (containing a native <select> whose intrinsic
       min-content = ~536px from the longest 47-char venue name) was
       blowing the header + entire app wider than the 375px viewport. */
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "venue venue  venue"
      "burger titles actions";
    align-items: center;
    gap: 0.5rem;
    padding: 0.7rem 0.75rem;
    min-width: 0;
    max-width: 100vw;
    overflow: hidden;             /* belt-and-braces against any other
                                    content that tries to exceed viewport */
  }
  .hamburger        { grid-area: burger; }
  .header-actions   { grid-area: actions; gap: 0.4rem; }

  /* The venue switcher is inside .header-titles, so pull the whole titles
     column into the top "venue" row and let it fill width. The .header-
     titles wrapper still shows the switcher; main/sub are hidden below. */
  .header-titles {
    grid-area: venue;
    min-width: 0;                 /* Phase 2 QA fix: the native <select>
                                    intrinsic min-content = ~536px from the
                                    longest 47-char venue name. With a bare
                                    grid-row-spanning element, that pushed
                                    the whole header + main wider than the
                                    375px viewport. Two-part fix:
                                    (1) min-width:0 lets flex children shrink
                                    (2) max-width caps the row-spanning cell
                                    at the container's inner width. */
    max-width: 100%;
    overflow: hidden;
    padding: 0 !important;
    border: none !important;
    border-radius: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
  }

  /* Full-width, tappable switcher pill. */
  .venue-switcher,
  .venue-switcher:not([hidden]) {
    display: flex;
    width: 100%;
    min-width: 0;                 /* see above — same reason */
    align-items: center;
    gap: 0.45rem;
    padding: 0.55rem 0.85rem;
    border-radius: 0.95rem;
    background: var(--surface-soft);
    border: 1px solid var(--line);
    margin-bottom: 0 !important;
  }
  .venue-switcher-label {
    flex-shrink: 0;
  }
  .venue-switcher select {
    flex: 1 1 0;
    min-width: 0;
    width: 100%;
    max-width: 100%;
    /* Phase 2 QA: the select shows one long selected-option label; let
       the chrome truncate it visually with ellipsis instead of growing. */
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    padding: 0.45rem 2rem 0.45rem 0.7rem;
    font-size: 0.85rem;
    background-color: transparent;
    border: none;
  }

  /* The big bold venue name + subtitle now live in the pill — hide the
     redundant copies in .header-titles so row 1 stays short. */
  .header-titles .eyebrow,
  .header-main,
  .header-sub {
    display: none;
  }

  /* Row 2: keep the theme toggle + user chip compact so the row fits. */
  .header-actions .header-status {
    display: none;   /* "Live Knowledge Base" is dev-only fluff on phones */
  }

  /* A thin second-row "you are signed in as X" hint so users don't lose
     role context (since headerSub is hidden). Populated by header.js. */
  .header-titles::after {
    content: '';
    grid-area: titles;
  }
}

/* ======================================================================
   V21.3 — Spec Test landing redesign
   ======================================================================
   Replaced the three unlabelled dropdowns with a two-column setup panel:
   labelled controls on the left, "How grading works" panel on the right.
   Fills the desktop viewport, stacks to single column on phone.
   ====================================================================== */
.spec-test-setup {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 1.25rem;
  margin-bottom: 1rem;
}
.spec-test-setup-form h3,
.spec-test-hint-panel h3 {
  margin: 0 0 0.75rem;
  font-size: 1rem;
}
.spec-test-setup-form .input-group {
  margin-bottom: 0.9rem;
}
.spec-test-setup-form .input-group .hint {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.72rem;
}
.spec-test-start-btn {
  width: 100%;
  margin-top: 0.3rem;
}

.spec-test-hint-panel {
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: 0.95rem;
  background: var(--surface-soft);
}
.spec-test-hint-panel ul {
  margin: 0;
  padding-left: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.spec-test-hint-panel li {
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--text);
}
.spec-test-hint-panel li strong {
  color: var(--text-strong);
}

@media (max-width: 760px) {
  .spec-test-setup {
    grid-template-columns: 1fr;
    gap: 0.85rem;
  }
  .spec-test-hint-panel {
    padding: 0.95rem 1rem;
  }
  .spec-test-hint-panel li {
    font-size: 0.8rem;
  }
}

/* ======================================================================
   V21.3 — Leaderboard filter row
   ======================================================================
   Three filters inline on desktop, stacked on phone. Each select has a
   visible label above it (the "controls" pattern used to hide labels
   since the selects carried aria-label only — QA found that cryptic).
   ====================================================================== */
.leaderboard-filters {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.75rem;
  margin-bottom: 1rem;
}
.leaderboard-filter {
  margin: 0;
}
.leaderboard-filter span {
  display: block;
  margin-bottom: 0.3rem;
  font-size: 0.75rem;
  color: var(--muted);
  font-weight: 500;
}
@media (max-width: 600px) {
  .leaderboard-filters {
    grid-template-columns: 1fr;
    gap: 0.55rem;
    margin-bottom: 0.7rem;
  }
}

/* ======================================================================
   V21.3 — Team Dashboard summary tile height
   ======================================================================
   The 4 stat tiles reused .card-grid (grid-auto-rows: 17rem) which is
   sized for flash cards. On the Team Dashboard they ended up as giant
   empty boxes with the number + label in the top-left. Cap the row
   height to content and tighten padding so tiles look like dashboard
   stats, not flashcard placeholders.
   ====================================================================== */
#teamSummary.card-grid {
  grid-auto-rows: auto;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.75rem;
  margin-bottom: 1rem;
}
#teamSummary.card-grid .reference-card {
  min-height: 0;
  padding: 0.95rem 1.1rem;
}
#teamSummary.card-grid .reference-card h4 {
  margin: 0 0 0.15rem;
  font-size: 1.6rem;
  letter-spacing: -0.01em;
  color: var(--text-strong);
}
#teamSummary.card-grid .reference-card .hint,
#teamSummary.card-grid .reference-card p {
  margin: 0;
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ---------------------------------------------------------------------------
   Reduced-motion — WCAG 2.3.3 / vestibular safety.
   Previously every transition, flash-card flip, and hover-lift animated at
   full speed regardless of user preference. This block collapses all timing
   down to ~0 so the interface still responds (we keep 1ms, not 0, so that
   transitionend/animationend listeners still fire), but nothing moves. The
   flash-card flip becomes an instant face-swap; hover lifts become
   colour-only; the nav slides in without the easing curve.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0 !important;
    scroll-behavior: auto !important;
  }
  /* Explicitly kill the orb-drift background animation on the splash — it's
     decorative and a known vestibular trigger. */
  .app-background .bg-orb,
  .bg-orb-1, .bg-orb-2 { animation: none !important; }
  /* Flash-card flip: keep the face-swap (transform) instant so users still
     see the spec when they tap. */
  .flash-card, .flash-card-inner { transition: none !important; }
}

/* ---------------------------------------------------------------------------
   Hover-gating — only apply hover-lift / hover-glow on devices that actually
   have a hover-capable pointer. Prevents the "sticky hover" issue on iOS +
   Android where tapping a card leaves it in the :hover state until the user
   scrolls or taps elsewhere. Desktop + trackpad still get the affordance.
   --------------------------------------------------------------------------- */
@media (hover: none) {
  .flash-card:hover,
  .home-qa-card:hover,
  .reference-card:hover,
  .nav-link:hover { transform: none !important; box-shadow: none !important; }
}

/* ---------------------------------------------------------------------------
   Floor-plan zone patterns — WCAG 1.4.1 Use of Colour. Legend chips get a
   secondary visual cue (an SVG-like striped/dotted background) so that
   colour-blind users can still tell Cocktail-Bar pink from Booth pink. The
   class is applied by renderFloorPlanLegend(); each --fp-pattern value maps
   to a different repeating-gradient.
   --------------------------------------------------------------------------- */
.fp-legend-chip[data-zone-pattern="0"] { background-image: none; }
.fp-legend-chip[data-zone-pattern="1"] {
  background-image: repeating-linear-gradient(45deg, rgba(255,255,255,0.18) 0 4px, transparent 4px 8px);
}
.fp-legend-chip[data-zone-pattern="2"] {
  background-image: repeating-linear-gradient(-45deg, rgba(255,255,255,0.18) 0 4px, transparent 4px 8px);
}
.fp-legend-chip[data-zone-pattern="3"] {
  background-image: radial-gradient(rgba(255,255,255,0.25) 1.2px, transparent 1.4px);
  background-size: 6px 6px;
}
.fp-legend-chip[data-zone-pattern="4"] {
  background-image: repeating-linear-gradient(90deg, rgba(255,255,255,0.18) 0 2px, transparent 2px 6px);
}
.fp-legend-chip[data-zone-pattern="5"] {
  background-image: repeating-linear-gradient(0deg, rgba(255,255,255,0.18) 0 2px, transparent 2px 6px);
}

/* ---------------------------------------------------------------------------
   Legal-modal styling — real Terms + Privacy modals are long. Give them a
   scroll-container + readable typography instead of the single-paragraph
   stub they used to be.
   --------------------------------------------------------------------------- */
.legal-modal { max-width: 44rem; max-height: 85vh; display: flex; flex-direction: column; }
.legal-modal h3 { margin-bottom: 0.25rem; }
.legal-modal .legal-version { margin: 0 0 1rem; color: var(--text-muted); font-size: 0.85rem; }
.legal-modal .legal-body {
  overflow-y: auto;
  padding-right: 0.5rem;
  margin-bottom: 1rem;
  line-height: 1.55;
  font-size: 0.95rem;
}
.legal-modal .legal-body h4 {
  margin: 1.1rem 0 0.35rem;
  font-size: 0.95rem;
  color: var(--text-strong);
}
.legal-modal .legal-body h4:first-child { margin-top: 0; }
.legal-modal .legal-body p,
.legal-modal .legal-body ul { margin: 0 0 0.6rem; }
.legal-modal .legal-body ul { padding-left: 1.2rem; }
.legal-modal .legal-body ul li { margin-bottom: 0.25rem; }
.legal-modal .legal-body code {
  background: rgba(127,127,127,0.18);
  padding: 0.05rem 0.3rem;
  border-radius: 0.25rem;
  font-size: 0.85em;
}
.legal-modal .legal-contact {
  margin-top: 0.8rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
@media (max-width: 600px) {
  .legal-modal { max-height: 92vh; }
  .legal-modal .legal-body { font-size: 0.9rem; }
}

/* ---------------------------------------------------------------------------
   Storage / cookie disclosure banner — shown once per browser under the
   login splash. Dismissal is persisted to localStorage.
   --------------------------------------------------------------------------- */
.storage-banner {
  position: fixed;
  left: 50%;
  bottom: 1rem;
  transform: translateX(-50%);
  width: min(34rem, calc(100vw - 1rem));
  padding: 0.7rem 0.95rem;
  display: flex;
  gap: 0.75rem;
  align-items: center;
  background: rgba(18, 22, 38, 0.97);
  color: #f5f7fb;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.32);
  z-index: 35; /* below .modal (40) so a modal opening always covers the banner */
  font-size: 0.85rem;
  line-height: 1.35;
}
body.light .storage-banner {
  background: #ffffff;
  color: #0f172a;
  border-color: rgba(15, 23, 42, 0.12);
}
.storage-banner p { margin: 0; flex: 1 1 auto; min-width: 0; }
.storage-banner .storage-banner-link {
  color: inherit;
  text-decoration: underline;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  cursor: pointer;
}
.storage-banner .storage-banner-actions {
  display: flex;
  gap: 0.4rem;
  flex-shrink: 0;
}
.storage-banner button.primary { white-space: nowrap; }
.storage-banner[hidden] { display: none; }
@media (max-width: 520px) {
  .storage-banner {
    width: calc(100vw - 0.8rem);
    bottom: 0.45rem;
    padding: 0.6rem 0.7rem;
    font-size: 0.78rem;
    gap: 0.5rem;
    flex-direction: row;
    align-items: center;
  }
  .storage-banner button.primary.btn-sm {
    padding: 0.4rem 0.7rem;
    font-size: 0.8rem;
  }
}

/* T2-04 scope-toggle: cluster roll-up on Team Dashboard + Leaderboard.
   Sits above the primary filter row; hides entirely for single-venue users
   (staff). The "All" radio is revealed only to BK root by JS adding the
   `.show-all` class to the fieldset. */
.scope-toggle {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  align-items: center;
  padding: 0.55rem 0.85rem;
  margin: 0 0 1rem;
  border: 1px solid var(--border, rgba(255,255,255,0.08));
  border-radius: 12px;
  background: var(--surface-soft, rgba(255,255,255,0.03));
}
.scope-toggle[hidden] { display: none; }
.scope-toggle legend {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-dim, rgba(255,255,255,0.65));
  padding: 0 0.35rem;
}
.scope-toggle label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.9rem;
  cursor: pointer;
}
.scope-toggle input[type="radio"] { accent-color: var(--accent, #f2994a); }
.scope-toggle .is-bk-root { display: none; }
.scope-toggle.show-all .is-bk-root { display: inline-flex; }
.team-venue-breakdown {
  margin: 0.5rem 0 1rem;
}
.team-venue-breakdown h3 {
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0 0 0.4rem;
  color: var(--text-dim, rgba(255,255,255,0.7));
}

/* T2-05 Bulk CSV import — Marcus top-3 commercial dealbreaker.
   Collapsed <details> block above the grid-two admin form. Preview table
   colours rows green/red via .is-ok / .is-bad so the operator can spot
   validation errors before committing the import. */
.admin-bulk-import {
  margin: 0 0 1rem;
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  background: var(--surface-soft);
  padding: 0.6rem 0.9rem;
}
.admin-bulk-import > summary {
  cursor: pointer;
  font-weight: 600;
  padding: 0.25rem 0;
  list-style: none;
}
.admin-bulk-import > summary::-webkit-details-marker { display: none; }
.admin-bulk-import > summary::before {
  content: '▸ ';
  display: inline-block;
  transition: transform 120ms ease;
  transform-origin: center;
}
.admin-bulk-import[open] > summary::before { content: '▾ '; }
.admin-bulk-import-body {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-top: 0.75rem;
}
.admin-bulk-import-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: flex-end;
}
.admin-bulk-import-toolbar .input-group {
  flex: 1 1 180px;
  min-width: 160px;
  margin: 0;
}
.admin-bulk-import-toolbar > button {
  flex: 0 0 auto;
}
.admin-bulk-import-drop {
  border: 1px dashed var(--line);
  border-radius: 0.6rem;
  padding: 0.9rem;
  background: rgba(116, 124, 255, 0.04);
}
.admin-bulk-import-drop input[type="file"] {
  display: block;
  width: 100%;
}
.bulk-import-status {
  font-size: 0.9rem;
  color: var(--text);
  min-height: 1.1rem;
}
.bulk-import-status.is-error { color: #e06464; }
.bulk-import-status.is-ok { color: #4fbf6f; }
.bulk-import-preview {
  overflow-x: auto;
  max-height: 280px;
  overflow-y: auto;
  border-radius: 0.5rem;
}
.bulk-import-preview table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.82rem;
}
.bulk-import-preview th,
.bulk-import-preview td {
  border-bottom: 1px solid var(--line);
  padding: 0.4rem 0.55rem;
  text-align: left;
  vertical-align: top;
}
.bulk-import-preview th {
  background: var(--surface-soft);
  font-weight: 600;
}
.bulk-import-preview tr.is-ok td { background: rgba(79, 191, 111, 0.08); }
.bulk-import-preview tr.is-bad td { background: rgba(224, 100, 100, 0.1); }
.bulk-import-preview .bulk-status-badge {
  display: inline-block;
  padding: 0.1rem 0.45rem;
  border-radius: 0.4rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.bulk-import-preview tr.is-ok .bulk-status-badge { background: #2c6a3f; color: #eaffea; }
.bulk-import-preview tr.is-bad .bulk-status-badge { background: #7a2a2a; color: #ffecec; }


/* -----------------------------------------------------------------------
   Marcus v5-harsh #2: Executive dashboard + charts.
   Pure-SVG charts (no chart lib). Every chart has a hidden <table> below
   it for screen-readers, surfaced via .chart-sr-table { sr-only }.
   ----------------------------------------------------------------------- */
.exec-dash { padding-bottom: 2rem; }
.exec-kpi-grid {
  display: grid; gap: 1rem; margin: 1rem 0 1.25rem;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.exec-kpi-card {
  padding: 1rem 1.1rem; border-radius: 14px;
  background: linear-gradient(135deg, var(--accent-soft), var(--accent-soft-2));
  border: 1px solid var(--accent-focus-ring);
  display: flex; flex-direction: column; gap: 0.2rem;
}
.exec-kpi-val { font-size: 1.8rem; font-weight: 700; color: var(--text-strong); line-height: 1.1; }
.exec-kpi-lbl { font-weight: 600; color: var(--text); font-size: 0.9rem; }
.exec-kpi-hint { font-size: 0.78rem; opacity: 0.7; color: var(--text); }
.exec-row { margin: 1rem 0; }
.exec-row-heat { display: grid; grid-template-columns: 3fr 1fr; gap: 1rem; align-items: start; }
.exec-chart-block, .exec-callout, .exec-leaderboard-block, .exec-digest-block {
  background: var(--surface-elev); border: 1px solid var(--line, rgba(0,0,0,0.08));
  padding: 1rem 1.1rem; border-radius: 14px;
}
.exec-chart-block h3, .exec-callout h3, .exec-leaderboard-block h3, .exec-digest-block h3 {
  margin: 0 0 0.35rem;
}
.exec-chart-head {
  display: flex; justify-content: space-between; align-items: center;
  gap: 0.75rem; flex-wrap: wrap;
}
.exec-chart-toggle { display: inline-flex; border: 1px solid var(--accent-focus); border-radius: 999px; padding: 2px; }
.exec-toggle-btn {
  background: transparent; border: 0; color: var(--text);
  padding: 0.35rem 0.85rem; border-radius: 999px; cursor: pointer; font-size: 0.83rem;
}
.exec-toggle-btn.is-active { background: var(--accent); color: var(--text-on-accent); font-weight: 600; }
.exec-chart-summary {
  margin: 0.1rem 0 0.75rem; color: var(--text); opacity: 0.85;
  font-size: 0.9rem; line-height: 1.4;
}
.exec-chart-svg svg {
  width: 100%; height: auto; display: block;
  max-height: 320px;
}
.chart-grid { stroke: var(--line, rgba(120,120,140,0.18)); stroke-width: 0.6; }
.chart-axis-lbl { font-size: 11px; fill: var(--text); opacity: 0.65; font-family: inherit; }
.chart-heatmap-val { font-size: 11px; fill: var(--text-on-accent); font-weight: 600; font-family: inherit; pointer-events: none; }
.chart-sr-table {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0; padding: 0; margin: -1px;
}
.chart-legend { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.4rem; }
.chart-legend-chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.78rem; padding: 0.15rem 0.55rem; border-radius: 999px;
  background: var(--surface-soft); color: var(--text);
}
.chart-legend-swatch {
  display: inline-block; width: 10px; height: 10px; border-radius: 3px;
}
.exec-heatmap-scroll { overflow-x: auto; max-width: 100%; }
.exec-heatmap-scroll svg { max-height: none; min-width: 560px; }
.exec-callout { background: var(--surface-strong); }
.exec-top-missed-list { list-style: none; padding: 0; margin: 0.4rem 0; }
.exec-top-missed-list li {
  display: flex; gap: 0.6rem; padding: 0.55rem 0;
  border-bottom: 1px solid var(--line, rgba(120,120,140,0.12));
}
.exec-top-missed-list li:last-child { border-bottom: 0; }
.exec-top-missed-rank {
  min-width: 2rem; height: 2rem; display: inline-flex;
  align-items: center; justify-content: center;
  background: var(--danger); color: #fff; border-radius: 8px;
  font-weight: 700; font-size: 0.88rem;
}
.exec-top-missed-body strong { display: block; color: var(--text-strong); }
.exec-top-missed-meta { font-size: 0.78rem; opacity: 0.7; }
.exec-leaderboard-table { width: 100%; border-collapse: collapse; }
.exec-leaderboard-table th, .exec-leaderboard-table td {
  border-bottom: 1px solid var(--line, rgba(120,120,140,0.12));
  padding: 0.5rem 0.6rem; text-align: left; vertical-align: middle;
  font-size: 0.9rem;
}
.exec-leaderboard-table thead th { font-weight: 600; opacity: 0.8; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.04em; }
.exec-lb-rank { font-weight: 700; color: var(--accent); font-size: 0.85rem; }
.exec-lb-sparkline svg { display: block; width: 60px; height: 20px; }
.exec-digest-header {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 0.75rem;
}
.exec-digest-pill {
  align-self: flex-start; padding: 0.2rem 0.55rem; border-radius: 999px;
  background: var(--surface-soft); color: var(--text);
  font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  border: 1px solid var(--line, rgba(120,120,140,0.18));
}
.exec-digest-email {
  margin-top: 0.6rem; padding: 0.9rem; border-radius: 10px;
  background: var(--surface-strong); border: 1px dashed var(--accent-focus);
  font-size: 0.92rem; line-height: 1.5;
}
.exec-digest-meta {
  display: grid; gap: 0.2rem; padding-bottom: 0.55rem; margin-bottom: 0.55rem;
  border-bottom: 1px solid var(--line, rgba(120,120,140,0.12)); font-size: 0.82rem; opacity: 0.8;
}
.exec-digest-body p { margin: 0.4rem 0; }
.exec-digest-body ul { margin: 0.4rem 0; padding-left: 1.1rem; }
.exec-digest-body li { margin: 0.2rem 0; }

/* Phone layout: stack KPIs, drop heatmap column grid, scroll heatmap. */
@media (max-width: 640px) {
  .exec-kpi-grid { grid-template-columns: repeat(2, 1fr); }
  .exec-row-heat { grid-template-columns: 1fr; }
  .exec-chart-head { flex-direction: column; align-items: flex-start; }
  .exec-leaderboard-table { font-size: 0.82rem; }
  .exec-leaderboard-table th, .exec-leaderboard-table td { padding: 0.4rem 0.35rem; }
  .exec-lb-sparkline svg { width: 48px; }
}
@media (max-width: 420px) {
  .exec-kpi-grid { grid-template-columns: 1fr 1fr; gap: 0.6rem; }
  .exec-kpi-val { font-size: 1.4rem; }
  .exec-leaderboard-table thead th:nth-child(3),
  .exec-leaderboard-table tbody td:nth-child(3) { display: none; }
}

/* ============================================================================
   V21 HOTFIX — Flipped flash-card overflow on mobile/tablet
   ============================================================================
   The original breakpoint capped the "escape to centered modal" behaviour at
   520px, which left iPhone Plus / Pro Max (430-480px CSS) and small tablets
   (600-768px CSS) stuck with the in-grid 3D flip — content overflowed the
   viewport because the flipped back-face was wider than the grid cell.
   Widening to 768px + hardening overflow/box-sizing on every inner element.
   ============================================================================ */
@media (max-width: 768px) {
  .flash-card.is-flipped,
  .flash-card.is-flipped * {
    box-sizing: border-box;
  }
  .flash-card.is-flipped {
    position: fixed !important;
    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%) !important;
    width: min(24rem, calc(100vw - 1.5rem)) !important;
    max-width: calc(100vw - 1.5rem) !important;
    height: auto !important;
    max-height: calc(100vh - 2rem) !important;
    min-height: 0 !important;
    z-index: 1000 !important;
    border-radius: 1.4rem !important;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55) !important;
    perspective: none !important;
    overflow: hidden !important;
  }
  .flash-card.is-flipped .card-inner {
    transform: none !important;
    transition: none !important;
    transform-style: flat !important;
    height: auto !important;
    min-height: 0 !important;
    width: 100% !important;
  }
  .flash-card.is-flipped .card-front { display: none !important; }
  .flash-card.is-flipped .card-back {
    position: relative !important;
    transform: none !important;
    inset: auto !important;
    border-radius: 1.4rem !important;
    min-height: 0 !important;
    max-height: calc(100vh - 2rem) !important;
    backface-visibility: visible !important;
    -webkit-backface-visibility: visible !important;
    opacity: 1 !important;
    width: 100% !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
  }
  .flash-card.is-flipped .card-face {
    padding: 2.2rem 1rem 1.1rem !important;
    overflow-y: auto !important;
    overflow-x: hidden !important;
    border-radius: 1.4rem !important;
    width: 100% !important;
    max-width: 100% !important;
  }
  /* Any text inside the flipped card must wrap, not force width. */
  .flash-card.is-flipped h3,
  .flash-card.is-flipped p,
  .flash-card.is-flipped li,
  .flash-card.is-flipped td,
  .flash-card.is-flipped th,
  .flash-card.is-flipped span,
  .flash-card.is-flipped div {
    overflow-wrap: anywhere;
    word-break: break-word;
    min-width: 0;
    max-width: 100%;
  }
  .flash-card.is-flipped h3 {
    font-size: 1.2rem !important;
    line-height: 1.25 !important;
    margin-top: 0.3rem !important;
  }
  .flash-card.is-flipped .spec-table,
  .flash-card.is-flipped table {
    width: 100% !important;
    max-width: 100% !important;
    table-layout: auto !important;
    font-size: 0.9rem !important;
  }
  .flash-card.is-flipped .spec-table td,
  .flash-card.is-flipped .spec-table th,
  .flash-card.is-flipped table td {
    padding: 0.3rem 0.4rem !important;
    white-space: normal !important;          /* override spec-measure nowrap */
    word-break: break-word;
  }
  .flash-card.is-flipped .badge,
  .flash-card.is-flipped .badge-cat,
  .flash-card.is-flipped .badge-full {
    font-size: 0.7rem !important;
    padding: 0.25rem 0.55rem !important;
  }
  /* Section containers (garnish, glass, notes, scoring) all honour the max */
  .flash-card.is-flipped .card-section,
  .flash-card.is-flipped .spec-block,
  .flash-card.is-flipped .note,
  .flash-card.is-flipped .card-note,
  .flash-card.is-flipped .score-row {
    max-width: 100% !important;
    overflow-x: hidden !important;
  }
  /* No backdrop dim — per V21 user spec the rest of the page stays at full
     brightness. The card's own box-shadow provides visual separation, and
     the card's native background colour (dark navy #2b3357 in dark theme,
     white in light theme) is preserved. */

  /* Section containing flipped card must not clip or trap, AND must shed
     `.card`'s backdrop-filter:blur(16px) while the modal is up — iOS Safari
     creates a fixed-positioning containing block on any element with a
     backdrop-filter, which forces the "fixed modal" to render blurred
     relative to its backdrop-filter ancestor, NOT the viewport. Result: the
     whole viewport looks hazy on iOS when a card is open. Killing all
     backdrop-filter sources via body class + !important guarantees the
     flipped card escapes correctly on every browser. */
  section.card:has(.flash-card.is-flipped),
  body.has-flipped-card section.card,
  body.has-flipped-card .card {
    overflow: visible !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  /* Kill the decorative background orbs' 70px filter:blur while a card is
     flipped — they sit behind the whole app at fixed position and iOS
     Safari composites them oddly under a fixed modal. */
  body.has-flipped-card .app-background,
  body.has-flipped-card .bg-orb,
  body.has-flipped-card .bg-orb-1,
  body.has-flipped-card .bg-orb-2 {
    filter: none !important;
    opacity: 0 !important;
    visibility: hidden !important;
  }
  /* Force the flipped card into its own stacking context with isolation so
     iOS Safari can never inherit a blur from an ancestor. */
  .flash-card.is-flipped {
    isolation: isolate !important;
    contain: layout paint !important;
  }
}

