/* ============================================
   Brindis · Main app (seating chart)
   ============================================ */

[data-screen="main"] {
  display: flex;
  flex-direction: column;
  background: var(--cream);
}

/* App header */
.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* max(env, var) so the bar never tucks under the status bar: env() can read 0
     on WKWebView's first paint, so App.refreshSafeArea() also publishes the real
     inset as --safe-top on a boot timeline; whichever is correct (non-zero) wins.
     [Carlo device QA: top bar under status bar, controls untappable until resize] */
  padding: calc(max(env(safe-area-inset-top, 0px), var(--safe-top, 0px)) + 12px) 12px 12px;
  background: var(--white);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
  z-index: 5;
}

.app-header-left {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 1;
  min-width: 0;
}

.app-title {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 0 4px;
  /* Don't GROW (so the ✏️ rename button stays right next to the name), but DO
     allow shrinking + ellipsis so a long event name never clips the pencil on a
     narrow phone. grow:1 pushed the pencil away toward the center. [fix 2026-06-14] */
  flex: 0 1 auto;
  min-width: 0;
}
/* Rename pencil stays a fixed-size, always-tappable target next to the title. */
.app-header-left .icon-btn-rename { flex: 0 0 auto; }

/* Left menu = standalone soft button. */
.app-header-left .icon-btn {
  width: 42px;
  min-width: 42px;
  height: 42px;
  padding: 0;
  border-radius: 12px;
  font-size: 21px;
  background: var(--cream-dark);
  border: 1px solid var(--line);
  color: var(--ink);
}
.app-header-left .icon-btn:hover {
  background: var(--gold-light);
  border-color: var(--gold);
}

/* Right actions (undo · more) = ONE segmented control, not two isolated boxes:
   a single pill with a hairline divider so they read as one intentional group. */
.app-header-right {
  display: flex;
  align-items: center;
  gap: 0;
  background: var(--cream-dark);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
}
.app-header-right .icon-btn {
  width: 46px;
  min-width: 46px;
  height: 40px;
  padding: 0;
  border: none;
  border-radius: 0;
  background: transparent;
  font-size: 20px;
  color: var(--ink);
}
.app-header-right .icon-btn + .icon-btn {
  border-left: 1px solid var(--line);
}
.app-header-right .icon-btn:hover {
  background: var(--gold-light);
}
/* Undo pops in brand gold when there's something to undo; dim when not. */
.app-header #btn-undo:not(:disabled) { color: var(--gold-dark); }
.app-header #btn-undo:disabled { opacity: 0.3; cursor: default; }

/* Stats row */
.app-stats {
  display: flex;
  gap: 8px;
  padding: 10px 14px;
  background: var(--white);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
.app-stats::-webkit-scrollbar { display: none; }

.stat-pill {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  padding: 6px 12px;
  background: var(--cream);
  border-radius: var(--radius-pill);
  font-size: 14px;
  white-space: nowrap;
}

.stat-pill > span:first-child {
  font-weight: 700;
  color: var(--ink);
  font-size: 15px;
}

.stat-label {
  color: var(--muted);
  font-size: 12px;
}

/* App body */
.app-body {
  flex: 1;
  display: flex;
  overflow: hidden;
  position: relative;
}

/* Pending panel (left on desktop, bottom on mobile) */
.pending-panel {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border-right: 1px solid var(--line);
  overflow: visible;
  flex-shrink: 0;
  position: relative;
  transition: width var(--dur-base, 220ms) var(--ease, ease), min-width var(--dur-base, 220ms) var(--ease, ease);
}

/* Collapse toggle on the right edge of the sidebar — prominent drawer tab */
/* Vertical center aligned with the CANVAS area (not the sidebar), so we offset
   by half the canvas-controls toolbar height (~52px / 2 ≈ 26px). */
.pending-toggle {
  position: absolute;
  top: calc(50% + 26px);
  right: -22px;
  transform: translateY(-50%);
  width: 36px;
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--gold), var(--gold-dark));
  border: none;
  border-radius: 0 12px 12px 0;
  color: var(--white);
  font-size: 24px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 4px 0 12px rgba(0, 0, 0, 0.18), inset 1px 0 0 rgba(255, 255, 255, 0.25);
  z-index: 12;
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
  padding: 0;
  line-height: 1;
}
.pending-toggle:hover {
  background: linear-gradient(135deg, var(--gold-dark), var(--gold));
  box-shadow: 6px 0 16px rgba(0, 0, 0, 0.25), inset 1px 0 0 rgba(255, 255, 255, 0.35);
  transform: translateY(-50%) translateX(2px);
}
.pending-toggle:active {
  transform: translateY(-50%) scale(0.96);
}

/* Hide toggle on mobile (sidebar is at bottom, collapse doesn't make sense) */
@media (max-width: 640px) {
  .pending-toggle { display: none; }
}

.pending-header {
  padding: 14px 14px 10px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}

.pending-header h3 {
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 8px;
}

.search-input {
  width: 100%;
  padding: 8px 12px;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  /* 16px prevents iOS Safari auto-zoom-in on focus */
  font-size: 16px;
  background: var(--cream);
  transition: border-color var(--dur-fast) var(--ease);
}

.search-input:focus {
  outline: none;
  border-color: var(--gold);
  background: var(--white);
}

.pending-list {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}

.pending-list .guest-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--cream);
  border-radius: var(--radius-md);
  margin-bottom: 6px;
  font-size: 14px;
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
  text-align: left;
  width: 100%;
  border: 1.5px solid transparent;
}

.pending-list .guest-chip:hover {
  border-color: var(--gold);
  background: var(--white);
}

.pending-list .guest-chip:active {
  transform: scale(0.98);
}

.pending-list .guest-chip {
  /* Desktop: block touch-action so the drag pointer events aren't preempted
     by browser pan. Mobile overrides this below to allow native scroll. */
  touch-action: none;
}
@media (hover: none) {
  .pending-list .guest-chip {
    /* pan-y restores NATIVE vertical scroll on touch (Carlo: "regresa el
       scroll hacia abajo"). A guest is dragged out by a SIDEWAYS swipe or by
       press-holding ~400ms then dragging any direction (see seating.js); a
       plain vertical swipe just scrolls the list. */
    touch-action: pan-y;
  }
}

/* Permanent drag hint pinned above the pending list. [Carlo: "siempre deja un
   texto arriba del primer invitado"] */
.pending-drag-hint {
  flex: 0 0 auto;
  margin: 2px 10px 6px;
  padding: 7px 10px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--accent-dark, #9A4A2E);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  border-radius: 8px;
  text-align: center;
}
/* Only show the drag hint when the drawer is OPEN. When collapsed it leaked
   out and overlapped the "N guests to seat" handle label. [Carlo 2026-06-11] */
.app-body.sidebar-collapsed .pending-drag-hint { display: none; }

.pending-list .guest-chip.drag-source {
  /* Mark ONLY the guest being moved (Carlo: "si acaso solo la fila del
     invitado arrastrado para saber quién se está moviendo") — a clear accent
     frame instead of the old fade, so it reads as "this is the one" rather
     than "this one vanished". */
  opacity: 0.85;
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: 10px;
}

/* `.long-press-active`: the drag has actually started — stronger visual + lift
   so the user knows their finger is now controlling a guest. (The old
   `.long-press-armed` rule was removed with the long-press timer; drag now
   starts on a horizontal pull, see seating.js.) */
@media (hover: none) {
  .pending-list .guest-chip.long-press-active {
    background: var(--white);
    box-shadow: 0 6px 18px rgba(44, 36, 24, 0.18);
    transform: scale(1.03);
    transition: transform 0.12s ease, box-shadow 0.12s ease;
  }
}

.pending-panel.drop-target {
  /* Do NOT flood the whole drawer (Carlo: "la mayoría de la hoja se ilumina,
     es confuso"). Just a thin inset frame to hint "drop here to unseat". */
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);
  transition: box-shadow var(--dur-fast) var(--ease);
}

.pending-list .guest-chip .guest-avatar {
  width: 32px;
  height: 32px;
  background: var(--gold-light);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 13px;
  color: var(--ink);  /* ink-on-gold-light = 8-11:1 in every theme; gold-dark was sub-AA [audit #16] */
  flex-shrink: 0;
}

.pending-list .guest-chip .guest-name {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pending-empty {
  padding: 24px 14px;
  text-align: center;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}

.panel-footer {
  padding: 10px 12px calc(max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px)) + 10px);
  border-top: 1px solid var(--line);
  flex-shrink: 0;
}

.pending-panel > .btn-full {
  margin: 10px;
  width: calc(100% - 20px);
}

/* Canvas area */
.canvas-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--cream);
  position: relative;
}

.canvas-controls {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 8px 10px;
  background: var(--white);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
  flex-wrap: wrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.canvas-controls::-webkit-scrollbar { display: none; }
.canvas-controls .spacer { flex: 1 0 auto; }

/* Collapsible top controls bar — a slim grip (like the drawer handle) to hide
   the toolbar and give the canvas the full screen, then bring it back. [Carlo].
   Only meaningful where the toolbar shows (tablet/desktop); on phones the
   toolbar is already replaced by the FAB, so the grip is hidden there. */
.controls-handle {
  flex-shrink: 0;
  width: 100%;
  height: 15px;
  border: none;
  border-bottom: 1px solid var(--line);
  background: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  transition: background var(--dur-fast, 140ms) var(--ease, ease);
}
.controls-handle:hover { background: var(--surface); }
.controls-handle-grip {
  width: 40px;
  height: 4px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--gold) 55%, var(--border));
  transition: width var(--dur-fast, 140ms) var(--ease, ease);
}
.canvas-wrap.controls-collapsed .controls-handle-grip { width: 56px; }
.canvas-wrap.controls-collapsed .canvas-controls { display: none; }
@media (max-width: 640px) { .controls-handle { display: none; } }

.zoom-label {
  font-size: 12px;
  color: var(--muted);
  min-width: 38px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.btn-inline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  transition: all var(--dur-fast) var(--ease);
  cursor: pointer;
  white-space: nowrap;
  height: 36px;
}

.btn-inline:hover {
  border-color: var(--gold);
  background: var(--cream);
  transform: translateY(-1px);
}

.btn-inline:active {
  transform: scale(0.96);
}

.btn-inline-icon {
  font-size: 16px;
  line-height: 1;
}

.btn-inline-label {
  line-height: 1;
}

.party-btn {
  background: linear-gradient(135deg, var(--gold), var(--coral));
  color: var(--white);
  font-size: 18px;
}

.party-btn:hover {
  transform: rotate(-5deg) scale(1.05);
}

/* Party mode visual state */
body.party-mode .app {
  /* EMBER — terracota profundo (noche cálida de la marca), no negro/morado frío.
     Mismo color de los pantallazos promocionales. */
  background: radial-gradient(ellipse at 50% 42%, #96462D 0%, #4E2216 45%, #1A0C08 100%);
  transition: background 600ms var(--ease);
}

body.party-mode .app-header,
body.party-mode .app-stats,
body.party-mode .pending-panel,
body.party-mode .canvas-controls {
  background: rgba(26, 12, 8, 0.92);
  border-color: color-mix(in srgb, var(--gold) 20%, transparent);
  color: var(--cream);
}

/* Hide the floating zoom/size controls during party mode. Party is a lean-back
   "watch everyone mingle" view (the rest of the chrome is already hidden), and
   zooming mid-party could leave the canvas mis-anchored (Carlo's report). The
   FAB stays so the user can still open Tools to end the party. */
body.party-mode .app-controls {
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
}

body.party-mode .app-title,
body.party-mode .stat-pill,
body.party-mode .pending-header h3,
body.party-mode .guest-chip,
body.party-mode .zoom-label,
body.party-mode .pending-empty {
  color: var(--cream);
}

body.party-mode .stat-pill {
  background: color-mix(in srgb, var(--gold) 15%, transparent);
}

body.party-mode .stat-pill > span:first-child {
  color: var(--gold-light);
}

body.party-mode .canvas {
  background-image: radial-gradient(circle, rgba(184, 92, 61, 0.3) 1px, transparent 1px);
  background-size: 28px 28px;
}

body.party-mode .table-shape {
  background: rgba(250, 244, 232, 0.95);
  border-color: var(--gold);
  animation: table-pulse 2s ease-in-out infinite;
  box-shadow: 0 0 24px color-mix(in srgb, var(--gold) 40%, transparent);
}

body.party-mode .table-name {
  color: var(--ink);
}

body.party-mode .table-node.full .table-shape {
  animation: table-happy-pulse 1.5s ease-in-out infinite;
  border-color: var(--coral);
  box-shadow: 0 0 32px rgba(184, 92, 61, 0.6);
}

@keyframes table-pulse {
  0%, 100% { box-shadow: 0 0 20px color-mix(in srgb, var(--gold) 30%, transparent); }
  50% { box-shadow: 0 0 40px color-mix(in srgb, var(--gold) 60%, transparent); }
}

@keyframes table-happy-pulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 24px rgba(184, 92, 61, 0.4); }
  50% { transform: scale(1.04); box-shadow: 0 0 48px rgba(184, 92, 61, 0.8); }
}

/* Disco lights */
.disco-lights {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  overflow: hidden;
}

.disco-light {
  position: absolute;
  border-radius: 50%;
  filter: blur(40px);
  opacity: 0.45;
  mix-blend-mode: screen;
}

.disco-light-0 { width: 200px; height: 200px; background: #e8508a; top: 10%; left: 10%; animation: disco-move-0 4s ease-in-out infinite; }
.disco-light-1 { width: 240px; height: 240px; background: #f5c842; top: 20%; right: 5%; animation: disco-move-1 5s ease-in-out infinite; }
.disco-light-2 { width: 180px; height: 180px; background: #3a8abd; bottom: 20%; left: 30%; animation: disco-move-2 3.5s ease-in-out infinite; }
.disco-light-3 { width: 220px; height: 220px; background: #c41e3a; bottom: 10%; right: 10%; animation: disco-move-3 4.5s ease-in-out infinite; }
.disco-light-4 { width: 160px; height: 160px; background: #9a3ed6; top: 50%; left: 50%; animation: disco-move-4 3.8s ease-in-out infinite; }

@keyframes disco-move-0 { 0%,100% { transform: translate(0,0); opacity: 0.3; } 50% { transform: translate(80px, 120px); opacity: 0.55; } }
@keyframes disco-move-1 { 0%,100% { transform: translate(0,0); opacity: 0.35; } 50% { transform: translate(-100px, 80px); opacity: 0.5; } }
@keyframes disco-move-2 { 0%,100% { transform: translate(0,0); opacity: 0.3; } 50% { transform: translate(60px, -100px); opacity: 0.55; } }
@keyframes disco-move-3 { 0%,100% { transform: translate(0,0); opacity: 0.4; } 50% { transform: translate(-80px, -60px); opacity: 0.6; } }
@keyframes disco-move-4 { 0%,100% { transform: translate(0,0); opacity: 0.25; } 50% { transform: translate(120px, -80px); opacity: 0.5; } }

/* Floating emojis */
.party-emoji {
  position: fixed;
  bottom: -50px;
  z-index: 4;
  pointer-events: none;
  animation: emoji-float linear forwards;
  filter: drop-shadow(0 4px 12px rgba(184, 92, 61, 0.3));
}

@keyframes emoji-float {
  0% { transform: translateY(0) rotate(0deg); opacity: 0; }
  10% { opacity: 1; }
  90% { opacity: 1; }
  100% { transform: translateY(-110vh) rotate(360deg); opacity: 0; }
}

.canvas-scroll {
  flex: 1;
  overflow: auto;
  position: relative;
  -webkit-overflow-scrolling: touch;
  cursor: grab;
  /* Allow native 1-finger pan ONLY. Pinch is handled by our custom JS
     handler (attachCanvasPinch + gesturestart on Safari) so that the
     browser doesn't try to do its own "accessibility zoom" that
     minimizes the Safari window on iPhone. */
  touch-action: pan-x pan-y;
}

.canvas-scroll.panning {
  cursor: grabbing;
}

.canvas-scroll.panning * {
  pointer-events: none;
}

.canvas {
  position: relative;
  width: 3600px;
  height: 2800px;
  background-image:
    radial-gradient(circle, color-mix(in srgb, var(--gold) 15%, transparent) 1px, transparent 1px);
  background-size: 28px 28px;
  transform-origin: 0 0;
  transition: transform var(--dur-base) var(--ease);
}

/* Tables on canvas */
.table-node {
  position: absolute;
  cursor: grab;
  transition: transform var(--dur-fast) var(--ease);
  user-select: none;
  /* Without this the browser's native scroll/pinch on .canvas-scroll
     swallows the table drag on touch devices. */
  touch-action: none;
}

/* Stop iOS Safari from starting its OWN native drag-and-drop in parallel with
   our pointer drag — that left a translucent GRAY snapshot of the table (most
   obvious on the rectangular head table) hanging at the lift point. Disable the
   native drag image + the long-press callout on every draggable canvas node. */
.table-node, .table-node *,
.prop-node, .prop-node *,
.seat, .seat * {
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.table-node.dragging {
  cursor: grabbing;
  /* !important so it beats the per-item inline z-index (newest-on-top); the
     dragged table must float above everything while you move it. */
  z-index: 9999 !important;
  transition: none;
}

.table-node.dragging .table-shape {
  box-shadow: 0 12px 32px rgba(44, 36, 24, 0.25);
}

.table-shape {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--table-fill, #EAF6EE);
  border: 2.5px solid var(--table-fill-border, var(--success));
  box-shadow: var(--shadow-md);
  color: var(--ink);
  font-weight: 600;
  transition: all var(--dur-fast) var(--ease);
}

.table-node:hover .table-shape {
  box-shadow: var(--shadow-lg);
  border-color: var(--gold-dark);
}

/* Table container sizes include seat ring */
.table-node[data-kind="round"] {
  width: 200px;
  height: 200px;
}
.table-node[data-kind="round"] .table-shape {
  width: 140px;
  height: 140px;
  border-radius: 50%;
  top: 30px;
  left: 30px;
}

.table-node[data-kind="rectangle"] {
  width: 200px;
  height: 160px;
}
.table-node[data-kind="rectangle"] .table-shape {
  width: 170px;
  height: 110px;
  border-radius: var(--radius-md);
  top: 25px;
  left: 15px;
}

.table-node[data-kind="long"] {
  width: 290px;
  height: 140px;
}
.table-node[data-kind="long"] .table-shape {
  width: 260px;
  height: 90px;
  border-radius: var(--radius-md);
  top: 25px;
  left: 15px;
}

.table-node[data-kind="head"] {
  width: 210px;
  height: 120px;
}
.table-node[data-kind="head"] .table-shape {
  width: 190px;
  height: 90px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, var(--gold-light), var(--white));
  border-color: var(--gold-dark);
  top: 15px;
  left: 10px;
}
/* Vertical head table: tall box, seats run down a side (JS positions them). */
.table-node[data-kind="head"].head-vertical { width: 120px; height: 210px; }
.table-node[data-kind="head"].head-vertical .table-shape {
  width: 90px;
  height: 190px;
  top: 10px;
  left: 15px;
}

/* Seats around tables */
.seat {
  position: absolute;
  width: 26px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all var(--dur-fast) var(--ease);
  pointer-events: none;
}

.seat.occupied {
  pointer-events: auto;
  cursor: grab;
  touch-action: none;
}

.seat.occupied:active {
  cursor: grabbing;
}

/* Bigger tappable target on touch — the visual person stays the same size,
   but ::before adds an invisible 44 px hit area so dragging a seated guest
   no longer feels like surgery. Apple HIG floor. */
@media (hover: none) {
  .seat.occupied::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -45%);
    border-radius: 50%;
    /* Invisible but receives the touch */
    background: transparent;
    z-index: 1;
  }
}

/* Tag-highlight mode: when the user activates a side-filter chip in the sidebar,
   the canvas dims every seated guest whose tag is currently filtered out.
   The seats that match the highlighted tag(s) stay at full opacity.
   Empty seats also fade so the eye lands on the relevant occupants. */
.canvas.has-side-filter .seat:not(.occupied) {
  opacity: 0.18;
}
.canvas.has-side-filter .seat.occupied.dimmed {
  opacity: 0.22;
  filter: grayscale(0.55);
  transition: opacity var(--dur-fast) var(--ease), filter var(--dur-fast) var(--ease);
}
.canvas.has-side-filter .seat.occupied:not(.dimmed) {
  /* Subtle ring so the highlighted guests are clearly visible. */
  transition: filter var(--dur-fast) var(--ease);
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--gold) 55%, transparent));
}

/* All seats become detectable during drag, including empty */
body.dragging-guest .seat {
  pointer-events: auto;
}

.seat.drop-target::before {
  background: var(--gold);
  border: 2.5px solid var(--gold-dark);
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--gold) 50%, transparent);
  animation: seat-pulse 0.9s ease-in-out infinite;
}

.seat.drop-target {
  transform: scale(1.35);
  z-index: 20;
}

@keyframes seat-pulse {
  0%, 100% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--gold) 50%, transparent); }
  50% { box-shadow: 0 0 0 14px color-mix(in srgb, var(--gold) 20%, transparent); }
}

/* Name label under each occupied seat */
.seat-name {
  position: absolute;
  top: 32px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 10px;
  font-weight: 600;
  /* Forzar texto oscuro sobre badge clara para no quebrar en tema midnight */
  color: #2C2418;
  background: rgba(255, 255, 255, 0.95);
  padding: 1px 6px;
  border-radius: 8px;
  white-space: nowrap;
  pointer-events: none;
  max-width: 90px;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: 0 1px 3px rgba(44, 36, 24, 0.12);
  /* Hairline edge so labels that crowd on a dense round table still read as
     separate pills in the exported plan. [audit cosmetic] */
  border: 1px solid rgba(44, 36, 24, 0.10);
  z-index: 2;
}

body.party-mode .seat-name {
  background: rgba(44, 36, 24, 0.85);
  color: var(--cream);
}

.seat.drag-source {
  opacity: 0.35;
}

.table-node.drop-target .table-shape {
  border-color: var(--coral);
  box-shadow: 0 0 0 6px rgba(184, 92, 61, 0.35), var(--shadow-lg);
  transform: scale(1.04);
  animation: table-drop-pulse 1.2s ease-in-out infinite;
}

@keyframes table-drop-pulse {
  0%, 100% { box-shadow: 0 0 0 6px rgba(184, 92, 61, 0.35), var(--shadow-lg); }
  50% { box-shadow: 0 0 0 14px rgba(184, 92, 61, 0.15), var(--shadow-lg); }
}

/* Drag ghost (following cursor) */
.drag-ghost {
  position: fixed;
  pointer-events: none;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 8px 24px rgba(44, 36, 24, 0.3));
}

.drag-ghost .person {
  transform: scale(1.5);
}

.drag-ghost-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  background: var(--white);
  padding: 3px 10px;
  border-radius: 999px;
  box-shadow: var(--shadow-md);
  white-space: nowrap;
  margin-top: 6px;
}

.seat::before {
  content: '';
  position: absolute;
  inset: 5px;
  background: var(--cream-dark);
  border: 1.5px solid rgba(138, 138, 154, 0.35);
  border-radius: 50%;
  box-shadow: inset 0 1px 2px rgba(44, 36, 24, 0.06);
  transition: opacity var(--dur-fast) var(--ease);
}

.seat.occupied::before {
  display: none;
}

/* Stylized person (monito) */
.person {
  position: relative;
  width: 16px;
  pointer-events: none;
  filter: drop-shadow(0 1px 2px rgba(44, 36, 24, 0.18));
}

.person .head {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #f5d5a8;
  border: 1px solid rgba(58, 32, 16, 0.25);
  margin: 0 auto;
  position: relative;
  z-index: 2;
}

.person .hair {
  position: absolute;
  top: -2px;
  left: 0;
  right: 0;
  height: 5px;
  background: #3a2010;
  border-radius: 5px 5px 0 0;
}

.person.female .hair {
  border-radius: 50%;
  top: -3px;
  height: 6px;
  background: #6b3a1a;
}

.person .body {
  width: 15px;
  height: 14px;
  border-radius: 3px 3px 2px 2px;
  margin: -1px auto 0;
  position: relative;
  z-index: 1;
}

/* Default shirt colors by detected gender. When a guest is tagged with
   a side/group, JS sets --shirt-color on the .person which overrides
   these defaults via var() fallback below. */
.person.male .body { background: var(--shirt-color, #3a8abd); }
.person.female .body { background: var(--shirt-color, #e85d98); }
.person.unknown .body { background: var(--shirt-color, #e88a20); }

.person.captain .head {
  box-shadow: 0 0 0 2px var(--gold), 0 0 8px color-mix(in srgb, var(--gold) 60%, transparent);
  border-color: var(--gold-dark);
}

.person.captain .body {
  box-shadow: 0 0 6px color-mix(in srgb, var(--gold) 50%, transparent);
}

.person.captain::before {
  content: '⭐';
  position: absolute;
  top: -11px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  line-height: 1;
  z-index: 3;
  filter: drop-shadow(0 1px 2px color-mix(in srgb, var(--gold) 60%, transparent));
}

/* Head table label */
.head-table-label {
  position: absolute;
  top: -22px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 11px;
  font-weight: 600;
  color: var(--gold-dark);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  pointer-events: none;
}
/* Flipped: seats above the table → label sits below */
.head-table-label.flipped {
  top: auto;
  bottom: -22px;
}

.table-name {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  line-height: 1;
}

.table-meta {
  font-size: 11px;
  color: var(--muted);
  font-weight: 500;
  margin-top: 4px;
  font-variant-numeric: tabular-nums;
}

.table-node.full .table-shape {
  /* Respect a custom per-table colour even when the table is full — it was
     hard-reverting to green, so coloured tables looked like they "didn't
     change" once you finished seating them. [Carlo] Over-capacity keeps red
     below because that's an error warning, not a style choice. */
  border-color: var(--table-fill-border, var(--success));
  background: var(--table-fill, #EAF6EE);
}

.table-node.over-capacity .table-shape {
  border-color: var(--danger);
  background: #FCECE8;
}

/* La estrella del capitán ahora vive sobre el avatar de la persona,
   no en la esquina de la mesa (era confuso tener ambos marcadores). */

/* Props (venue stations) */
.prop-node {
  position: absolute;
  cursor: grab;
  user-select: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: transform var(--dur-fast) var(--ease);
  /* CRITICAL on touch: without this iOS Safari swallows pointermove as a
     scroll/pan gesture and the drag never starts. Matches the table-node
     rule. The central emoji button inherits this so dragging from the icon
     works the same as dragging from the shape background. */
  touch-action: none;
}
.prop-node .prop-emoji-btn,
.prop-node .prop-text-label,
.prop-node .prop-shape {
  touch-action: none;
}

.prop-node.dragging {
  cursor: grabbing;
  z-index: 9999 !important; /* beats per-item inline z while dragging */
  transition: none;
}

.prop-shape {
  width: calc(110px * var(--prop-scale-x, var(--prop-scale, 1)));
  height: calc(110px * var(--prop-scale-y, var(--prop-scale, 1)));
  background: linear-gradient(135deg, #FFF6E3, #F3E4BE);
  border: 2.5px dashed var(--gold);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-md);
  transition: box-shadow var(--dur-fast) var(--ease);
  position: relative;
  transform: rotate(var(--prop-rotation, 0deg));
  transform-origin: center center;
}

.prop-node.resizing .prop-shape {
  transition: none;
}

.prop-shape-circle {
  border-radius: 50%;
}

.prop-shape-square {
  border-radius: 16px;
}

.prop-shape .prop-emoji {
  font-size: calc(56px * min(var(--prop-scale-x, var(--prop-scale, 1)), var(--prop-scale-y, var(--prop-scale, 1))));
  transform: rotate(calc(-1 * var(--prop-rotation, 0deg)));
}
/* Keep the label HORIZONTAL (readable) but drop it clear of a rotated shape's
   corner, so rotating the station no longer hides its title. [Carlo] */
.prop-node .prop-label {
  transform: translateY(var(--prop-label-offset, 0px));
}

/* Dance floor: distinctive gold-gradient radial pattern, no emoji */
.prop-shape.prop-kind-dance {
  background: radial-gradient(circle at 30% 25%, #FFF6E3 0%, #E8C896 55%, #C9A574 100%);
  border: 3px solid var(--gold-dark);
  overflow: hidden;
}

.prop-shape.prop-kind-dance::before {
  content: '';
  position: absolute;
  inset: 10%;
  border-radius: inherit;
  background: conic-gradient(
    from 0deg,
    rgba(255, 255, 255, 0.22) 0deg 22deg, transparent 22deg 45deg,
    rgba(255, 255, 255, 0.14) 45deg 67deg, transparent 67deg 90deg,
    rgba(255, 255, 255, 0.22) 90deg 112deg, transparent 112deg 135deg,
    rgba(255, 255, 255, 0.14) 135deg 157deg, transparent 157deg 180deg,
    rgba(255, 255, 255, 0.22) 180deg 202deg, transparent 202deg 225deg,
    rgba(255, 255, 255, 0.14) 225deg 247deg, transparent 247deg 270deg,
    rgba(255, 255, 255, 0.22) 270deg 292deg, transparent 292deg 315deg,
    rgba(255, 255, 255, 0.14) 315deg 337deg, transparent 337deg 360deg
  );
  pointer-events: none;
}

.prop-shape.prop-kind-dance::after {
  content: '';
  position: absolute;
  inset: 40%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,0.3), transparent 70%);
  pointer-events: none;
}

/* Resize handle */
.prop-resize-handle {
  position: absolute;
  bottom: 6px;
  right: 6px;
  width: 28px;
  height: 28px;
  background: var(--gold);
  color: var(--on-gold);
  border: 2.5px solid var(--white);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  cursor: nwse-resize;
  touch-action: none;
  box-shadow: 0 2px 8px rgba(44, 36, 24, 0.3);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  z-index: 10;
}

/* Resize handle visibility: hover on desktop, always-on on touch.
   The rotate/delete corner handles are still hidden on touch (the sheet
   handles those) — but the resize handle stays so users can grab the
   corner and drag, matching the desktop affordance. */
@media (hover: hover) and (pointer: fine) {
  .prop-node:hover .prop-resize-handle,
  .prop-node.resizing .prop-resize-handle {
    opacity: 1;
  }
}
@media (hover: none) {
  /* Rotate/delete still hidden on touch — accessed via the prop sheet */
  .prop-rotate-handle,
  .prop-delete-handle {
    display: none;
  }
  /* Resize handle on touch: small visible chip (22 px, matches the table
     resize handle so the canvas reads consistent) + invisible 44 px hit
     area via ::before so a finger can still tap reliably. The handle DOES
     NOT scale with the prop (it lives outside the .prop-shape transform),
     so we keep it small enough that even a 30 % station doesn't look like
     a button with a tiny prop attached. */
  .prop-resize-handle {
    opacity: 0.92;
    width: 22px;
    height: 22px;
    font-size: 10px;
    bottom: -6px;
    right: -6px;
    border-width: 2px;
    box-shadow: 0 2px 6px rgba(44, 36, 24, 0.25);
  }
  .prop-resize-handle::before {
    content: '';
    position: absolute;
    inset: -11px;
    border-radius: 50%;
  }
  .prop-node.resizing .prop-resize-handle {
    opacity: 1;
    transform: scale(1.1);
  }
  /* Staff badge stays subtle / non-interactive (was already removed from
     render — kept here in case future preference restores it). */
  .prop-staff { opacity: 0.85; pointer-events: none; }
}

.prop-resize-handle:hover {
  transform: scale(1.15);
}

.prop-resize-handle:active {
  transform: scale(0.95);
}

.prop-node:hover .prop-shape {
  border-style: solid;
  box-shadow: var(--shadow-lg);
  /* Preserve rotation on hover (do NOT overwrite with scale, that breaks rotation) */
}

.prop-emoji {
  font-size: 56px;
  line-height: 1;
  filter: drop-shadow(0 2px 4px rgba(44, 36, 24, 0.15));
}

.prop-label {
  margin-top: 6px;
  font-size: calc(13px * var(--prop-name-scale, 1));
  font-weight: 600;
  /* Texto oscuro fijo para no quebrar contraste en theme midnight */
  color: #2C2418;
  background: rgba(255, 255, 255, 0.95);
  padding: 3px 10px;
  border-radius: 999px;
  box-shadow: var(--shadow-sm);
  white-space: nowrap;
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
}

body.party-mode .prop-shape {
  animation: prop-pulse 2.5s ease-in-out infinite;
  background: linear-gradient(135deg, #FFF6E3, #F3E4BE);
}

@keyframes prop-pulse {
  0%, 100% { box-shadow: 0 0 24px color-mix(in srgb, var(--gold) 40%, transparent); }
  50% { box-shadow: 0 0 48px rgba(184, 92, 61, 0.6); }
}

/* Prop picker (grid in sheet) */
.prop-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 10px;
}

.prop-picker-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 16px 8px;
  background: var(--cream);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  transition: all var(--dur-fast) var(--ease);
  cursor: pointer;
}

.prop-picker-item:hover {
  border-color: var(--gold);
  background: var(--white);
  transform: translateY(-2px);
}

.prop-picker-emoji {
  font-size: 40px;
  line-height: 1;
}

.prop-picker-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  text-align: center;
  line-height: 1.2;
}

/* Party mode: monitos dancing */
/* Party mode: occupied seats fade out (guests have "stood up" to walk) */
body.party-mode .seat.occupied,
body.party-ending .seat.occupied {
  opacity: 0.12;
  transition: opacity 500ms var(--ease);
}

body.party-mode .seat-name,
body.party-ending .seat-name {
  opacity: 0;
}

/* Walking persons (party mode) */
.walking-person {
  position: absolute;
  width: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
  /* ABOVE the tables: table nodes carry an inline incremental z-index
     ("newest on top", quickly > 6), so walkers at z 6 passed UNDER them —
     head + body hidden, only the feet peeking below the table edge ("monito
     sin cuerpo", device-QA iPad 2026-06-11). Walkers are pointer-events:none
     foreground decoration, so sitting above every table is safe. */
  z-index: 10500;
  filter: drop-shadow(0 3px 6px rgba(44, 36, 24, 0.3));
}

.wp-head {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #f5d5a8;
  border: 1px solid rgba(58, 32, 16, 0.3);
  position: relative;
}

.wp-hair {
  position: absolute;
  top: -3px;
  left: 0;
  right: 0;
  height: 6px;
  background: #3a2010;
  border-radius: 6px 6px 0 0;
}

.walking-person.female .wp-hair {
  border-radius: 50%;
  top: -4px;
  height: 8px;
  background: #6b3a1a;
}

.wp-body {
  width: 18px;
  height: 16px;
  border-radius: 3px 3px 2px 2px;
  margin-top: -1px;
}

.walking-person.male .wp-body { background: #3a8abd; }
.walking-person.female .wp-body { background: #e85d98; }
.walking-person.unknown .wp-body { background: #e88a20; }

.wp-legs {
  display: flex;
  gap: 3px;
  margin-top: -1px;
}

.wp-leg {
  width: 5px;
  height: 7px;
  background: #2c2c3e;
  border-radius: 0 0 2px 2px;
}

.walking-person.walking .wp-leg:first-child {
  animation: wp-leg-l 0.4s ease-in-out infinite;
  transform-origin: top center;
}

.walking-person.walking .wp-leg:last-child {
  animation: wp-leg-r 0.4s ease-in-out infinite;
  transform-origin: top center;
}

@keyframes wp-leg-l {
  0%, 100% { transform: rotate(-15deg); }
  50% { transform: rotate(15deg); }
}

@keyframes wp-leg-r {
  0%, 100% { transform: rotate(15deg); }
  50% { transform: rotate(-15deg); }
}

.wp-name {
  font-size: 9px;
  font-weight: 600;
  color: var(--cream);
  background: rgba(44, 36, 24, 0.85);
  padding: 1px 5px;
  border-radius: 6px;
  margin-top: 2px;
  white-space: nowrap;
}

/* Speech bubble (on seats, used outside party) */
.speech-bubble {
  position: absolute;
  top: -28px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--white);
  color: var(--ink);
  padding: 4px 10px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(44, 36, 24, 0.3);
  z-index: 20;
  pointer-events: none;
  animation: speech-appear 0.35s var(--ease-spring), speech-fade 0.5s ease 3.5s both;
}

/* Walker speech bubble (during party mode, on walking persons) */
.walker-bubble {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-bottom: 4px;
  background: var(--white);
  color: var(--ink);
  padding: 5px 11px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(44, 36, 24, 0.35);
  z-index: 25;
  pointer-events: none;
  animation: bubble-pop 8s ease-out forwards;
}

.walker-bubble::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--white);
}

@keyframes bubble-pop {
  0% { opacity: 0; transform: translateX(-50%) translateY(6px) scale(0.5); }
  8% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
  92% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
  100% { opacity: 0; transform: translateX(-50%) translateY(-4px) scale(0.95); }
}

.speech-bubble::after {
  content: '';
  position: absolute;
  bottom: -5px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 6px solid var(--white);
  filter: drop-shadow(0 2px 2px rgba(44, 36, 24, 0.15));
}

@keyframes speech-appear {
  0% { opacity: 0; transform: translateX(-50%) translateY(8px) scale(0.5); }
  100% { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
}

@keyframes speech-fade {
  to { opacity: 0; transform: translateX(-50%) translateY(-4px) scale(0.95); }
}

/* Sheet extras */
.sheet-input {
  width: 100%;
  padding: 14px 16px;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  font-size: 16px;
  background: var(--cream);
  margin-bottom: var(--space-4);
  transition: border-color var(--dur-fast) var(--ease);
}

.sheet-input:focus {
  outline: none;
  border-color: var(--gold);
  background: var(--white);
}

.sheet-actions {
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
  align-items: center;
  margin-top: var(--space-4);
}

.sheet-menu, .sheet-choices {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.menu-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--cream);
  border: 1.5px solid transparent;
  border-radius: var(--radius-md);
  transition: all var(--dur-fast) var(--ease);
  text-align: left;
  width: 100%;
  font-size: 16px;
  font-weight: 500;
}

/* Only apply :hover effects on devices with a real pointer (mouse/trackpad).
   On touch screens iOS Safari keeps :hover "stuck" after a tap until the
   user taps somewhere else — which is why opening the Tools sheet looked
   like "Venue image" was pre-selected (the FAB tap leaked into the menu
   item underneath as it animated up). */
@media (hover: hover) {
  .menu-row:hover {
    border-color: var(--gold);
    background: var(--white);
  }
}
.menu-row:active {
  border-color: var(--gold);
  background: var(--white);
}

.menu-icon {
  font-size: 20px;
  flex-shrink: 0;
  width: 32px;
  text-align: center;
}

.menu-label {
  color: var(--ink);
}

/* Tools sheet grid — replaces the old vertical list with a 4-column
   responsive grid of large circular tiles. Each tile is a
   single tap target with an emoji disc and a tight label below. The grid
   collapses to 4 cols on phones, 4 cols on desktop sheets too (the
   sheet's max-width caps the row width). */
.tools-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px 10px;
  padding: 4px 2px 8px;
}
@media (max-width: 360px) {
  .tools-grid { grid-template-columns: repeat(3, 1fr); }
}

.tools-tile {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.tools-tile-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 28px;
  line-height: 1;
  background: var(--cream-dark);
  border: 1.5px solid var(--line);
  box-shadow: 0 2px 6px rgba(44, 36, 24, 0.06);
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.tools-tile:active .tools-tile-icon {
  transform: scale(0.93);
}
.tools-tile:hover .tools-tile-icon {
  border-color: var(--gold);
  background: var(--white);
}

/* Tone variants give a soft hint of the action's flavor without screaming.
   `add` = warm tan (creation), `layout` = soft cream (utility),
   `toggle` = neutral with active highlight, `party` = coral celebration. */
.tools-tile.tone-add .tools-tile-icon {
  background: var(--gold-light);
  border-color: var(--gold);
}
.tools-tile.tone-layout .tools-tile-icon {
  background: var(--cream);
}
.tools-tile.tone-toggle .tools-tile-icon {
  background: var(--cream-dark);
}
.tools-tile.tone-toggle.tile-active .tools-tile-icon {
  background: var(--gold);
  border-color: var(--gold-dark);
  color: var(--on-gold);
}
.tools-tile.tone-party .tools-tile-icon {
  background: var(--coral, #D9B870);
  border-color: transparent;
  color: var(--white);
}

.tools-tile-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft, var(--ink));
  text-align: center;
  line-height: 1.2;
  letter-spacing: 0.01em;
}

/* Seat-picker list inside sheet */
.table-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
  gap: var(--space-2);
  max-height: 50dvh;
  overflow-y: auto;
}

.table-picker-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: var(--space-3);
  background: var(--cream);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  transition: all var(--dur-fast) var(--ease);
}

.table-picker-item:hover:not(:disabled) {
  border-color: var(--gold);
  background: var(--white);
}

.table-picker-item:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.table-picker-item .tpi-name {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1;
}

.table-picker-item .tpi-count {
  font-size: 11px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* ════════════════════════════════════════════════════════════════
   MOBILE: canvas-first layout. Hide the toolbar, collapse the pending
   panel by default, surface tools through the floating FAB.
   ════════════════════════════════════════════════════════════════ */
@media (max-width: 640px) {
  /* Order: canvas on top (the king), pending panel as collapsed drawer below */
  .app-body {
    flex-direction: column;
  }
  .canvas-wrap {
    order: 1;
    flex: 1;
    min-height: 0;
  }

  /* Hide the desktop toolbar entirely on mobile — its actions live in
     the FAB tools sheet (Add table / Add station / Image / Names / Lock /
     Export / Party mode). The user gets 100% canvas for the floor plan. */
  .canvas-controls {
    display: none;
  }

  /* App stats: reduce visual weight on mobile, single slim row */
  .app-stats {
    padding: 6px 10px 8px;
    gap: 6px;
    border-bottom: 1px solid color-mix(in srgb, var(--gold) 14%, transparent);
    background: linear-gradient(180deg, rgba(255, 252, 247, 0.6), transparent);
  }
  .app-stats .stat-pill {
    /* Soft sand fill + hairline gold border = pills feel like proper chips,
       not naked text. The 32px min-height + 14/11 type ladder hits Apple HIG
       for tappable secondary controls. */
    padding: 5px 12px;
    font-size: 12px;
    min-height: 44px;
    /* Base .stat-pill uses align-items:baseline; with the 44px min-height that
       floats the text above center. Center it vertically on mobile. [Carlo] */
    align-items: center;
    background: rgba(255, 252, 247, 0.85);
    border: 1px solid color-mix(in srgb, var(--gold) 28%, transparent);
    border-radius: 999px;
    transition: transform 0.12s ease, background 0.12s ease, border-color 0.12s ease;
  }
  .app-stats .stat-pill:active {
    transform: scale(0.96);
    background: var(--cream);
    border-color: color-mix(in srgb, var(--gold) 50%, transparent);
  }
  .app-stats .stat-pill .stat-label {
    /* 11px is the Apple HIG floor for secondary text. 10px reads as broken on
       newer iPhones with high-density screens. */
    font-size: 11px;
    opacity: 0.78;
    letter-spacing: 0.01em;
  }
  .app-stats .stat-pill > span:first-child {
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -0.01em;
  }

  /* App header: tighter on mobile — but KEEP the safe-area top inset, or the
     header tucks under the status bar/notch and ☰/⋯ become untappable. This
     mobile override used to be a flat `padding: 6px 12px`, which silently beat
     the base rule's safe-area top and was THE root cause of the header-under-
     the-notch bug (reported 6×; a headless test proved padding-top stayed 6px
     even with --safe-top:59). [Carlo device QA 2026-06-11] */
  .app-header {
    padding: calc(max(env(safe-area-inset-top, 0px), var(--safe-top, 0px)) + 6px) 12px 6px;
  }
  .app-header .app-title {
    font-size: 17px;
  }
  /* Undo on mobile: ALWAYS visible next to the ⋯ menu (greyed when there's
     nothing to undo) so the slot is never an empty gap — Carlo expected to see
     it on iPhone. renderStats toggles :disabled; the dim state below signals
     "nothing to undo yet". */
  .app-header #btn-undo { display: inline-flex; }

  /* Pending panel = bottom drawer. Three modes: collapsed (44px handle
     only), normal (40dvh), expanded (80dvh — drag-up state). The user
     can drag the handle vertically to switch between them, or tap to
     toggle collapsed↔normal. */
  .pending-panel {
    order: 2;
    height: 40dvh;
    max-height: 60dvh; /* bumped so the user can drag up past the 320px ceiling */
    border-right: none;
    border-top: 1px solid var(--line);
    flex-shrink: 0;
    transition: height var(--dur-base, 220ms) var(--ease, ease), max-height var(--dur-base, 220ms) var(--ease, ease);
    position: relative;
    background: var(--white);
  }
  .app-body.sidebar-collapsed .pending-panel {
    /* Include the safe-area so the "N invitados por sentar" label isn't clipped
       behind iOS Safari's bottom toolbar / home indicator. [Carlo report] */
    height: calc(44px + max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px)));
    max-height: calc(44px + max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px)));
    padding-bottom: max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px));
    overflow: hidden;
  }
  .app-body.sidebar-expanded .pending-panel {
    height: 80dvh;
    max-height: 80dvh;
  }
  .app-body.sidebar-collapsed .pending-header,
  .app-body.sidebar-collapsed .pending-list,
  .app-body.sidebar-collapsed .pending-panel > .btn-full {
    display: none;
  }

  /* The toggle becomes a full-width tappable bar at the top of the drawer.
     Drag-able vertically (handled in JS attachPendingHandleDrag): drag up
     to expand, drag down to collapse. Tap toggles collapsed↔normal. */
  .pending-toggle {
    display: flex !important;
    top: 0;
    right: 0;
    left: 0;
    bottom: auto;
    transform: none;
    width: 100%;
    height: 44px;
    border-radius: 0;
    border: none;
    background: transparent;
    color: var(--muted);
    font-size: 0; /* Hide any inline text content like '‹' */
    box-shadow: none;
    z-index: 5;
    padding: 0;
    /* Crucial: kill native touch-action so the drag JS controls the gesture.
       Without this, iOS may steal the gesture as a page scroll the moment
       the user starts dragging. */
    touch-action: none;
    cursor: ns-resize;
  }
  /* Kill the desktop golden-gradient :hover/:active on the drawer bar. On iOS
     the :hover state STICKS after a tap/drag, so the base
     `.pending-toggle:hover { background: linear-gradient(gold,gold-dark) }`
     (higher specificity than this rule's transparent) painted the bar ORANGE
     and hid the "N guests to seat" label until you tapped elsewhere — exactly
     the "se queda a medias" bug. [Carlo device QA 2026-06-11] */
  .pending-toggle:hover,
  .pending-toggle:active,
  .pending-toggle:focus {
    background: transparent !important;
    transform: none !important;
    box-shadow: none !important;
  }
  /* Sheet-style drag handle line at the very top */
  .pending-toggle::before {
    content: '';
    position: absolute;
    top: 7px;
    left: 50%;
    transform: translateX(-50%);
    width: 40px;
    height: 4px;
    background: var(--line);
    border-radius: 2px;
  }
  /* Friendly text label below the handle. Only shown when COLLAPSED so it
     doesn't overlap with the actual list content when the drawer is open. */
  .app-body.sidebar-collapsed .pending-toggle::after {
    content: attr(data-count);
    position: absolute;
    top: 16px;
    left: 0;
    right: 0;
    text-align: center;
    font-size: 13.5px;
    /* High-contrast, legible label (was --muted/500, hard to read on some
       themes and looked like an empty strip). [Carlo report] */
    color: var(--ink);
    font-weight: 600;
    letter-spacing: -0.01em;
  }
  /* Make the collapsed strip read clearly as a tappable bar, not a blank
     band: a warm fill + a defined top edge that stands apart from the canvas. */
  .app-body.sidebar-collapsed .pending-panel {
    background: var(--surface);
    border-top: 1.5px solid color-mix(in srgb, var(--gold) 50%, var(--border));
  }
  .app-body.sidebar-collapsed .pending-toggle::before {
    background: color-mix(in srgb, var(--gold) 60%, var(--border));
  }
  /* When the drawer is OPEN, only the handle line shows. The handle alone
     hints "tap me to close" without competing with the list header. */
  .app-body:not(.sidebar-collapsed) .pending-toggle {
    height: 18px; /* shrink to just the handle */
  }
  .app-body:not(.sidebar-collapsed) .pending-toggle::after {
    display: none;
  }
  /* Push the pending-header down a bit so it doesn't touch the handle */
  .app-body:not(.sidebar-collapsed) .pending-header {
    padding-top: 18px;
  }
}

/* Tablet/Desktop pending toggle remains as before (golden right-edge pill) */

/* Tablet/Desktop: pending panel on the left */
@media (min-width: 641px) {
  .pending-panel {
    width: 300px;
    flex-shrink: 0;
  }
  .canvas-wrap {
    flex: 1;
    min-width: 0;
  }
  /* Collapsed state — panel disappears, only the toggle stays visible on the canvas edge */
  .app-body.sidebar-collapsed .pending-panel {
    width: 0;
    min-width: 0;
    border-right-color: transparent;
  }
  .app-body.sidebar-collapsed .pending-header,
  .app-body.sidebar-collapsed .pending-list,
  .app-body.sidebar-collapsed .pending-panel > .btn-full {
    display: none;
  }
  .app-body.sidebar-collapsed .pending-toggle {
    /* Panel is width:0 when collapsed; the base right:-22px then clips the 36px
       tab 14px off the left edge — shift it fully into view (NOT right:0, which
       would push it entirely off-screen). [audit] */
    right: -36px;
    border-left: 1px solid var(--line);
    border-radius: 0 8px 8px 0;
  }
}

/* Seated guest chips inside table sheet */
.seated-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 50dvh;
  overflow-y: auto;
  margin-bottom: var(--space-4);
}

.seated-list .guest-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--cream);
  border-radius: var(--radius-md);
  font-size: 14px;
}

.seated-list .guest-chip .guest-name {
  flex: 1;
}

.seated-list .guest-chip .captain-star {
  color: var(--gold-dark);
  font-size: 14px;
}

.seated-list .remove-btn {
  color: var(--danger);
  padding: 4px 8px;
  font-size: 12px;
  font-weight: 500;
  border-radius: var(--radius-sm);
  background: transparent;
  cursor: pointer;
}

.seated-list .remove-btn:hover {
  background: #FCECE8;
}

/* Rich seated row with meal + captain */
.seated-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--cream);
  border-radius: var(--radius-md);
}

.seated-name-col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.seated-name-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 500;
}

.seated-name-row .guest-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.seated-name-row .captain-star {
  color: var(--gold-dark);
  font-size: 13px;
}

.meal-picker {
  display: flex;
  gap: 4px;
}

.meal-picker {
  display: flex;
  gap: 6px;
  align-items: center;
}

.meal-btn {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--white);
  border: 1.5px solid var(--line);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  cursor: pointer;
  transition: all var(--dur-base) var(--ease-spring);
  padding: 0;
  line-height: 1;
  transform-origin: center;
}

.meal-btn:hover {
  border-color: var(--gold);
  transform: scale(1.08);
}

/* Selected meal is emphasized */
.meal-btn.active {
  background: var(--gold-light);
  border-color: var(--gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 45%, transparent);
  transform: scale(1.35);
  z-index: 1;
  font-size: 16px;
}

.meal-btn.active:hover {
  transform: scale(1.42);
}

/* Fade and shrink non-selected when any is active */
.meal-picker:has(.meal-btn.active) .meal-btn:not(.active) {
  opacity: 0.28;
  transform: scale(0.7);
  filter: grayscale(0.6);
}

.meal-picker:has(.meal-btn.active) .meal-btn:not(.active):hover {
  opacity: 0.9;
  transform: scale(0.95);
  filter: grayscale(0);
}

.captain-btn {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--white);
  border: 1.5px solid var(--line);
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
  padding: 0;
  opacity: 0.5;
}

.captain-btn:hover {
  opacity: 1;
  border-color: var(--gold);
}

.captain-btn.active {
  background: var(--gold-light);
  border-color: var(--gold-dark);
  color: var(--gold-dark);
  opacity: 1;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--gold) 35%, transparent);
}

/* Theme picker */
.theme-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}

.theme-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  background: var(--white);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}

.theme-card:hover {
  border-color: var(--gold);
  transform: translateY(-2px);
}

.theme-card.active {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 35%, transparent);
}

.theme-swatches {
  display: flex;
  gap: 4px;
  height: 32px;
  border-radius: 8px;
  overflow: hidden;
}

.theme-sw {
  flex: 1;
}

.theme-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  text-align: center;
}

body.theme-dark {
  background: var(--cream-dark);
}

/* Captain bottle label */
.captain-bottle-label {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  color: var(--gold-dark);
  background: var(--gold-light);
  padding: 2px 8px;
  border-radius: 999px;
  margin-top: 2px;
  cursor: pointer;
  width: fit-content;
}

.captain-bottle-label:hover {
  background: var(--gold);
  color: var(--on-gold);
}

/* Events list */
.events-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 50dvh;
  overflow-y: auto;
  margin-bottom: 8px;
}

.events-list .choice-row {
  padding: 14px 14px;
}

.events-list .choice-row-current {
  border-color: var(--gold);
  background: var(--cream);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--gold) 25%, transparent);
}

.events-row-actions {
  display: flex;
  gap: 4px;
  align-items: center;
  margin-left: auto;
}

/* Danger variant for icon-btn: used on the trash icon of the CURRENTLY OPEN
   event so the user notices it deletes "what's on screen right now". */
.icon-btn.icon-btn-danger {
  background: rgba(184, 92, 61, 0.10);
  border: 1px solid rgba(184, 92, 61, 0.35);
  color: var(--danger);
}
.icon-btn.icon-btn-danger:hover {
  background: rgba(184, 92, 61, 0.22);
  border-color: rgba(184, 92, 61, 0.65);
}

/* Guest list sheet */
.guest-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));
  gap: 6px;
  margin-bottom: 12px;
}

.gs-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 8px 4px;
  background: var(--cream);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
}

.gs-num {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.gs-label {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.guest-full-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 55dvh;
  overflow-y: auto;
  margin-top: 8px;
}

.gl-table-info {
  font-size: 12px;
  font-weight: 500;
}

.gl-table-info.seated {
  color: var(--success);
}

.gl-table-info.unassigned {
  color: var(--coral);
}

.section-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: var(--space-4) 0 var(--space-2);
}

/* Type selector (round / rect / long) */
.type-selector {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-bottom: 12px;
}

.type-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 14px 8px;
  background: var(--cream);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  transition: all var(--dur-fast) var(--ease);
  cursor: pointer;
}

.type-btn:hover {
  border-color: var(--gold);
  background: var(--white);
}

.type-btn.active {
  background: var(--gold-light);
  border-color: var(--gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 20%, transparent);
}

/* Stepper (capacity +/-) */
.stepper {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 12px 0;
  margin-bottom: 8px;
}

.stepper-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  font-size: 24px;
  font-weight: 600;
  color: var(--ink);
  background: var(--white);
  border: 2px solid var(--line);
  box-shadow: var(--shadow-sm);
  transition: all var(--dur-fast) var(--ease);
}

.stepper-btn:hover:not(:disabled) {
  border-color: var(--gold);
  transform: scale(1.05);
}

.stepper-btn:active:not(:disabled) {
  transform: scale(0.95);
}

.stepper-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.stepper-value {
  font-family: var(--font-display);
  font-size: 36px;
  font-weight: 700;
  color: var(--ink);
  min-width: 70px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* The angle number doubles as a tap target to type an exact value. Render the
   <button> like the plain value but hint that it's tappable. [Carlo 2026-06-15] */
.stepper-value.stepper-value-editable {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 4px;
  text-decoration: underline dotted var(--gold);
  text-underline-offset: 5px;
}

/* Per-edge seat editor (rectangular / long tables): a compact row per edge —
   the two long sides + the two ends/cabeceras — plus a running total. */
.edge-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 3px 0;
}
.edge-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
}
.edge-row .stepper {
  gap: 12px;
  padding: 4px 0;
  margin: 0;
}
.edge-row .stepper-btn {
  width: 44px;
  height: 44px;
  font-size: 22px;
}
.edge-row .stepper-value {
  font-size: 22px;
  min-width: 34px;
}
.edge-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.edge-total .edge-label {
  font-weight: 600;
}
.edge-total-val {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* Autosave badge */
.autosave-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  color: var(--success);
  font-weight: 500;
  opacity: 0;
  transform: translateY(-4px);
  transition: all var(--dur-base) var(--ease);
  pointer-events: none;
  margin-left: auto;
  padding: 0 8px;
  white-space: nowrap;
  /* Pin to the right + opaque bg so it isn't clipped when the pills overflow-scroll
     on narrow phones (flex scrollable padding-right collapses at <=390px). [audit] */
  position: sticky;
  right: 0;
  background: var(--white);
}

.autosave-badge.visible {
  opacity: 1;
  transform: translateY(0);
}

/* ============================================
   Scoring engine visual feedback
   Ported from wedding-seating (mesa feliz / conflicto)
   ============================================ */

/* Stat pill in header */
.stat-pill.stat-score #stat-score {
  font-variant-numeric: tabular-nums;
}
.stat-pill.stat-score.score-good #stat-score {
  color: var(--success);
}
.stat-pill.stat-score.score-bad #stat-score {
  color: var(--danger);
}

/* Per-table mood — green halo when happy, red when conflict */
.table-node.happy .table-shape {
  box-shadow: 0 0 0 2px var(--success), var(--shadow-md);
}
.table-node.conflict .table-shape {
  box-shadow: 0 0 0 2px var(--danger), var(--shadow-md);
  animation: conflict-pulse 2.4s ease-in-out infinite;
}
@keyframes conflict-pulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--danger), var(--shadow-md); }
  50%      { box-shadow: 0 0 0 3px var(--danger), 0 0 18px rgba(199, 62, 29, 0.35); }
}

/* Inline badge on the table shape */
.table-score-badge {
  position: absolute;
  bottom: -10px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  background: var(--white);
  border: 1px solid var(--line);
  white-space: nowrap;
  pointer-events: none;
  font-variant-numeric: tabular-nums;
}
.table-score-badge.good { color: var(--success); border-color: var(--success); }
.table-score-badge.bad  { color: var(--danger);  border-color: var(--danger); }

/* ============================================
   Side filters + partner chips + side picker
   ============================================ */

/* Filter chips in pending header */
.side-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 0 4px;
}
.side-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--white);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.side-filter-chip:hover {
  background: var(--cream);
  border-color: var(--gold);
}
/* Active = this tag is currently highlighting its guests on the canvas. */
.side-filter-chip.active {
  background: var(--side-color, var(--gold));
  border-color: var(--side-color, var(--gold));
  color: var(--white);
  font-weight: 600;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 18%, transparent);
}
.side-filter-chip.active .side-filter-dot {
  background: var(--white) !important;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.12);
}

/* ✏️ Edit-tags trigger: sits at the end of the side-filter row */
.side-filter-edit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 26px;
  padding: 0;
  background: transparent;
  border: 1px dashed var(--line);
  border-radius: var(--radius-pill);
  cursor: pointer;
  font-size: 12px;
  opacity: 0.6;
  transition: all var(--dur-fast) var(--ease);
}
.side-filter-edit:hover {
  opacity: 1;
  background: var(--cream);
  border-color: var(--gold);
  border-style: solid;
}

/* Tag editor sheet rows */
.tag-editor-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 4px;
}
.tag-editor-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}
.tag-editor-color {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--white);
  box-shadow: 0 0 0 1px var(--line);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: transform var(--dur-fast) var(--ease);
}
.tag-editor-color:hover {
  transform: scale(1.12);
}
.tag-editor-color:active {
  transform: scale(0.95);
}

/* Inline color grid that appears between tag rows when the user taps a
   tag's color circle. Rendered as a sibling AFTER its row so the rows
   below get pushed down — no overlap, no z-index fight. */
.tag-color-picker {
  background: var(--surface, var(--cream-dark));
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  padding: 10px;
  margin: -2px 0 6px;
  display: grid;
  grid-template-columns: repeat(8, minmax(24px, 1fr));
  gap: 8px;
  animation: tag-color-expand var(--dur-fast) var(--ease);
}
@keyframes tag-color-expand {
  from { opacity: 0; transform: scaleY(0.6); transform-origin: top; }
  to   { opacity: 1; transform: scaleY(1); transform-origin: top; }
}
.tag-color-swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid var(--white);
  box-shadow: 0 0 0 1px var(--line);
  cursor: pointer;
  padding: 0;
  transition: transform var(--dur-fast) var(--ease);
}
.tag-color-swatch:hover { transform: scale(1.15); }
.tag-color-swatch:active { transform: scale(0.9); }
.tag-color-swatch.active {
  box-shadow: 0 0 0 2px var(--gold-dark);
}
.tag-editor-name {
  flex: 1;
  min-width: 0;
  padding: 8px 10px;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  /* 16px prevents iOS auto-zoom on focus */
  font-size: 16px;
  background: var(--cream);
  font-family: inherit;
}
.tag-editor-name:focus {
  outline: none;
  border-color: var(--gold);
  background: var(--white);
}
.tag-editor-delete {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--line);
  color: var(--muted);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  flex-shrink: 0;
  transition: all var(--dur-fast) var(--ease);
}
.tag-editor-delete:hover {
  background: rgba(184, 92, 61, 0.12);
  border-color: rgba(184, 92, 61, 0.55);
  color: var(--danger);
}
.side-filter-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}
.side-filter-label { line-height: 1; }

/* Side dot on each pending chip */
.side-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  display: inline-block;
  margin-right: 4px;
  flex: 0 0 auto;
}

/* Partner chip (combined "Juan + María") */
.guest-chip.has-partner {
  background: linear-gradient(135deg, rgba(159, 122, 234, 0.08) 0%, rgba(184, 92, 61, 0.08) 100%);
  border-color: rgba(159, 122, 234, 0.3);
}
.guest-chip.has-partner::after {
  content: '👥';
  margin-left: auto;
  font-size: 11px;
  opacity: 0.6;
}

/* Side picker (inline in seated row) */
.side-picker {
  display: inline-flex;
  gap: 4px;
  margin-top: 4px;
}
.side-btn {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1.5px solid var(--line);
  background: var(--white);
  color: var(--ink-soft);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.side-btn.active {
  background: var(--side-color, var(--gold));
  border-color: var(--side-color, var(--gold));
  color: var(--white);
}

/* ============================================
   v2 panels: Meals + Registro + text export
   ============================================ */

.text-export-toolbar {
  display: flex;
  gap: 8px;
  margin-top: 18px;
  flex-wrap: wrap;
}
.text-export-toolbar .btn {
  flex: 1 1 auto;
  min-width: 140px;
  font-size: 14px;
}

.meals-summary {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 16px;
}
.meals-stat {
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 12px 6px;
  text-align: center;
}
.ms-emoji { font-size: 22px; line-height: 1.1; }
.ms-num {
  font-family: 'Playfair Display', Georgia, serif;
  font-size: 24px;
  font-weight: 700;
  color: var(--ink);
  margin-top: 4px;
}
.ms-label {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: 2px;
}

.meals-tables {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 6px;
  max-height: 40dvh;
  overflow-y: auto;
}
.meals-table-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 13px;
}
.mtr-name { font-weight: 600; color: var(--ink); }
.mtr-counts {
  display: flex;
  gap: 10px;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

.registro-preview {
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 14px;
  font-family: 'SF Mono', Monaco, 'Cascadia Mono', Consolas, monospace;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  max-height: 45dvh;
  overflow-y: auto;
  color: var(--ink);
  margin-bottom: 6px;
}

@media (max-width: 480px) {
  .meals-summary { grid-template-columns: repeat(2, 1fr); }
  .registro-preview { font-size: 11px; padding: 12px; }
}

/* ============================================
   v2 toolbar additions: tables-size group, lock/names buttons
   ============================================ */
.ctl-group {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px 4px;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  margin-left: 2px;
}
.ctl-group-label { font-size: 14px; padding: 0 4px; opacity: 0.7; }
.icon-btn-sm {
  width: 26px;
  height: 26px;
  font-size: 14px;
  padding: 0;
  border-radius: 50%;
}
/* Apple HIG / Google Material: 44pt minimum touch target on touch devices.
   Keep the small visual but grow the hit area via padding + min-size. */
@media (hover: none) {
  .icon-btn-sm {
    width: 36px;
    height: 36px;
    font-size: 16px;
  }
  .stat-pill {
    min-height: 40px;
  }
  .btn-inline {
    min-height: 40px;
    padding: 8px 14px;
  }
}

.btn-inline.active {
  background: var(--gold);
  color: var(--on-gold);
  border-color: var(--gold);
}
.btn-inline.active:hover { background: var(--gold-dark); border-color: var(--gold-dark); }
.btn-inline[disabled] { opacity: 0.55; cursor: wait; }

/* Lock + hide-names states */
body.lock-active .table-node,
body.lock-active .seat.occupied,
body.lock-active .prop-node,
body.lock-active .guest-chip {
  cursor: not-allowed !important;
}
body.lock-active #btn-toggle-lock {
  box-shadow: 0 0 0 2px rgba(184, 92, 61, 0.35);
}

body.hide-names .guest-name,
body.hide-names .seat-name,
body.hide-names .seated-name { visibility: hidden; }

/* Table scaling — two honest multipliers:
   • --table-mult on :root = global pill (the value the user sees in the
     floating bottom-left chip). Persists per-event.
   • --table-scale on the node itself = per-table override (corner drag
     + sheet stepper).
   The pill % matches reality 1:1. No hidden device multiplier — the
   default just starts smaller on mobile (0.5) and bigger on desktop
   (1.0), set in JS so each event picks its own baseline on first open. */
.table-node {
  /* Three-axis transform composed in CSS so we don't have to recompute
     it in JS on every mutation:
     • scale = global pill × per-table scale
     • rotate = per-table rotation in degrees (rectangular/long tables;
       round tables visually don't change so we just leave it at 0)
     Order matters: scale first, rotate after, so the rotation pivots
     around the visual center post-scale, not the unscaled origin. */
  transform:
    scale(calc(var(--table-mult, 1) * var(--table-scale, 1)))
    rotate(var(--table-rotation, 0deg));
  transform-origin: center center;
  transition: transform var(--dur-base) var(--ease);
}
.table-node.resizing {
  transition: none;
}

/* Per-table resize handle (bottom-right corner, hidden until hover on
   desktop; hidden entirely on touch — phone users adjust via the Width
   stepper inside the table sheet, where a 22 px target would be unhittable
   with a finger). Mirrors prop-resize-handle so the visual language stays
   consistent. */
.table-resize-handle {
  position: absolute;
  bottom: -6px;
  right: -6px;
  width: 22px;
  height: 22px;
  background: var(--gold);
  color: var(--on-gold);
  border: 2px solid var(--white);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  cursor: nwse-resize;
  touch-action: none;
  box-shadow: 0 2px 6px rgba(44, 36, 24, 0.25);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  z-index: 10;
}
@media (hover: hover) and (pointer: fine) {
  .table-node:hover .table-resize-handle,
  .table-node.resizing .table-resize-handle {
    opacity: 1;
  }
  .table-resize-handle:hover {
    transform: scale(1.15);
  }
}
/* Touch: small visible chip (22 px) + invisible 44 px ::before hit area
   so a finger can grab it without making the visual button dominate
   small tables. Same dimensions as the prop resize chip so both feel
   like the same control. */
@media (hover: none) {
  .table-resize-handle {
    opacity: 0.92;
    width: 22px;
    height: 22px;
    font-size: 10px;
    bottom: -8px;
    right: -8px;
  }
  .table-resize-handle::before {
    content: '';
    position: absolute;
    inset: -11px;
    border-radius: 50%;
  }
  .table-node.resizing .table-resize-handle {
    opacity: 1;
    transform: scale(1.15);
  }
}

/* ============================================
   v2: Auto-staff badge + rotated tables
   ============================================ */
.prop-staff {
  position: absolute;
  bottom: -6px;
  right: -10px;
  width: 32px;
  height: 32px;
  background: var(--white);
  border: 2px solid var(--gold);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.15);
  pointer-events: none;
  z-index: 4;
}

.table-node.rotated-90 .table-shape {
  transform: rotate(90deg);
}
.table-node.rotated-90 .table-shape .table-name,
.table-node.rotated-90 .table-shape .table-meta,
.table-node.rotated-90 .table-shape .head-table-label {
  transform: rotate(-90deg);
}

/* Prop kind colors (visible accent for service stations) */
.prop-kind-tacos .prop-shape { background: linear-gradient(135deg, #FFE9B8, #FFCB6B); }
.prop-kind-elotes .prop-shape { background: linear-gradient(135deg, #FFF8C8, #F5D547); }
.prop-kind-bar .prop-shape { background: linear-gradient(135deg, #E4D8F5, #B69BE4); }
.prop-kind-dance .prop-shape { background: repeating-linear-gradient(45deg, #FFF1DC, #FFF1DC 12px, #F5E6CA 12px, #F5E6CA 24px); }
.prop-kind-photobooth .prop-shape { background: linear-gradient(135deg, #D4E8F8, #8FB8E0); }
.prop-kind-cake .prop-shape { background: linear-gradient(135deg, #FFD9E8, #FF9FC1); }
.prop-kind-stage .prop-shape { background: linear-gradient(135deg, #2A1A10, #4A2E1C); color: var(--gold-light); }
.prop-kind-stage .prop-label { color: var(--gold-light); }
.prop-kind-tree .prop-shape { background: radial-gradient(circle at 50% 65%, #4E9A4E 0%, #2E7C2E 60%, transparent 65%); border-color: transparent; box-shadow: none; }
.prop-kind-tree .prop-staff,
.prop-kind-cake .prop-staff,
.prop-kind-dance .prop-staff { display: none; }

/* ============================================
   v2: Venue image background + uploader UI
   ============================================ */
.venue-layer {
  position: absolute;
  inset: 0;
  /* Floor map nunca captura pointer — el canvas pan y los drags de mesa funcionan
     siempre. Posicionar el venue se hace desde el sheet con botones direccionales. */
  pointer-events: none;
  z-index: 0;
  /* overflow visible para que la imagen no se trunque al moverla más allá del centro */
  overflow: visible;
}
.venue-layer img.venue-img {
  position: absolute;
  top: 50%;
  left: 50%;
  max-width: none;
  max-height: none;
  width: auto;
  height: auto;
  max-block-size: 100%;
  max-inline-size: 100%;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
.canvas.has-venue .table-node,
.canvas.has-venue .prop-node,
.canvas.has-venue .seat { z-index: 2; }

.venue-preview {
  position: relative;
  width: 100%;
  height: 160px;
  background: var(--cream);
  border: 1px dashed var(--line);
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  margin-bottom: 12px;
}
.venue-preview-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
.venue-preview-placeholder {
  color: var(--muted);
  font-style: italic;
  font-size: 14px;
}

/* Tiny visual anchor used when the venue panel re-opens with an image
   already loaded. The canvas is the real preview at that point — this is
   just "yes, this is the image we're talking about." */
.venue-thumb-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: var(--cream);
  border-radius: var(--radius-md);
  margin-bottom: 10px;
}
.venue-thumb-img {
  width: 46px;
  height: 46px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--line);
  flex-shrink: 0;
}
.venue-thumb-label {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.3;
}
.venue-opacity-wrap {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 6px;
}
.venue-opacity-slider {
  flex: 1;
  accent-color: var(--gold);
}
.venue-opacity-label {
  min-width: 44px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink);
}

/* ============================================
   v2: Snapshot history list
   ============================================ */
.snapshot-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 55dvh;
  overflow-y: auto;
}
.snapshot-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}
.snapshot-row.current {
  background: var(--cream);
  border-color: var(--gold);
}
.snap-info { flex: 1; min-width: 0; }
.snap-when {
  font-weight: 600;
  color: var(--ink);
  font-size: 14px;
  margin-bottom: 4px;
}
.snap-stats {
  font-size: 12px;
  color: var(--muted);
}
.snap-current-tag {
  font-size: 11px;
  color: var(--gold-dark);
  margin-top: 4px;
  font-style: italic;
}

/* ============================================
   Section header w/ edit pill — used in Add Guest sheet so the user can
   jump into the tag/meal editor without leaving the form. Pill sits flush
   right next to the section label, muted but obviously tappable.
   ============================================ */
.sheet-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
  margin-bottom: 6px;
}
.sheet-section-header .sheet-section-label {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}
.section-edit-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  background: var(--cream);
  border: 1px solid color-mix(in srgb, var(--gold) 32%, transparent);
  border-radius: 999px;
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: transform 0.1s ease, background 0.12s ease, border-color 0.12s ease;
  /* Big-enough tap target without making the chip feel oversized */
  min-height: 28px;
}
.section-edit-pill:hover {
  background: var(--white);
  border-color: var(--gold);
}
.section-edit-pill:active {
  transform: scale(0.95);
  background: var(--white);
}

/* ============================================
   v2: Add-guest side+meal pickers (inline)
   ============================================ */
.add-guest-side-row,
.add-guest-meal-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.add-guest-side-btn,
.add-guest-meal-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.add-guest-side-btn:hover,
.add-guest-meal-btn:hover {
  border-color: var(--gold);
  background: var(--cream);
}
.add-guest-side-btn.active {
  background: var(--side-color, var(--gold));
  border-color: var(--side-color, var(--gold));
  color: var(--white);
  font-weight: 600;
}
.add-guest-side-btn.active .side-dot { background: var(--white) !important; }
.add-guest-meal-btn.active {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--on-gold);
  font-weight: 600;
}
.side-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--side-color, var(--muted));
  flex-shrink: 0;
}

/* ============================================
   v2: Stat pill as action (clickable shortcut)
   ============================================ */
button.stat-pill {
  border: 1.5px solid transparent;
  cursor: pointer;
  font: inherit;
  font-size: 14px;
}
button.stat-pill-action:hover {
  border-color: var(--gold);
  background: var(--white);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}
button.stat-pill-action:active { transform: scale(0.97); }
/* Meals pill renders like its siblings: the old gold-gradient highlight read
   as "active/alert" (on iPad the themed gold leaned red) and Carlo flagged it
   as a bug — "¿por qué está coloreado?". Neutral = no false signal.
   [device-QA iPad 2026-06-11] */

/* Restroom station */
.prop-kind-restroom .prop-shape {
  background: linear-gradient(135deg, #E8EAEF, #BFC4CD);
  border-color: #8A8F99;
}
.prop-kind-restroom .prop-staff { display: none; }

/* Dance floor needs to remain visible when only horizontal/vertical resize */
.prop-shape.prop-kind-dance .prop-emoji { font-size: calc(48px * var(--prop-emoji-scale, 1) * min(var(--prop-scale-x, 1), var(--prop-scale-y, 1))); }

/* Rotation handle — visible on hover, drag for continuous rotation */
.prop-rotate-handle {
  position: absolute;
  top: -10px;
  right: -10px;
  width: 28px;
  height: 28px;
  background: var(--coral);
  color: var(--white);
  border: 2.5px solid var(--white);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 700;
  cursor: grab;
  box-shadow: 0 2px 6px rgba(0,0,0,0.25);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
  z-index: 11;
  user-select: none;
}
/* Rotate handle visibility: hover on desktop only.
   On touch the prop sheet's "Rotación" stepper handles it — a 22 px corner
   handle can't be hit reliably with a finger and crowds the resize chip. */
@media (hover: hover) and (pointer: fine) {
  .prop-node:hover .prop-rotate-handle,
  .prop-node.rotating .prop-rotate-handle {
    opacity: 1;
  }
}
@media (hover: none) {
  /* Definitive hide — this rule lives AFTER the earlier @media (hover: none)
     block at ~line 1020, so the cascade keeps rotate hidden on phones. */
  .prop-rotate-handle { display: none !important; }
}
.prop-rotate-handle:active,
.prop-node.rotating .prop-rotate-handle {
  cursor: grabbing;
  background: var(--coral);
  transform: scale(1.1);
}
/* Disable any transform transition on prop-shape — prevents the "hover wobble" bug */
.prop-shape { transition: box-shadow var(--dur-fast) var(--ease) !important; }
.prop-node.rotating .prop-shape { transition: none !important; }

/* ============================================
   v2: Delete handles on tables + props (hover X)
   ============================================ */
.table-delete-handle,
.prop-delete-handle {
  position: absolute;
  top: -10px;
  left: -10px;
  width: 26px;
  height: 26px;
  background: var(--danger);
  color: var(--white);
  border: 2.5px solid var(--white);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0,0,0,0.25);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  z-index: 12;
  padding: 0;
  user-select: none;
}
.table-delete-handle:hover,
.prop-delete-handle:hover { background: #e6253f; transform: scale(1.15); }
/* Desktop (pointer:fine + hover:hover): reveal X on hover only */
@media (hover: hover) and (pointer: fine) {
  .table-node:hover .table-delete-handle,
  .prop-node:hover .prop-delete-handle { opacity: 1; }
}
/* Mobile (no hover capability): hide the small red delete X entirely.
   The canvas already shows the gold resize handle on every table/prop —
   stacking a second corner chip looks saturated and risks accidental
   deletes from misfires. Delete lives inside the table/prop sheet
   under "Acciones → Eliminar mesa / Eliminar estación". */
@media (hover: none) {
  .table-delete-handle,
  .prop-delete-handle { display: none; }
}

/* Meals: clickable stat + expanded list */
button.meals-stat {
  border: 1.5px solid transparent;
  cursor: pointer;
  font: inherit;
  width: 100%;
  text-align: center;
}
button.meals-stat-clickable:hover {
  border-color: var(--gold);
  background: var(--white);
  transform: translateY(-1px);
}
button.meals-stat.active {
  border-color: var(--gold);
  background: var(--white);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 15%, transparent);
}
.meals-expanded:not(:empty) {
  margin-top: 12px;
  padding: 12px;
  background: var(--cream);
  border-radius: var(--radius-md);
  border: 1px solid var(--line);
}
.meals-expanded-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 8px;
}
.meals-guest-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.meals-guest-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 13px;
}
.guest-avatar-mini {
  width: 28px; height: 28px;
  background: var(--gold-light);
  color: var(--gold-dark);
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 600;
  flex-shrink: 0;
}
.meals-guest-info { flex: 1; min-width: 0; }
.meals-guest-name { font-weight: 600; color: var(--ink); }
.meals-guest-table { font-size: 11px; color: var(--muted); margin-top: 1px; }
.meals-allergy-tag {
  font-size: 11px;
  background: #FFE9C0;
  color: #8B5A00;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid #E8C26B;
  white-space: nowrap;
}

/* Allergy chips */
.add-guest-allergy-btn {
  display: inline-flex;
  align-items: center;
  padding: 6px 10px;
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  font-size: 12px;
  color: var(--ink);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.add-guest-allergy-btn:hover { border-color: #E8A435; background: #FFF3DC; }
.add-guest-allergy-btn.active {
  background: #FFB347;
  border-color: #E8A435;
  color: #5A3700;
  font-weight: 600;
}
textarea.sheet-input { font-family: inherit; }

/* ============================================
   Emoji picker
   ============================================ */
.emoji-tab-bar {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  padding: 4px;
  background: var(--cream);
  border-radius: var(--radius-md);
  margin-bottom: 10px;
  border: 1px solid var(--line);
}
.emoji-tab {
  width: 38px;
  height: 38px;
  background: transparent;
  border: 1.5px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 20px;
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.emoji-tab:hover { background: var(--white); border-color: var(--line); }
.emoji-tab.active { background: var(--white); border-color: var(--gold); box-shadow: 0 1px 4px color-mix(in srgb, var(--gold) 25%, transparent); }

.emoji-grid-wrap {
  max-height: 50dvh;
  overflow-y: auto;
}
.emoji-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 4px;
  padding: 4px 0;
}
.emoji-cell {
  aspect-ratio: 1;
  background: var(--white);
  border: 1.5px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 26px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all var(--dur-fast) var(--ease);
  padding: 0;
  line-height: 1;
}
.emoji-cell:hover { background: var(--cream); border-color: var(--gold); transform: scale(1.05); }
.emoji-cell.selected { background: var(--gold-light); border-color: var(--gold); }
@media (max-width: 480px) {
  .emoji-grid { grid-template-columns: repeat(6, 1fr); }
  .emoji-cell { font-size: 24px; }
}

/* Emoji preview button (in prop sheet + custom prop sheet) */
.emoji-preview-btn {
  width: 70px;
  height: 70px;
  background: var(--cream);
  border: 2.5px dashed var(--gold);
  border-radius: var(--radius-md);
  font-size: 36px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  line-height: 1;
  transition: all var(--dur-fast) var(--ease);
}
.emoji-preview-btn:hover { background: var(--white); border-style: solid; transform: scale(1.05); }

.emoji-row-control {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 0;
  margin-bottom: 10px;
}
.emoji-size-box {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}
.emoji-size-label {
  font-size: 12px;
  color: var(--muted);
  margin-right: auto;
}
.emoji-size-box .stepper-btn {
  width: 30px; height: 30px;
}

/* Prop emoji uses emojiScale variable */
.prop-shape .prop-emoji {
  font-size: calc(56px * var(--prop-emoji-scale, 1) * min(var(--prop-scale-x, var(--prop-scale, 1)), var(--prop-scale-y, var(--prop-scale, 1))));
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  line-height: 1;
}
.prop-emoji-btn:hover {
  filter: brightness(1.1);
  transform: rotate(calc(-1 * var(--prop-rotation, 0deg))) scale(1.1);
}

/* ============================================
   v2: Compact guest list rows + stat filter buttons
   ============================================ */
button.gs-stat-filter {
  border: 1.5px solid transparent;
  background: var(--cream);
  cursor: pointer;
  font: inherit;
  font-size: inherit;
  transition: all var(--dur-fast) var(--ease);
}
button.gs-stat-filter:hover { border-color: var(--gold); background: var(--white); transform: translateY(-1px); }
button.gs-stat-filter.active {
  background: var(--gold);
  border-color: var(--gold-dark);
  color: var(--on-gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 20%, transparent);
}
button.gs-stat-filter.active .gs-num,
button.gs-stat-filter.active .gs-label { color: var(--on-gold); }

.gl-row-compact {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  margin-bottom: 4px;
  width: 100%;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
  min-height: 36px;
}
.gl-row-compact:hover {
  border-color: var(--gold);
  background: var(--cream);
}
.gl-avatar-sm {
  width: 26px;
  height: 26px;
  background: var(--gold-light);
  color: var(--gold-dark);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 600;
  flex-shrink: 0;
}
.gl-avatar-sm.seated {
  background: #DBEDD5;
  color: #2E6E42;
}
.gl-name {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gl-table-mini {
  font-size: 11px;
  color: var(--muted);
  font-weight: 500;
  background: var(--cream);
  padding: 2px 7px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  flex-shrink: 0;
}
.gl-table-mini.unassigned {
  background: transparent;
  color: var(--coral);
  font-style: italic;
}
.gl-meal-mini {
  font-size: 14px;
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #DBEDD5;
  border-radius: 50%;
  flex-shrink: 0;
}
.gl-meal-mini.empty { background: transparent; opacity: 0; width: 0; height: 0; padding: 0; }
.gl-meal-mini.veg { background: #C8E5B0; }
/* Interactive quick-assign (Carlo 2026-06-15): the badge is tappable. A guest
   with no meal shows a dashed "add" affordance instead of being invisible. */
.gl-meal-mini { cursor: pointer; }
.gl-meal-mini.addable { background: transparent; border: 1.5px dashed var(--line); opacity: 0.6; }
.gl-meal-mini.addable:hover { opacity: 1; border-color: var(--gold); }
.gl-meal-mini.picking { outline: 2px solid var(--gold); outline-offset: 1px; opacity: 1; }
.gl-row-wrap { width: 100%; }
/* Inline meal strip under a guest row — indented past the avatar. */
.gl-meal-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 2px 10px 8px 44px;
  margin-top: -2px;
  margin-bottom: 4px;
}
.meal-clear-sm { border-style: dashed; font-size: 15px; }
.gl-allergy-mini {
  font-size: 12px;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #FFE9C0;
  border-radius: 50%;
  flex-shrink: 0;
  color: #8B5A00;
}
.gl-captain-mini {
  font-size: 13px;
  flex-shrink: 0;
}
.gl-del-mini {
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--muted);
  border-radius: 50%;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  opacity: 0;
  transition: all var(--dur-fast) var(--ease);
  flex-shrink: 0;
}
@media (hover: hover) and (pointer: fine) {
  .gl-row-compact:hover .gl-del-mini { opacity: 1; }
  .gl-del-mini:hover { background: var(--danger); color: var(--white); }
}
/* Mobile: always show the delete button (dim) — no hover available */
@media (hover: none) {
  .gl-del-mini { opacity: 0.55; }
}

.guest-full-list { max-height: 50dvh; overflow-y: auto; padding: 4px 0; }

/* Multi-select (bulk delete) in the guest list */
.gl-check {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--line);
  border-radius: 6px;
  background: var(--white);
  color: #fff;
  font-size: 14px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.gl-check.checked {
  background: var(--accent);
  border-color: var(--accent);
}
.gl-sel-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 8px 0 4px;
  flex-wrap: wrap;
}
.gl-sel-all {
  padding: 6px 12px;
  border-radius: 999px;
  border: 1.5px solid var(--line);
  background: var(--white);
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.gl-sel-all:hover { border-color: var(--accent); background: var(--cream); }
.gl-sel-count { font-size: 13px; color: var(--muted); font-weight: 500; }
.gl-sel-delete {
  padding: 6px 14px;
  border-radius: 999px;
  border: none;
  background: var(--line);
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  cursor: not-allowed;
  transition: all var(--dur-fast) var(--ease);
}
.gl-sel-delete.ready { background: var(--danger); color: #fff; cursor: pointer; }
.gl-sel-delete.ready:hover { background: var(--danger-dark); }

/* Sheet title with an inline rename pencil (guest seat-picker, etc.) */
.sheet-title-row { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.sheet-title-edit {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1.5px solid var(--line);
  border-radius: 50%;
  background: var(--white);
  font-size: 15px;
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.sheet-title-edit:hover { border-color: var(--accent); background: var(--cream); }
.sheet-title-edit:active { transform: scale(0.94); }

/* Table-size stepper inside the Tools sheet (moved from the floating pill) */
.tools-size-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 14px;
  padding: 12px;
  background: var(--cream);
  border-radius: var(--radius-md);
}
.tools-size-rowlabel { font-size: 14px; font-weight: 600; color: var(--ink); margin-right: 4px; }

/* ============================================
   Icon mode selector (emoji / text / none)
   ============================================ */
.icon-mode-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-bottom: 12px;
}
.icon-mode-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 12px 6px;
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  font: inherit;
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.icon-mode-btn:hover { border-color: var(--gold); background: var(--cream); }
.icon-mode-btn.active {
  background: var(--gold);
  border-color: var(--gold-dark);
  color: var(--on-gold);
}
.icon-mode-icon {
  font-size: 22px;
  line-height: 1;
}
.icon-mode-label {
  font-size: 11px;
  font-weight: 500;
}
.icon-mode-btn.active .icon-mode-icon,
.icon-mode-btn.active .icon-mode-label { color: var(--white); }

/* Text label inside prop (when iconMode = 'text') */
.prop-text-label {
  font-family: var(--font-display, 'Playfair Display', Georgia, serif);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: calc(20px * var(--prop-emoji-scale, 1) * min(var(--prop-scale-x, 1), var(--prop-scale-y, 1)));
  color: var(--ink);
  text-align: center;
  padding: 0 10px;
  line-height: 1.1;
  word-break: break-word;
  transform: rotate(calc(-1 * var(--prop-rotation, 0deg)));
}

/* Captain chip — visible toggle in seated row */
.captain-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
  margin-top: 6px;
  width: fit-content;
}
.captain-chip:hover {
  border-color: var(--gold);
  background: var(--cream);
}
.captain-chip.active {
  background: var(--gold);
  border-color: var(--gold-dark);
  color: var(--on-gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 20%, transparent);
}
.captain-chip-icon { font-size: 16px; line-height: 1; }
.captain-chip-label { font-weight: 600; }

/* Captain badge — shown below seated list in table sheet */
.captain-badge {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 10px 14px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--gold) 12%, transparent), color-mix(in srgb, var(--gold) 4%, transparent));
  border: 1px solid color-mix(in srgb, var(--gold) 35%, transparent);
  border-radius: var(--radius-md);
  color: #2C2418;
  font-weight: 600;
  font-size: 14px;
}
.captain-badge-icon { font-size: 18px; line-height: 1; }
.captain-badge-label { flex: 1; word-break: break-word; }

/* ============================================
   CSV Import preview + actions
   ============================================ */
.csv-preview {
  margin-top: 14px;
  padding: 14px;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}
.csv-preview-title {
  font-weight: 700;
  font-size: 15px;
  color: var(--ink);
  margin-bottom: 8px;
}
.csv-preview-stats {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px dashed var(--line);
}
.csv-preview-sample-title {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}
.csv-preview-row {
  font-size: 13px;
  color: var(--ink);
  padding: 2px 0;
}
.csv-preview-more { color: var(--muted); font-style: italic; }
.csv-action-row {
  display: flex;
  gap: 8px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.csv-action-row .btn { flex: 1 1 auto; min-width: 140px; font-size: 13px; }
.btn-danger {
  background: var(--danger);
  color: var(--white);
  border: 1.5px solid var(--danger);
}
.btn-danger:hover { background: var(--danger-dark); border-color: var(--danger-dark); }

/* ============================================
   Add table sheet: per-kind quantity stepper
   ============================================ */
.add-table-row {
  display: flex;
  align-items: stretch;
  gap: 8px;
  margin-bottom: 8px;
}
.add-table-tap {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  cursor: pointer;
  text-align: left;
  font: inherit;
  transition: all var(--dur-fast) var(--ease);
}
.add-table-tap:hover {
  border-color: var(--gold);
  background: var(--cream);
  transform: translateY(-1px);
}
.add-table-tap.disabled,
.add-table-tap[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
  background: var(--cream);
}
.add-table-tap.disabled:hover,
.add-table-tap[disabled]:hover {
  border-color: var(--line);
  background: var(--cream);
  transform: none;
}
/* Singleton (head table) row when selected for inclusion in the batch */
.add-table-tap.selected {
  border-color: var(--gold);
  background: var(--gold-light);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 18%, transparent);
}
.add-table-tap.selected:hover {
  background: var(--gold-light);
}
.add-table-stepper {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  background: var(--cream);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  flex-shrink: 0;
}
.add-table-stepper-btn {
  width: 32px;
  height: 32px;
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: 50%;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.add-table-stepper-btn:hover { border-color: var(--gold); background: var(--cream); }
.add-table-qty {
  min-width: 28px;
  text-align: center;
  font-weight: 700;
  font-size: 16px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  padding: 0 4px;
}

/* Meals panel: 5 stats (Meat, Fish, Veg, None, Allergies) */
.meals-summary {
  grid-template-columns: repeat(5, 1fr) !important;
}
/* Allergies stat: neutral like the others when NOT selected (the ⚠️ icon is
   its identity). The warning fill shows ONLY when it's the active filter, so it
   no longer reads as "always on" next to the real selection. */
.meals-stat-allergy.active {
  background: linear-gradient(135deg, #FFE9C0, #FFD9A0) !important;
  border-color: #E8A435 !important;
  box-shadow: 0 0 0 3px rgba(232,164,53,0.35) !important;
}
.meals-stat-allergy.active .ms-num,
.meals-stat-allergy.active .ms-label { color: #8B5A00 !important; font-weight: 600; }
@media (max-width: 600px) {
  .meals-summary { grid-template-columns: repeat(3, 1fr) !important; }
}

/* ============================================
   v2: Compact seated-row inside table sheet
   ============================================ */
.seated-row-compact {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  margin-bottom: 6px;
  min-height: 44px;
}
.seat-num-badge {
  width: 22px;
  height: 22px;
  background: var(--cream);
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.guest-avatar-sm {
  width: 28px;
  height: 28px;
  background: var(--gold-light);
  color: var(--gold-dark);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
  flex-shrink: 0;
}
.src-name-wrap {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.src-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.src-side-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1.5px solid rgba(255,255,255,0.6);
  box-shadow: 0 0 0 1px var(--line);
}
.src-captain-star { font-size: 13px; flex-shrink: 0; }
.src-allergy {
  font-size: 12px;
  background: #FFE9C0;
  color: #8B5A00;
  padding: 1px 6px;
  border-radius: 50%;
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

/* 44px tap targets for the small seat-row controls (visually ~26px). [audit] */
.meal-btn-sm, .src-edit, .src-remove { position: relative; }
.meal-btn-sm::after, .src-edit::after, .src-remove::after { content: ''; position: absolute; inset: -9px; }

.meal-picker-sm {
  display: inline-flex;
  gap: 2px;
  flex-shrink: 0;
}
.meal-btn-sm {
  width: 26px;
  height: 26px;
  background: var(--cream);
  border: 1.5px solid transparent;
  border-radius: 50%;
  font-size: 13px;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0.55;
  transition: all var(--dur-fast) var(--ease);
}
.meal-btn-sm:hover { opacity: 1; border-color: var(--line); }
.meal-btn-sm.active {
  opacity: 1;
  background: #DBEDD5;
  border-color: #5CB87A;
}
/* Pencil that opens the meal-type editor — dashed so it reads as an action,
   not a selectable meal. */
.meal-edit-sm {
  opacity: 0.7;
  background: transparent;
  border-style: dashed;
  border-color: var(--line);
}
.meal-edit-sm:hover { opacity: 1; }
.src-edit, .src-remove {
  width: 26px;
  height: 26px;
  background: transparent;
  border: none;
  border-radius: 50%;
  color: var(--muted);
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: all var(--dur-fast) var(--ease);
}
.src-edit:hover { background: var(--cream); color: var(--ink); }
.src-remove:hover { background: var(--danger); color: var(--white); }

/* Sheet back-navigation row */
.sheet-back-row {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px 6px 8px;
  margin-bottom: 12px;
  background: var(--cream);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.sheet-back-row:hover {
  border-color: var(--gold);
  background: var(--white);
  transform: translateX(-2px);
}
.sheet-back-arrow { font-size: 16px; font-weight: 700; line-height: 1; }
.sheet-back-label { font-weight: 500; }

/* ============================================
   Captains bulk picker: tables + chips per table
   ============================================ */
.captains-tables-wrap {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 55dvh;
  overflow-y: auto;
}
.captains-table-block {
  padding: 10px 12px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}
.captains-table-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px dashed var(--line);
}
.captains-table-name { font-weight: 700; color: var(--ink); font-size: 14px; }
.captains-table-empty { font-size: 12px; color: var(--muted); font-style: italic; }
.captains-bottle-input {
  padding: 6px 12px;
  background: var(--cream);
  border: 1.5px solid var(--gold);
  border-radius: var(--radius-pill);
  /* 16px prevents iOS auto-zoom on focus */
  font-size: 16px;
  color: var(--ink);
  width: 140px;
}
.captains-bottle-input:focus { outline: none; background: var(--white); }
.captains-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.captains-guest-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px 5px 5px;
  background: var(--cream);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  font: inherit;
  font-size: 12px;
  color: var(--ink);
  cursor: pointer;
  transition: all var(--dur-fast) var(--ease);
}
.captains-guest-chip:hover {
  border-color: var(--gold);
  background: var(--white);
}
.captains-guest-chip.active {
  background: var(--gold);
  border-color: var(--gold-dark);
  color: var(--on-gold);
  font-weight: 600;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--gold) 25%, transparent);
}
.captains-chip-avatar {
  width: 22px;
  height: 22px;
  background: var(--gold-light);
  color: var(--gold-dark);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  flex-shrink: 0;
}
.captains-guest-chip.active .captains-chip-avatar {
  background: var(--white);
  color: var(--gold-dark);
}
.captains-chip-mark { font-size: 14px; line-height: 1; }

/* Venue image D-pad (move floor map without breaking canvas pan) */
.venue-dpad {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  padding: 12px;
  background: var(--cream);
  border-radius: var(--radius-md);
  border: 1px solid var(--line);
}
.venue-dpad-row {
  display: flex;
  gap: 6px;
}
.venue-dpad-btn {
  width: 44px;
  height: 44px;
  background: var(--white);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  font-size: 20px;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: all var(--dur-fast) var(--ease);
}
.venue-dpad-btn:hover { border-color: var(--gold); background: var(--cream); }
.venue-dpad-btn:active { transform: scale(0.92); }
.venue-dpad-center {
  background: var(--gold-light);
  color: var(--gold-dark);
  font-size: 18px;
}
.venue-dpad-spacer { width: 44px; height: 44px; }

/* Pending sidebar: header for 'already seated' search matches */
.pending-section-header {
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 12px 4px 6px;
  margin-top: 8px;
  border-top: 1px solid var(--line);
}
.guest-chip.seated-chip {
  background: var(--cream);
  border-style: dashed;
}
.guest-chip.seated-chip:hover { background: var(--white); border-style: solid; }
.guest-chip .guest-avatar.seated { background: #DBEDD5; color: #2E6E42; }
.pending-seat-badge {
  font-size: 11px;
  background: var(--white);
  color: var(--muted);
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  white-space: nowrap;
  margin-left: auto;
  flex-shrink: 0;
}


/* ════════════════════════════════════════════════════════════════
   FAB (Floating Action Button) — mobile-only entry to tools sheet.
   Hidden on desktop where the toolbar is visible.
   ════════════════════════════════════════════════════════════════ */
.app-fab {
  display: none;
}

@media (max-width: 640px) {
  .app-fab {
    display: flex;
    /* Anchored inside .canvas-wrap (above the drawer), same context as
       .app-controls, so both share a baseline and track the drawer. */
    position: absolute;
    right: 12px;
    bottom: 12px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--gold), var(--gold-dark));
    color: var(--white);
    border: none;
    box-shadow: 0 6px 18px rgba(184, 92, 61, 0.30), 0 2px 6px rgba(0, 0, 0, 0.18);
    cursor: pointer;
    align-items: center;
    justify-content: center;
    z-index: 100;
    transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
    padding: 0;
  }
  .app-fab:active {
    transform: scale(0.92);
    box-shadow: 0 3px 10px rgba(184, 92, 61, 0.35);
  }
  /* While the floating controls tray is open, fade the FAB out so the expanded
     zoom/table controls don't collide with it (they share the bottom row on
     narrow phones). Tapping the canvas or the toggle restores it. */
  .app.controls-open .app-fab {
    opacity: 0;
    transform: scale(0.6);
    pointer-events: none;
  }
  .app-fab-icon {
    font-size: 28px;
    line-height: 1;
    font-weight: 300;
  }
  /* FAB now lives in .canvas-wrap, which already shrinks above the drawer, so
     it tracks the drawer automatically — no manual --drawer-h reposition. */

  /* Inviting pulse when the canvas is essentially empty (no regular tables,
     no props). Pulsates the gold ring so a first-time user notices the FAB
     without us shouting at them. JS adds .needs-attention when applicable. */
  .app-fab.needs-attention::before {
    content: '';
    position: absolute;
    inset: -4px;
    border-radius: 50%;
    border: 2px solid var(--gold);
    opacity: 0.5;
    animation: fab-pulse 1.8s cubic-bezier(0.4, 0, 0.6, 1) infinite;
    pointer-events: none;
  }
  @keyframes fab-pulse {
    0%   { transform: scale(1);    opacity: 0.55; }
    70%  { transform: scale(1.35); opacity: 0;   }
    100% { transform: scale(1.35); opacity: 0;   }
  }
  /* Respect reduced motion — keep visual cue without the animation */
  @media (prefers-reduced-motion: reduce) {
    .app-fab.needs-attention::before {
      animation: none;
      opacity: 0.4;
    }
  }
}

/* ════════════════════════════════════════════════════════════════
   Canvas hint — first-time guidance arrow pointing to the FAB.
   Only visible on mobile when the canvas has no user-added content.
   ════════════════════════════════════════════════════════════════ */
/* ════════════════════════════════════════════════════════════════
   Prop sheet — Width / Height / Angle steppers. Two-column grid for
   width + height so they line up visually, full-width rotation below.
   ════════════════════════════════════════════════════════════════ */
.prop-size-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 10px;
}
.prop-size-stepper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 8px;
  background: var(--cream);
  border-radius: var(--radius-md);
}
.prop-size-stepper .prop-size-label {
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}
.prop-size-stepper .stepper {
  gap: 8px;
}

/* ════════════════════════════════════════════════════════════════
   Table sheet — "+ Add guest to this table" button. Sits between the
   Seated list and the Actions block so it reads as "you can add to
   this list," not buried in a menu of destructive options.
   ════════════════════════════════════════════════════════════════ */
.table-add-guest-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
}
.table-add-guest-btn .btn-icon {
  font-size: 18px;
  font-weight: 400;
  line-height: 1;
}
.table-add-guest-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ════════════════════════════════════════════════════════════════
   Floating table-size stepper (mobile-only). Lives bottom-left, mirrors
   the FAB on the bottom-right. Always visible so the user never has to
   open the Tools sheet just to nudge the tables bigger/smaller.
   ════════════════════════════════════════════════════════════════ */
.app-controls { display: none; }

@media (max-width: 640px) {
  /* Collapsible floating controls, anchored to the BOTTOM of the canvas area
     (its parent .canvas-wrap is flex:1 above the drawer). Because it lives in
     the canvas box — not position:fixed to the screen — it always sits just
     above the drawer and never overlaps it, even when iOS Safari's text-size
     control reflows the layout. */
  .app-controls {
    position: absolute;
    left: 12px;
    /* bottom:17 (vs the FAB's 12) so the 46px control row and the 56px FAB
       share the SAME vertical center — they read as one aligned row. */
    bottom: 17px;
    z-index: 60;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    pointer-events: none; /* children re-enable; taps pass through the gap */
    user-select: none;
    transition: opacity 0.16s ease, transform 0.16s ease;
  }
  /* The floating controls stay visible when the drawer opens — they're anchored
     to the bottom of the canvas area (above the drawer), so like the FAB they
     sit just above it without covering the "Guests to seat" header. (Carlo
     wanted the zoom lupita reachable while the guest list is open.) */
  /* Always-visible round toggle. Tap to expand/collapse the tray. */
  .app-controls-toggle {
    pointer-events: auto;
    flex: none;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: var(--white);
    border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
    box-shadow: 0 4px 14px rgba(44, 36, 24, 0.16), 0 1px 3px rgba(0, 0, 0, 0.06);
    color: var(--ink);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.14s ease, transform 0.12s ease, border-color 0.14s ease;
  }
  .app-controls-toggle:active { transform: scale(0.92); }
  .app-controls-toggle svg { width: 22px; height: 22px; display: block; }
  .app-controls[data-collapsed="false"] .app-controls-toggle {
    background: var(--gold-light);
    border-color: var(--gold-dark);
  }

  /* The expanding tray (zoom -/+, editable %, table-size stepper, search). */
  .app-controls-tray {
    pointer-events: auto;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    height: 46px;
    padding: 0 6px;
    background: var(--white);
    border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
    border-radius: 999px;
    box-shadow: 0 4px 14px rgba(44, 36, 24, 0.14), 0 1px 3px rgba(0, 0, 0, 0.06);
    transform-origin: left center;
    transition: opacity 0.16s ease, transform 0.2s cubic-bezier(0.2, 0.7, 0.3, 1);
  }
  .app-controls[data-collapsed="true"] .app-controls-tray {
    opacity: 0;
    transform: scaleX(0.55) translateX(-10px);
    pointer-events: none;
    visibility: hidden;
  }
  .app-controls[data-collapsed="false"] .app-controls-tray {
    opacity: 1;
    transform: none;
    visibility: visible;
  }
  .app-controls-tray button {
    width: 36px;
    height: 36px;
    border: none;
    background: transparent;
    color: var(--ink);
    font-size: 22px;
    font-weight: 500;
    line-height: 1;
    border-radius: 50%;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.12s ease, transform 0.1s ease;
  }
  .app-controls-tray button:active { background: var(--cream); transform: scale(0.92); }

  /* Editable zoom %. Tap to type an exact value (see App.editZoom). */
  .app-controls-value {
    min-width: 52px !important;
    width: auto !important;
    height: 34px !important;
    padding: 0 8px !important;
    font-size: 14px !important;
    font-weight: 700 !important;
    letter-spacing: -0.01em;
    background: var(--cream) !important;
    border: 1px solid var(--border) !important;
    border-radius: 999px !important;
    color: var(--ink);
  }
  .app-controls-value:active { background: var(--gold-light) !important; }

  .app-controls-sep {
    width: 1px;
    align-self: stretch;
    margin: 9px 4px;
    background: color-mix(in srgb, var(--gold) 28%, transparent);
  }
  .app-controls-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--ink);
    opacity: 0.62;
    padding: 0 2px;
    letter-spacing: -0.01em;
    white-space: nowrap;
    pointer-events: none;
  }
  .app-controls-search { font-size: 16px !important; }
}



/* Tools sheet — quick "table size" stepper at the bottom */
.tools-size-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}
.tools-size-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
}
.tools-size-stepper {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 2px 4px;
}
.tools-size-stepper .stepper-btn {
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  font-size: 18px;
  font-weight: 600;
  color: var(--gold-dark);
  cursor: pointer;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.tools-size-stepper .stepper-btn:active {
  background: var(--cream);
  transform: scale(0.92);
}
.tools-size-value {
  min-width: 48px;
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

/* ── Desktop sheet = centered modal ──────────────────────────────────────
   On mobile the sheet is a bottom-sheet (correct native idiom). On desktop a
   bottom strip looks cut off / off-center on tall screens, so center it as a
   modal with a soft fade. [Carlo: table sheet se veía raro en escritorio] */
@media (min-width: 641px) {
  .sheet {
    top: 50%;
    bottom: auto;
    transform: translate(-50%, -50%);
    opacity: 0;
    border-radius: var(--radius-xl);
    max-height: 88vh;
    transition: opacity 0.22s var(--ease), transform 0.22s var(--ease);
  }
  .sheet.visible {
    transform: translate(-50%, -50%);
    opacity: 1;
  }
  .sheet.sheet-compact { max-height: 72vh; }
}

/* ── Centered brand mark in the in-app header (wide desktop only) ─────────
   Fills the empty middle of the header with the Brindis wordmark so the bar
   doesn't look bare. Hidden on mobile/narrow (header is already full there;
   avoids overlapping a long event title). [Carlo] */
.app-header-brand { display: none; }
@media (min-width: 900px) {
  .app-header { position: relative; }
  .app-header-brand {
    display: flex;
    align-items: center;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    pointer-events: none;
    opacity: 0.9;
  }
  .app-header-brand img { height: 32px; width: auto; display: block; }
}

/* ════════════════════════════════════════════════════════════════
   SEATING VIEW — focused single-table seat assignment (Zola-style).
   Opened from the table sheet ("Acomodar lugares"). Reuses the canvas
   drag system: seats carry class .seat + data-table-id/data-seat-index,
   so Seating.beginDrag → dropOnSeat resolve drops here for free.
   Desktop: docks right. Mobile: bottom sheet. 2-initial circles, full
   name on hover/tap (Carlo-approved design).
   ════════════════════════════════════════════════════════════════ */
.sv-backdrop {
  position: fixed; inset: 0; z-index: 1200;
  background: rgba(44, 36, 24, 0.32);
  opacity: 0; transition: opacity 0.2s ease;
  display: flex; justify-content: flex-end;
}
.sv-backdrop.open { opacity: 1; }
.sv-panel {
  background: var(--surface-elevated);
  width: 460px; max-width: 100%; height: 100%;
  display: flex; flex-direction: column;
  box-shadow: -12px 0 40px rgba(44, 36, 24, 0.18);
  transform: translateX(24px); transition: transform 0.22s cubic-bezier(0.2,0.7,0.3,1);
  position: relative; /* anchor for the inline seat picker overlay */
}
.sv-backdrop.open .sv-panel { transform: none; }
.sv-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  padding: 20px 22px 14px; border-bottom: 1px solid var(--border);
}
.sv-head h3 { font-family: var(--font-display); font-weight: 600; font-size: 24px; margin: 0; line-height: 1.1; color: var(--ink); }
.sv-head .sv-cap { font-size: 13.5px; color: var(--text-soft); margin-top: 4px; }
.sv-head .sv-cap b { color: var(--success); }
.sv-x {
  width: 38px; height: 38px; border-radius: 12px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-soft); font-size: 17px;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer; flex: none;
}
.sv-ringwrap { padding: 22px 16px 6px; display: flex; justify-content: center; align-items: center; }
.sv-ring { position: relative; }
.sv-center {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
  border-radius: 50%; background: #EAF6EE; border: 2px solid var(--success);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.sv-center.rect { border-radius: 14px; }
.sv-center .sv-tn { font-family: var(--font-display); font-weight: 600; font-size: 30px; color: var(--ink); line-height: 1; }
.sv-center .sv-ts { font-size: 11px; color: var(--text-soft); margin-top: 3px; }
/* A seat in the view: bigger 2-initial circle. .seat (canvas) styles are
   overridden here; we keep the .seat class only for drag-target detection. */
.sv-ring .seat {
  position: absolute; width: 50px; height: 50px; margin: -25px 0 0 -25px;
  border-radius: 50%; box-sizing: border-box; left: auto; top: auto;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; letter-spacing: 0.02em; cursor: grab;
}
.sv-ring .seat.empty {
  background: var(--surface); border: 1.5px dashed #C5B79A; color: var(--text-muted); font-weight: 600; font-size: 20px;
}
.sv-ring .seat.occupied { color: #fff; box-shadow: 0 2px 5px rgba(44,36,24,0.18); border: 2px solid rgba(255,255,255,0.65); text-shadow: 0 1px 2px rgba(0,0,0,0.32); }
.sv-ring .seat .sv-tip {
  position: absolute; bottom: 116%; left: 50%; transform: translateX(-50%); z-index: 5;
  background: #2C2418; color: #fff; font-size: 12px; font-weight: 600; white-space: nowrap;
  padding: 4px 9px; border-radius: 7px; box-shadow: 0 4px 12px rgba(44,36,24,0.3);
  opacity: 0; pointer-events: none; transition: opacity 0.12s ease;
}
.sv-ring .seat:hover .sv-tip, .sv-ring .seat:focus .sv-tip { opacity: 1; }
.sv-ring .seat.drop-target { outline: 3px solid var(--gold); outline-offset: 2px; }
/* hide the canvas person figure / seat-name inside view seats — we use initials */
.sv-ring .seat .person, .sv-ring .seat .seat-name { display: none; }

.sv-tray {
  margin-top: auto; border-top: 1px solid var(--border);
  padding: 14px 18px calc(max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px)) + 18px); background: var(--surface);
}
.sv-tray h4 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-soft); margin: 0 0 10px; font-weight: 700; }
.sv-tray-row { display: flex; gap: 8px; flex-wrap: wrap; max-height: 22dvh; overflow-y: auto; }
.sv-chip {
  display: flex; align-items: center; gap: 7px; background: var(--surface-elevated);
  border: 1px solid var(--border); border-radius: 999px; padding: 6px 12px 6px 6px;
  font-size: 13px; font-weight: 500; box-shadow: 0 1px 3px rgba(44,36,24,0.08); cursor: grab; touch-action: none;
}
.sv-chip .sv-d { width: 22px; height: 22px; border-radius: 50%; color: #fff; font-size: 10px; font-weight: 700; display: flex; align-items: center; justify-content: center; flex: none; }
.sv-tray-empty { font-size: 13px; color: var(--text-muted); font-style: italic; }
.sv-hint { font-size: 12px; color: var(--text-muted); margin: 12px 2px 0; line-height: 1.5; }

@media (max-width: 640px) {
  .sv-backdrop { align-items: flex-end; justify-content: center; }
  .sv-panel {
    width: 100%; height: auto; max-height: 90dvh;
    border-radius: 20px 20px 0 0;
    transform: translateY(28px);
  }
  .sv-backdrop.open .sv-panel { transform: none; }
}

/* Tray becomes a drop zone when dragging a seated guest back to unassigned. */
.sv-tray.drop-target {
  outline: 2px dashed var(--gold-dark);
  outline-offset: -6px;
  background: var(--gold-light);
}

/* Friendly, inviting entry to the seating view (was a dark "🪑 Arrange seats"
   that Carlo found un-intuitive). Warm champagne fill, dark legible text. */
.sv-open-btn {
  background: linear-gradient(135deg, var(--gold-light), var(--gold));
  color: var(--on-gold);
  border: 1px solid var(--gold-dark);
  font-weight: 600;
  box-shadow: 0 2px 8px rgba(217, 184, 112, 0.32);
}
.sv-open-btn:hover { filter: brightness(1.03); }
.sv-open-btn:active { transform: scale(0.98); }

/* Inline seat picker (tap an empty seat → choose an unassigned guest). Sits
   over the seating view because a Sheet would render behind its backdrop. */
/* Inline drawers (empty-seat picker + seated-guest editor) live in the normal
   flow below the ring — NOT as an absolute overlay — so the seat circle stays
   visible while assigning or editing. When a drawer is open the tray is hidden
   (.sv-has-inline) to free the space, and the ring is pinned (never shrinks). */
.sv-drawer {
  flex: 1 1 auto; min-height: 0; z-index: 10;
  background: var(--surface-elevated);
  display: flex; flex-direction: column;
  border-top: 1px solid var(--border);
  box-shadow: 0 -10px 24px rgba(44, 36, 24, 0.10);
}
.sv-panel.sv-has-inline > .sv-tray { display: none; }
.sv-ringwrap { flex: 0 0 auto; }
.sv-editor-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: 14px 18px calc(max(env(safe-area-inset-bottom, 0px), var(--safe-bottom, 0px)) + 16px);
}
.sv-picker { border-radius: 0; }
.sv-picker-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 20px 12px; border-bottom: 1px solid var(--border);
}
.sv-picker-head h4 { font-family: var(--font-display); font-weight: 600; font-size: 19px; margin: 0; color: var(--ink); }
.sv-picker-x {
  width: 34px; height: 34px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text-soft); font-size: 15px; cursor: pointer; flex: none;
}
.sv-picker-list { flex: 1; overflow-y: auto; padding: 8px 12px 18px; }
.sv-picker-row {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  background: transparent; border: none; border-radius: 12px; padding: 11px 12px;
  font-size: 15px; color: var(--ink); cursor: pointer;
}
.sv-picker-row:hover { background: var(--surface); }
.sv-picker-row:active { background: var(--gold-light); }
.sv-picker-name { font-weight: 500; }

/* ── iPad / touch tablets ───────────────────────────────────────────
   iPad uses the DESKTOP layout (>640px) but is operated with fingers, so the
   desktop toolbar + header controls (sized for a mouse) are below Apple's 44px
   minimum touch target. Bump them on coarse-pointer tablets only — phones
   (≤640px) already have their own touch-sized controls, and mouse desktops
   keep the compact size. */
@media (pointer: coarse) and (min-width: 641px) {
  .app-header-left .icon-btn,
  .app-header-right .icon-btn { min-width: 44px; min-height: 44px; }
  .canvas-controls button,
  .canvas-controls .btn-inline { min-height: 44px; }
}

/* Smart alignment guides shown while dragging a table (Canva-style). Live
   inside #canvas so they scale with zoom; drawn at the matched canvas coords. */
#align-guides { position: absolute; inset: 0; pointer-events: none; z-index: 60; }
.align-guide { position: absolute; background: var(--danger); pointer-events: none; opacity: 0.85; }
.align-guide.v { width: 1.5px; top: 0; }
.align-guide.h { height: 1.5px; left: 0; }

/* Back arrow in the seating view header → returns to the table sheet. */
.sv-head-left { display: flex; align-items: flex-start; gap: 10px; min-width: 0; }
.sv-back {
  width: 38px; height: 38px; flex: none; border-radius: 12px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-soft); font-size: 24px; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-body); padding: 0 0 2px 0;
}
.sv-back:active { background: var(--gold-light); }

/* Multi-select "seat guests" rows go disabled once the table's free seats are
   all checked — you can't select more than fit. Shared by mobile/iPad/desktop. */
.choice-row.choice-row-disabled { opacity: 0.4; cursor: not-allowed; }

/* Custom scrollbar for the seating-view unassigned tray (iOS hides native
   ones; chips hijack touch for dragging). Visible track + draggable thumb in a
   chip-free right gutter. [Carlo: a visible bar to scroll without grabbing a chip] */
.sv-scrollwrap { position: relative; }
.sv-scrollwrap .sv-tray-row { padding-right: 18px; }
.sv-scrolltrack {
  position: absolute; top: 4px; bottom: 4px; right: 4px; width: 6px;
  border-radius: 999px; background: color-mix(in srgb, var(--gold) 20%, transparent);
  pointer-events: none;
}
.sv-scrollthumb {
  position: absolute; right: 3px; width: 8px; min-height: 30px;
  border-radius: 999px; background: var(--gold-dark); opacity: 0.65;
  cursor: grab; touch-action: none; z-index: 3;
}
.sv-scrollthumb:active { opacity: 0.9; cursor: grabbing; }

/* Full-screen cover shown WHILE exporting an image. The export briefly
   repositions the on-screen canvas to capture it at 1:1; this calm cover hides
   that jump (Carlo saw the plan slide to the corner and back on iPad). It lives
   OUTSIDE #canvas so html2canvas never captures it, and sits below the toast
   (z 1000) so the result message still shows through. */
.export-cover {
  position: fixed; inset: 0; z-index: 900;
  background: var(--cream, #FAF4E8);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  /* Opaque from the first frame so it hides the canvas jump instantly; only the
     fade-OUT is animated (a fade-in risked a flash of the shifting canvas). */
  opacity: 1; transition: opacity 0.2s ease;
}
.export-cover.hiding { opacity: 0; }
.export-cover-spin {
  width: 36px; height: 36px; border-radius: 50%;
  border: 3px solid var(--border, #e4ddd1);
  border-top-color: var(--gold, #C9A961);
  animation: brindis-spin 0.8s linear infinite;
}
.export-cover-msg {
  font-family: var(--font-display, 'Fraunces', serif);
  font-size: 18px; font-weight: 500; color: var(--ink, #2c2418);
}
@keyframes brindis-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .export-cover-spin { animation: none; } }

/* "My plan" screen (menu ☰ → Mi plan) */
.plan-card {
  border: 1.5px solid var(--line);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin-bottom: 12px;
  background: var(--white);
}
.plan-card.plan-current {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 22%, transparent);
}
.plan-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 8px;
}
.plan-name { font-family: var(--font-display, 'Fraunces', serif); font-size: 19px; font-weight: 600; color: var(--ink); }
.plan-price { font-size: 14px; font-weight: 600; color: var(--gold-dark); white-space: nowrap; }
.plan-feats { list-style: none; margin: 0 0 10px; padding: 0; }
.plan-feats li {
  font-size: 14px; color: var(--ink); padding: 3px 0 3px 22px; position: relative; line-height: 1.4;
}
.plan-feats li::before { content: '✓'; position: absolute; left: 0; color: var(--success, #5CB87A); font-weight: 700; }
.plan-badge-current {
  font-size: 13px; font-weight: 700; color: var(--gold-dark);
  text-align: center; padding: 6px 0 2px;
}

/* Proactive "free plan seats up to 30" banner (Entitlements.renderSeatLimitBanner) */
.seat-limit-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 12px 8px;
  padding: 9px 12px;
  background: color-mix(in srgb, var(--gold) 14%, var(--cream));
  border: 1px solid color-mix(in srgb, var(--gold) 40%, transparent);
  border-radius: var(--radius-md);
  font-size: 13px;
  color: var(--ink);
}
.seat-limit-banner .slb-text { flex: 1; line-height: 1.35; }
.seat-limit-banner .slb-cta {
  flex: 0 0 auto;
  /* Dark pill: AA-safe in all 8 themes (cream-on-ink ~14:1). The old
     #fff-on-gold-dark was 2.59:1, and ink-on-gold-dark fails on dark-gold
     themes — gold-dark varies per theme, so a constant gold bg can't pass. */
  background: var(--ink);
  color: var(--cream);
  border: none;
  border-radius: 999px;
  padding: 6px 12px;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.seat-limit-banner .slb-x {
  flex: 0 0 auto;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 14px;
  cursor: pointer;
  padding: 2px 4px;
}

/* Help Center (menu ☰ → Ayuda) — list → article detail → back */
.help-cat {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin: 18px 0 8px;
}
.help-row {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: 13px 14px;
  margin-bottom: 8px;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  line-height: 1.35;
}
.help-row:hover { border-color: var(--gold); }
.help-row:active { transform: scale(0.99); }
.help-back {
  background: none;
  border: none;
  color: var(--gold-dark);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  padding: 2px 0 8px;
}
.help-art-title { margin-bottom: 12px; }
.help-body {
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink);
  margin-bottom: 12px;
}

/* ════════════════════════════════════════════════════════════════════
   Header consolidation: 4 stacked strips → 2. The .app-topbar wraps
   .app-header + .app-stats and is display:contents by default, so iPhone
   (compact stack) stays UNCHANGED. On iPad (touch + tablet width) AND on
   desktop/MacBook (fine pointer, ≥900px) it becomes ONE row —
   ☰ name | stat pills | ↶ ⋯ — and the toolbar becomes a single scrollable
   strip instead of wrapping. Collapsing the toolbar then leaves only the top
   strip. The MacBook was missing this (it was gated to `pointer: coarse` =
   iPad only), so it showed 3 fat bars eating the canvas. [Carlo 2026-06-15]
   ════════════════════════════════════════════════════════════════════ */
.app-topbar { display: contents; }

@media (pointer: coarse) and (min-width: 641px), (pointer: fine) and (min-width: 900px) {
  .app-topbar {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--white);
    border-bottom: 1px solid var(--line);
    /* Same max(env, var) guard as the phone header so the iPad top bar never
       tucks under the status bar on first paint either. [v268 verify] */
    padding: calc(max(env(safe-area-inset-top, 0px), var(--safe-top, 0px)) + 10px) 14px 10px;
    z-index: 5;
  }
  /* Flatten the header so its groups join the topbar flex row beside the pills. */
  .app-topbar .app-header { display: contents; }
  .app-topbar .app-header-left { order: 1; flex: 0 1 auto; min-width: 0; }
  .app-topbar .app-header-brand { display: none; }
  .app-topbar .app-stats {
    order: 2; flex: 1 1 auto;
    background: transparent; border-bottom: none;
    padding: 0; overflow-x: auto;
  }
  .app-topbar .app-header-right { order: 3; flex: 0 0 auto; }
  .app-topbar .autosave-badge { display: none; } /* silent autosave (v254) */

  /* Toolbar = ONE scrollable strip, not wrapped into a 2nd row. */
  .canvas-controls { flex-wrap: nowrap; }
}

/* iPad PORTRAIT toolbar polish [Carlo]: landscape ("ya quedó") + desktop stay
   untouched. Drop the right-spacer that shoved the add buttons off-screen,
   reorder so +Table/+Estación show without scrolling (Lock — least important —
   goes last), and tighten the zoom + table-size controls a touch. */
@media (pointer: coarse) and (orientation: portrait) and (min-width: 641px) {
  .canvas-controls .spacer { display: none; }
  .canvas-controls > [data-action="zoom-out"],
  .canvas-controls > #zoom-label,
  .canvas-controls > [data-action="zoom-in"] { order: 1; }
  .canvas-controls > .ctl-group { order: 2; }
  .canvas-controls > [data-action="add-table"] { order: 3; }
  .canvas-controls > [data-action="add-prop"]  { order: 4; }
  .canvas-controls > [data-action="toggle-names"]  { order: 5; }
  .canvas-controls > [data-action="toggle-guides"] { order: 6; }
  .canvas-controls > [data-action="export-image"]  { order: 7; }
  /* Colors = least important → push it RIGHT, after Imagen and before Party.
     Without an explicit order it defaulted to 0 (leftmost). [Carlo 2026-06-15] */
  .canvas-controls > [data-action="open-theme"]    { order: 8; }
  .canvas-controls > .party-btn { order: 9; }
  .canvas-controls > [data-action="toggle-lock"] { order: 10; }
  /* slightly tighter zoom % and "Mesas" controls */
  .zoom-label { min-width: 30px; }
  .ctl-group { gap: 0; padding: 2px 2px; }
  .ctl-group-label { padding: 0 1px; }
}

/* Empty-canvas hint: a calm, CENTERED message shown on EVERY viewport when the
   plan has no tables yet (hidden by JS via .has-canvas-content once a table or
   prop exists). Decoupled from any button/direction so it survives label
   changes (e.g. "+ Mesa" → "Añadir mesa"). [Carlo: que esté al centro] */
.canvas-hint {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  text-align: center;
  /* Push the text BELOW the visual center: on a fresh wedding the boot scroll
     centers the head table on screen, and a dead-center hint would sit right
     on top of it. ~140px of top padding shifts the centered block ~70px down,
     clear of the table but still obviously "in the middle". */
  padding: 140px 28px 0;
  pointer-events: none;
  z-index: 4;
  animation: canvas-hint-fade-in 0.6s 0.3s ease-out backwards;
}
.canvas-hint-title { font-family: var(--font-display); font-size: 22px; font-weight: 600; color: var(--ink); }
.canvas-hint-sub { font-size: 15px; color: var(--muted); }
.app.has-canvas-content .canvas-hint { display: none; }

/* First-run affordance [Carlo 2026-06-15]: until the first table/prop exists,
   gently glow the "Add table" button AND the empty-state hint title in sync, so
   a newcomer instantly sees where to start. Stops the moment there's content. */
@keyframes brindis-start-glow {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--gold) 0%, transparent); }
  50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--gold) 30%, transparent); }
}
.app:not(.has-canvas-content) [data-action="add-table"] {
  animation: brindis-start-glow 1.8s ease-in-out infinite;
  border-color: var(--gold);
}
@keyframes brindis-hint-glow {
  0%, 100% { text-shadow: none; }
  50% { text-shadow: 0 0 14px color-mix(in srgb, var(--gold) 55%, transparent); }
}
.app:not(.has-canvas-content) .canvas-hint-title {
  animation: brindis-hint-glow 1.8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .app:not(.has-canvas-content) [data-action="add-table"],
  .app:not(.has-canvas-content) .canvas-hint-title { animation: none; }
}
@keyframes canvas-hint-fade-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) { .canvas-hint { animation: none; } }

/* Toolbar scroll affordance [Carlo]: a soft gold gradient that gently pulses on
   the RIGHT edge of the toolbar when it overflows (more icons to scroll to), so
   a first-time user knows to swipe right. JS (App.updateToolbarScrollHint) shows
   it only while overflowing + not-yet-discovered; it fades for good once the
   user scrolls the toolbar once (localStorage 'brindis.toolbarSeen'). */
.toolbar-scroll-glow {
  position: absolute;
  top: 0;
  right: 0;
  width: 46px;
  pointer-events: none;
  z-index: 6;
  opacity: 0;
  background: linear-gradient(to left, color-mix(in srgb, var(--gold) 55%, transparent), transparent);
  transition: opacity 0.4s ease;
}
.canvas-wrap.show-toolbar-glow .toolbar-scroll-glow {
  opacity: 1;
  animation: toolbar-more-pulse 1.7s ease-in-out infinite;
}
@keyframes toolbar-more-pulse {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 0.95; }
}
@media (prefers-reduced-motion: reduce) {
  .canvas-wrap.show-toolbar-glow .toolbar-scroll-glow { animation: none; opacity: 0.7; }
}

/* Toolbar collapse handle: a labeled, intuitive "Ocultar / Mostrar herramientas"
   affordance (chevron flips by state) instead of the bare grip line — the old
   grip didn't communicate what it did. JS sets the label (App._updateToolbarHandleLabel).
   Mobile keeps the handle hidden (toolbar lives in the FAB there). [Carlo] */
.controls-handle {
  height: auto;
  min-height: 24px;
  gap: 6px;
  font-size: 11px;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0.01em;
  padding: 4px 0;
}
.controls-handle-grip { display: none; }
.controls-handle-chevron {
  font-size: 13px;
  line-height: 1;
  transition: transform 0.2s var(--ease, ease);
}
.canvas-wrap.controls-collapsed .controls-handle-chevron { transform: rotate(180deg); }
.controls-handle:hover .controls-handle-label,
.controls-handle:hover .controls-handle-chevron { color: var(--gold-dark); }

/* First-time seat coachmark at the top of the pending list. Subtle + dismissable;
   auto-hides once the user seats anyone. [Carlo: drag-to-seat discoverability] */
.pending-hint {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 2px 0 10px;
  padding: 8px 8px 8px 12px;
  background: color-mix(in srgb, var(--gold) 12%, var(--white));
  border: 1px solid color-mix(in srgb, var(--gold) 30%, transparent);
  border-radius: 12px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink);
  animation: ph-fade 0.3s var(--ease, ease) both;
}
@keyframes ph-fade { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.pending-hint .ph-text { flex: 1; font-weight: 500; }
.pending-hint .ph-x {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s ease, color 0.12s ease;
}
.pending-hint .ph-x:hover { background: color-mix(in srgb, var(--gold) 20%, transparent); color: var(--ink); }
@media (pointer: coarse) { .pending-hint .ph-x { width: 40px; height: 40px; } }
@media (prefers-reduced-motion: reduce) { .pending-hint { animation: none; } }
