/*
  style.css
  ---------
  Plain CSS, no framework. Organized top to bottom roughly in the order
  things appear on screen: resets, layout, header, cards/forms, tab bar.
*/

:root {
  /* SetOut design tokens - light/off-white "warm" palette, confirmed
     2026-09-07 (see product-decisions.md's "SetOut wordmark, logo, and
     favicon" section). Replaces the earlier dark-mode placeholder
     defaults across the whole app, not just the lockup/favicon. */
  --bg: #FAF7F4;
  --surface: #FFFFFF;
  --surface-2: #F4EEEA;
  --border: #E8E0D9;
  --ink: #312F3B;
  --ink-soft: #6F6971;
  --ink-faint: #A79EA6;
  --accent: #66719E;
  --accent-soft: #E5E8F1;
  --accent-vivid: #4459AB;
  --accent-2: #4459AB;
  --tint: #C9BAB4;
  --tint-soft: #F4E9E4;
  --danger: #D65B4A;
  /* "Your changes haven't reached the server yet" (LUV-43): the only
     amber in the app, used only by the "Waiting to sync" status. Not as
     alarming as --danger, but clearly different from the calm grey
     states. 4.9:1 contrast on --bg. */
  --sync-waiting: #9A6314;
  --radius: 16px;
  --radius-pill: 999px;
  --shadow-card: 0 1px 2px rgba(49, 47, 59, .06), 0 10px 24px -16px rgba(49, 47, 59, .22);

  --font-display: "Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif;
  --font-body: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* --accent-2 and --danger are NOT part of the confirmed design pass
     (that covered bg/surface/ink/accent/tint plus the logo only) - these
     are a best-fit placeholder to keep the palette coherent, not a
     locked decision. Worth a direct look before treating as final. */

  /* Stage colors (kanban column), used on the Ideas-board Map view.
     Deliberately NOT reusing --accent/--accent-2/--danger, since those
     already mean something else on every card (activity type, style,
     urgent/reservation badges) - a pin/dot in one of those colors would
     look like it meant "activity type" or "urgent," not "stage."
     These are placeholder swatches, not a locked design-language
     decision - see product-decisions.md's Map view mockup section.
     Real colors (these included) get decided in the design-language
     pass once the data layer and functionality are finalized. */
  --stage-ideas: #a78bfa;
  --stage-plan: #2dd4bf;
  --stage-itinerary: #4ade80;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  /* Respect the iPhone's notch / home indicator when installed full-screen */
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 800;
  margin: 0;
}

#app {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.app-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 16px 12px;
  position: sticky;
  top: 0;
  background: var(--bg);
  z-index: 5;
}

.app-header h1 {
  font-size: 1.25rem;
  margin: 0;
}

/* Left-hand cluster on every sub-page header: the SetOut lockup
   (tap = go Home) with the screen's own title stacked below it. Home
   screen doesn't use this - it just shows the lockup alone. See
   subpageHeaderHtml()/brandLockupSvg() in app.js. */
.app-header .header-left {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.app-header .page-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 240px;
  /* Placeholder look for now - real type treatment is a design-
     language-pass decision, not made here. This only proves position. */
}
.app-header .icon-btn {
  flex: none;
}

/* SetOut brand lockup - see app.js's brandLockupSvg(). Reversed
   (light-on-dark) colors and the Bricolage Grotesque font are scoped
   to just these two spans, not the app's base font - the wider
   typography decision is still on hold until the design-language
   pass. Used standalone as an <h1> on Home, and inside .header-left
   as a plain <div> everywhere else (the page title takes the <h1>
   role there instead). */
.app-header .brand-lockup {
  display: flex;
  align-items: center;
  cursor: pointer;
}
.app-header .brand-lockup span {
  letter-spacing: -0.01em;
}
.app-header .brand-lockup .word-set {
  font-family: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-weight: 800;
  color: var(--ink);
}
.app-header .brand-lockup .word-out {
  font-family: "Yeseva One", serif;
  font-weight: 400;
  color: var(--accent-vivid);
}
.app-header .brand-lockup svg {
  margin: 0 3px;
  flex: none;
}

.screen {
  flex: 1;
  padding: 8px 16px 96px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.muted {
  color: var(--ink-soft);
}

.small {
  font-size: 0.85rem;
}

.card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 12px;
}

.card h2 {
  font-size: 1rem;
  margin: 0 0 10px;
}

.trip-row, .list-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  cursor: pointer;
}

.trip-name, .row-title {
  font-weight: 600;
}

.row-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.amount {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.note-body {
  white-space: pre-wrap;
  color: var(--ink-soft);
  margin-top: 4px;
}

.empty-state {
  padding: 24px 4px;
  text-align: center;
  line-height: 1.5;
}

.icon-btn {
  background: none;
  border: none;
  color: var(--ink);
  font-size: 1.3rem;
  line-height: 1;
  padding: 4px 8px;
  cursor: pointer;
}

.icon-btn.danger {
  color: var(--danger);
}

.check-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--surface-2);
}

.check-row:last-of-type {
  border-bottom: none;
}

.check-row span {
  flex: 1;
}

.checked-text {
  text-decoration: line-through;
  color: var(--ink-soft);
}

.check-row input[type="checkbox"] {
  width: 20px;
  height: 20px;
  accent-color: var(--accent);
}

.total-card {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
}

.total-amount {
  color: var(--accent);
  font-size: 1.1rem;
}

/* ---------------------------- Forms ---------------------------- */

.form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-bottom: 10px;
}

.form input,
.form select,
.form textarea {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  color: var(--ink);
  font-size: 1rem;
  font-family: inherit;
}

.form textarea {
  min-height: 64px;
  resize: vertical;
}

.form .row {
  display: flex;
  gap: 10px;
}

.form .row > label {
  flex: 1;
}

button.primary {
  width: 100%;
  background: var(--accent);
  color: #04121f;
  border: none;
  border-radius: 10px;
  padding: 12px;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  margin-top: 4px;
}

button.primary:active {
  opacity: 0.85;
}

/* -------------------------- Ideas board (kanban) --------------------------- */
/* The ideation board (Ideas tab): a 3-column kanban board (The Ideas /
   The Plan / The Itinerary), reviewed first as a mockup in
   mockup/kanban-mockup.html (now retired - its final approved state is
   what this section and the Ideas-tab rendering in app.js are built
   from). See product-decisions.md for what each field means and how
   columns are derived from the data, and hard-to-change-log.md for
   which of these choices are cheap to revisit later (mostly
   wording/colors) vs. not (the underlying field names in storage.js). */

.kanban-board {
  display: flex;
  gap: 20px;
  align-items: stretch;
  overflow-x: auto;
  padding-bottom: 12px;
}

/* flex: 1 1 0 makes all three columns share the full board width
   equally, so the board fills a laptop screen instead of hugging card
   width; max-width is just a ceiling for very wide monitors. */
.kanban-column {
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  min-width: 260px;
  max-width: 560px;
}

.kanban-column-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 12px 2px;
}

.kanban-column-header h2 {
  margin: 0;
  font-size: 1rem;
}

.kanban-column-count {
  color: var(--ink-soft);
  font-size: 0.8rem;
}

/* flex: 1 makes this fill all remaining vertical space in the column
   (itself stretched to match the tallest column), so the whole column
   body accepts a drop, not just a thin strip hugging the cards. */
.kanban-dropzone {
  flex: 1;
  min-height: 180px;
  border-radius: var(--radius);
  padding: 4px;
  transition: background 0.15s ease, outline 0.15s ease;
  outline: 2px dashed transparent;
  outline-offset: -2px;
}

.kanban-dropzone.drag-over {
  background: rgba(102, 113, 158, 0.08);
  outline-color: var(--accent);
}

.kanban-card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin-bottom: 10px;
  cursor: grab;
  border: 1px solid var(--border);
}

.kanban-card[draggable="true"]:active {
  cursor: grabbing;
}

.kanban-card.dragging {
  opacity: 0.35;
}

.kanban-card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.kanban-card-title-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
}

/* Bigger, colored, circular - reads as a button, not a stray character.
   Highlights further on hover so the whole title row visibly invites a
   click. */
.kanban-chevron {
  color: var(--accent);
  font-size: 0.9rem;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(102, 113, 158, 0.16);
  transition: transform 0.15s ease, background 0.15s ease;
}

.kanban-chevron.is-expanded {
  transform: rotate(90deg);
}

.kanban-card-title-row:hover .kanban-chevron {
  background: rgba(102, 113, 158, 0.32);
}

.kanban-card-title {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink);
  /* Up to two lines, then "..." (LUV-46). One line cut most titles
     short in a phone-width column. line-clamp needs this -webkit-box
     display; every current browser supports it. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.kanban-card.is-expanded .kanban-card-title {
  -webkit-line-clamp: unset;
}

.kanban-card-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.kanban-move-btn {
  background: none;
  border: none;
  color: var(--accent);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 3px 5px;
  border-radius: 6px;
}

.kanban-move-btn:hover {
  background: rgba(102, 113, 158, 0.12);
}

.kanban-card-collapsed-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.kanban-card.is-expanded .kanban-card-collapsed-meta {
  display: none;
}

/* Separate class from .kanban-card-collapsed-meta on purpose - this
   pills row lives inside .kanban-card-body (already hidden/shown as a
   whole via is-expanded), so it must NOT also match the rule above, or
   it gets force-hidden even while the card is expanded. */
.kanban-card-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.kanban-card-body {
  display: none;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--surface-2);
}

.kanban-card.is-expanded .kanban-card-body {
  display: block;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.72rem;
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  font-weight: 600;
}
.pill svg {
  width: 11px;
  height: 11px;
  flex: none;
}

.pill-activity {
  background: var(--tint-soft);
  color: var(--accent);
  border: 1px solid var(--tint);
}

.pill-style {
  background: rgba(68, 89, 171, 0.14);
  color: var(--accent-2);
  border: 1px solid rgba(68, 89, 171, 0.3);
}

/* Small read-only status badges shown on the card's second line
   (moved off the title row in LUV-46) - urgent, needs-reservation, and reserved. Display only; the
   actual controls that CHANGE these values are the .toggle-pill /
   .badge-urgent-toggle buttons in the expanded card body below. */
.badge-flag {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
}

.badge-urgent {
  background: var(--danger);
  color: #2a0a0a;
}

.badge-reservation-needed {
  background: rgba(68, 89, 171, 0.18);
  color: var(--accent-2);
  border: 1px solid rgba(68, 89, 171, 0.35);
}

.badge-reserved {
  background: rgba(102, 113, 158, 0.18);
  color: var(--accent);
  border: 1px solid rgba(102, 113, 158, 0.35);
}

.urgency-note {
  color: var(--danger);
  font-size: 0.82rem;
  margin-top: 6px;
}

.kanban-card-region {
  color: var(--ink);
  font-size: 0.82rem;
  font-weight: 500;
}

/* Only rendered once an idea has left The Ideas column - see the
   comment above exactLocationLine in kanbanCardHtml() in app.js. */
.kanban-card-exact-location {
  color: var(--accent);
  font-size: 0.82rem;
  margin-top: 6px;
}

/* Hidden while the card is expanded, like the collapsed meta row above:
   the expanded body has its own editable address field, so showing
   both would repeat the address. */
.kanban-card.is-expanded .kanban-card-exact-location {
  display: none;
}

.kanban-card-desc {
  font-size: 0.88rem;
  line-height: 1.45;
  margin-top: 8px;
}

.kanban-card-link {
  display: inline-block;
  margin-top: 8px;
  color: var(--accent);
  font-size: 0.82rem;
  text-decoration: none;
}

/* The actual clickable controls for reservation/reserved/urgent state -
   only shown in the expanded card body. */
.kanban-card-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--surface-2);
}

.toggle-pill {
  background: var(--surface-2);
  color: var(--ink-soft);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.78rem;
  padding: 5px 12px;
  cursor: pointer;
  white-space: nowrap;
}

.toggle-pill.is-on {
  background: rgba(102, 113, 158, 0.18);
  color: var(--accent);
  border-color: rgba(102, 113, 158, 0.35);
}

/* Urgent's toggle button (in the card body) - not the read-only
   .badge-urgent shown up in the header/collapsed view. Disabled
   (grayed out) whenever the card doesn't need a reservation at all,
   since "urgent" only means something when there's a reservation to
   be urgent about. */
.badge-urgent-toggle {
  border: none;
  cursor: pointer;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 5px 10px;
  border-radius: 999px;
  white-space: nowrap;
  background: var(--border);
  color: var(--ink-soft);
}

.badge-urgent-toggle.is-urgent {
  background: var(--danger);
  color: #2a0a0a;
}

.badge-urgent-toggle:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Inline-editable fields for a card's core details (category, style,
   region, address, description, link) - see kanbanCardHtml() /
   handleUpdateIdeaField() in app.js. Same label-above-control shape as
   .confirmation-info-field below, which was the original precedent
   for editing a card in place rather than through a separate form. */
.idea-edit-fields {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.idea-edit-row {
  display: flex;
  gap: 10px;
}

.idea-edit-row .idea-edit-field {
  flex: 1;
}

.idea-edit-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.idea-edit-field input,
.idea-edit-field select,
.idea-edit-field textarea {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 7px 10px;
  color: var(--ink);
  font-size: 0.85rem;
  font-family: inherit;
}

.idea-edit-field textarea {
  min-height: 50px;
  resize: vertical;
}

.idea-edit-link-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.idea-edit-link-row input {
  flex: 1;
}

.idea-edit-link-row .kanban-card-link {
  margin-top: 0;
  white-space: nowrap;
}

/* Confirmation details - the "reference this while traveling" field.
   Editable right on the card (not just at add-idea time), since this
   is usually only known well after the idea itself was added. */
.confirmation-info-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.82rem;
  color: var(--ink-soft);
  margin-top: 10px;
}

.confirmation-info-field textarea {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px 10px;
  color: var(--ink);
  font-size: 0.85rem;
  font-family: inherit;
  min-height: 50px;
  resize: vertical;
}

/* A nudge, not a block - shown when something's marked Reserved but
   has no confirmation info yet. Doesn't stop you from marking it
   Reserved in the first place (see product-decisions.md). */
.confirmation-nudge {
  color: var(--accent-2);
  font-size: 0.78rem;
  margin-top: 6px;
}

/* A checkbox row inside a .form that reads left-to-right (checkbox then
   label) instead of the form's usual label-above-input stacked layout. */
.form label.form-checkbox-row {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}

.form-checkbox-row input[type="checkbox"] {
  width: 20px;
  height: 20px;
  accent-color: var(--accent);
  flex-shrink: 0;
}

/* Grays out a checkbox row or textarea while it's disabled - used in
   the add-idea form so Urgent/Already reserved/their notes fields
   visibly gray out together whenever Reservation needed is unchecked
   (see handleAddFormReservationToggle in app.js), instead of just
   silently not saving what you typed into them. */
.form-checkbox-row:has(input:disabled) {
  opacity: 0.4;
}

.form textarea:disabled {
  opacity: 0.4;
}

/* The "+ Add idea" pill at the top of the Ideas tab, replacing what
   used to be a form permanently sitting at the bottom of the page. */
.pill-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--accent);
  color: #04121f;
  border: none;
  border-radius: 999px;
  padding: 8px 16px;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  margin-bottom: 14px;
}

.pill-btn:active {
  opacity: 0.85;
}

/* Ideas tab filter bar: a slim single row of plain selects (no card
   box, no field labels), matching the kanban mockup's filter-bar
   styling rather than the app's usual boxed .card.form look. */
.idea-filter-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.idea-filter-bar select {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px 10px;
  color: var(--ink);
  font-size: 0.85rem;
  font-family: inherit;
}

.idea-filter-checkbox {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-soft);
  font-size: 0.85rem;
  cursor: pointer;
}

.idea-filter-checkbox input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
}

/* Small text-only button, for actions that shouldn't look as heavy as
   button.primary (e.g. "Clear filters") - reusable anywhere that fits. */
.link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-size: 0.85rem;
  text-decoration: underline;
  cursor: pointer;
}

/* ---------------------- Ideas board (map view) ---------------------- */
/* The "Map" half of the Board/Map toggle on the Ideas tab - see
   app.js's mapViewHtml() and product-decisions.md's "Map view" section.
   Reviewed first in mockup/map-table-mockup.html (retired once ported
   here). */

.ideas-toolbar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}

.ideas-toolbar-row .pill-btn {
  margin-bottom: 0;
}

.view-toggle {
  display: inline-flex;
  background: var(--surface-2);
  border-radius: 999px;
  padding: 3px;
  gap: 2px;
}

.view-toggle button {
  border: none;
  background: none;
  color: var(--ink-soft);
  font-size: 0.85rem;
  font-weight: 600;
  padding: 7px 16px;
  border-radius: 999px;
  cursor: pointer;
}

.view-toggle button.active {
  background: var(--accent);
  color: #04121f;
}

.map-view {
  display: flex;
  gap: 18px;
  align-items: flex-start;
}

.map-list-pane {
  width: 360px;
  flex-shrink: 0;
  max-height: 560px;
  overflow-y: auto;
  padding-right: 4px;
}

/* Dot-grid texture stands in for real map tiles until Leaflet is
   wired up - see the comment on mapViewHtml() in app.js. */
.map-pane {
  flex: 1;
  position: relative;
  min-height: 400px;
  border-radius: var(--radius);
  overflow: hidden;
  background:
    radial-gradient(circle, rgba(148, 163, 184, 0.14) 1px, transparent 1px) 0 0/22px 22px,
    var(--surface);
  border: 1px solid var(--surface-2);
  padding: 10px;
}

.map-legend {
  position: absolute;
  top: 10px;
  right: 12px;
  background: rgba(15, 23, 42, 0.75);
  border-radius: 10px;
  padding: 8px 10px;
  font-size: 0.72rem;
  color: var(--ink-soft);
  display: flex;
  flex-direction: column;
  gap: 5px;
  z-index: 1;
}

.map-legend-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.map-legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.map-empty-note {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-width: 70%;
  text-align: center;
  margin: 0;
}

.map-caption {
  position: absolute;
  bottom: 10px;
  left: 12px;
  font-size: 0.7rem;
  color: var(--ink-soft);
  background: rgba(15, 23, 42, 0.7);
  padding: 4px 8px;
  border-radius: 6px;
  z-index: 1;
}

/* Read-only card for a "plotted" idea in the map view's list pane -
   no hover/click/expand behavior yet, unlike .kanban-card, since
   there's no pin on the other end of it to sync with yet. */
.maplist-card {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 10px 12px;
  margin-bottom: 8px;
  border: 1px solid var(--border);
}

.maplist-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.maplist-card-title {
  font-weight: 600;
  font-size: 0.9rem;
}

.maplist-stage-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 4px;
}

.maplist-card-region {
  font-size: 0.78rem;
  color: var(--ink-soft);
  margin-top: 2px;
}

.maplist-card-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 7px;
}

/* Ideas with no confirmed location yet, listed separately rather than
   hidden - see mapUnplottedHtml() in app.js. */
.not-on-map {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px dashed var(--surface-2);
}

.not-on-map h4 {
  font-size: 0.78rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin: 0 0 8px;
}

.not-on-map-card {
  background: var(--surface);
  border-radius: 10px;
  padding: 8px 10px;
  margin-bottom: 6px;
  font-size: 0.82rem;
}

.not-on-map-reason {
  color: var(--accent-2);
  font-size: 0.75rem;
  margin-top: 2px;
}

.not-on-map-reason.is-failed {
  color: var(--danger);
}

/* ---- TEMPORARY: demo pin preview -----------------------------------
   Everything below is scaffolding for evaluating the pin/hover/click
   interaction against fake positions before real geocoding exists.
   Delete this whole block (and its counterparts in app.js) once
   Phase 2 wires up real geocode()/renderMap() positions. See
   mapDemoPinsEnabled in app.js and product-decisions.md's "Map view"
   section. ---------------------------------------------------------- */

.map-view-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}

.demo-pins-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.demo-pins-toggle input {
  cursor: pointer;
}

.demo-pins-banner {
  font-size: 0.75rem;
  color: var(--accent-2);
  background: rgba(68, 89, 171, 0.12);
  padding: 3px 9px;
  border-radius: 6px;
}

.demo-tag {
  font-size: 0.6rem;
  color: var(--ink-soft);
  background: var(--surface-2);
  padding: 1px 5px;
  border-radius: 4px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  vertical-align: middle;
}

/* Interactive treatment only applies to demo-plotted cards - real
   plotted cards (mapPlottedCardsHtml) stay read-only until Phase 2
   gives them real pin positions to sync with too. */
.maplist-card.is-demo {
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.maplist-card.is-demo:hover,
.maplist-card.is-demo.is-active {
  border-color: var(--accent);
  background: var(--surface-2);
}

.map-pin {
  position: absolute;
  transform: translate(-50%, -100%);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: transform 0.12s ease;
  z-index: 2;
}

.map-pin-dot {
  width: 16px;
  height: 16px;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  border: 2px solid var(--bg);
  box-shadow: 0 1px 4px rgba(49, 47, 59, 0.18);
}

.map-pin.is-demo .map-pin-dot {
  outline: 1px dashed var(--ink-soft);
  outline-offset: 2px;
}

.map-pin.is-active {
  transform: translate(-50%, -100%) scale(1.35);
  z-index: 5;
}

.map-pin-label {
  display: none;
  background: var(--bg);
  color: var(--ink);
  font-size: 0.72rem;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 6px;
  white-space: nowrap;
  margin-bottom: 4px;
  border: 1px solid var(--surface-2);
}

.map-pin.is-active .map-pin-label,
.map-pin:hover .map-pin-label {
  display: block;
}
/* ---- END TEMPORARY: demo pin preview -------------------------------- */

/* --------------------------- Tab bar ---------------------------- */

.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  background: var(--surface);
  border-top: 1px solid var(--surface-2);
  padding-bottom: env(safe-area-inset-bottom);
  z-index: 10;
}

.tab-btn {
  flex: 1;
  background: none;
  border: none;
  color: var(--ink-soft);
  padding: 12px 4px;
  font-size: 0.8rem;
  cursor: pointer;
}

.tab-btn.active {
  color: var(--accent);
  font-weight: 600;
}


/* ============================================================================
   Home screen (bento) - built 2026-09-05
   ============================================================================ */
/* A state-aware hero banner (the only part that knows whether a trip is
   active) sits above a tile grid that never changes shape regardless of
   trip state - so nothing ever looks "broken" when there's no active
   trip, only the banner above it changes. Reviewed first as
   mockup/home-mockup.html (now retired) - see product-decisions.md for
   the full design conversation. Tile colors below are placeholder,
   reused from this file's existing --accent/--accent-2/--stage-*
   tokens rather than new ones - not a design-language decision, see
   hard-to-change-log.md. */

.hero-banner {
  background: linear-gradient(135deg, var(--surface), var(--surface-2));
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: 18px 20px;
  margin-bottom: 16px;
  cursor: pointer;
}
.hero-banner .eyebrow {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
  font-weight: 700;
  margin-bottom: 4px;
}
.hero-banner .trip-name {
  font-size: 1.3rem;
  font-weight: 700;
}
.hero-banner.empty {
  border-style: dashed;
  border-color: var(--ink-soft);
  text-align: center;
  cursor: default;
}
.hero-banner.empty .eyebrow {
  color: var(--ink-soft);
}

.bento-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 130px);
  grid-template-areas:
    "trips trips new new"
    "trips trips dash settings";
  gap: 12px;
}
@media (max-width: 640px) {
  .bento-grid {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 150px 90px 90px;
    grid-template-areas:
      "trips trips"
      "new new"
      "dash settings";
  }
}
.tile {
  border-radius: var(--radius);
  padding: 16px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  cursor: pointer;
  color: #04121f;
}
.tile .tile-icon {
  width: 26px;
  height: 26px;
}
.tile .tile-label {
  font-weight: 700;
  font-size: 1.02rem;
  margin-top: 10px;
}
.tile .tile-sub {
  font-size: 0.78rem;
  opacity: 0.85;
  margin-top: 2px;
}
.tile-trips { grid-area: trips; background: var(--accent); }
.tile-new { grid-area: new; background: var(--accent-2); }
.tile-dash { grid-area: dash; background: var(--stage-itinerary); }
.tile-settings { grid-area: settings; background: var(--stage-ideas); }
.tile.disabled {
  opacity: 0.45;
  cursor: default;
}
.coming-soon-badge {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: rgba(4, 18, 31, 0.35);
  padding: 2px 7px;
  border-radius: 999px;
  display: inline-block;
  margin-top: 6px;
}

/* --------------------------- Hamburger menu -------------------------- */
/* The single navigation trigger shown on every screen except Home
   (whose bento tiles already are the navigation). Opens a dropdown
   that jumps straight to any section - see product-decisions.md. */

.icon-btn {
  position: relative;
}
.menu-dropdown {
  position: absolute;
  top: 38px;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--surface-2);
  border-radius: 12px;
  padding: 6px;
  min-width: 190px;
  box-shadow: 0 8px 24px rgba(49, 47, 59, 0.18);
  z-index: 10;
  text-align: left;
}
.menu-dropdown .menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 0.9rem;
  cursor: pointer;
  color: var(--ink);
}
.menu-dropdown .menu-item:hover {
  background: var(--surface-2);
}
.menu-dropdown .menu-item.muted {
  cursor: default;
  color: var(--ink-soft);
}
.menu-dropdown .menu-item.muted:hover {
  background: none;
}
.menu-overlay {
  position: fixed;
  inset: 0;
  z-index: 9;
}

/* Account section at the bottom of the menu (LUV-40): who's signed in
   on this device, and Sign out. */
.menu-divider {
  height: 1px;
  background: var(--surface-2);
  margin: 4px 6px;
}
.menu-dropdown .menu-item.menu-account {
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  line-height: 1.3;
}
.menu-dropdown .menu-item.menu-account small {
  font-size: 0.78rem;
}

/* ------------------------- Sharing a trip (LUV-42) ------------------------ */
/* The Share button under a trip's name and the panel it opens - see
   sharePanelHtml() in app.js and mockup/share-trip-mockup.html. The
   panel slides up from the bottom, phone-sheet style, over a dimmed
   page; z-index 20 keeps it above the bottom tab bar (10). */
.share-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  font: 600 0.78rem var(--font-body);
  cursor: pointer;
  width: fit-content;
}
.share-chip svg {
  width: 14px;
  height: 14px;
}
.share-overlay {
  position: fixed;
  inset: 0;
  background: rgba(49, 47, 59, 0.28);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 20;
}
.share-panel {
  width: 100%;
  max-width: 520px;
  background: var(--bg);
  border-radius: 22px 22px 0 0;
  padding: 18px 18px calc(28px + env(safe-area-inset-bottom));
  max-height: 88vh;
  overflow-y: auto;
}
.share-panel-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.share-panel-head h2 {
  margin: 0;
  font-size: 1.05rem;
}
.share-close {
  background: none;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--ink-soft);
  cursor: pointer;
  padding: 0 2px;
}
.share-intro {
  color: var(--ink-soft);
  font-size: 0.84rem;
  line-height: 1.5;
  margin: 6px 0 14px;
}
.member-list {
  background: var(--surface);
  border-radius: var(--radius);
  padding: 4px 14px;
  margin-bottom: 14px;
}
.member-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 0;
  font-size: 0.9rem;
}
.member-row + .member-row {
  border-top: 1px solid var(--surface-2);
}
.member-email {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.member-you {
  color: var(--ink-soft);
  font-size: 0.78rem;
}
.member-remove {
  background: none;
  border: none;
  color: var(--danger);
  font: 600 0.82rem var(--font-body);
  cursor: pointer;
  padding: 0;
  flex: none;
}
.share-add-row {
  display: flex;
  gap: 8px;
}
.share-add-row input {
  flex: 1;
  min-width: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  font: 0.95rem var(--font-body);
  color: var(--ink);
}
.share-add-row button {
  flex: none;
  width: auto;
  margin: 0;
  padding: 10px 16px;
}
.share-msg {
  font-size: 0.82rem;
  line-height: 1.5;
  margin-top: 8px;
  color: var(--danger);
}
.share-hint {
  font-size: 0.78rem;
  color: var(--ink-soft);
  line-height: 1.5;
  margin-top: 10px;
}

/* --------------------- Sync status and account (LUV-43) ------------------- */
/* The status label, Home's account button, and the "Sync and account"
   panel - see syncStatusHtml() and accountPanelHtml() in app.js, and
   mockup/sync-status-mockup.html. The panel reuses the Share panel's
   bottom-sheet styles above. */
.sync-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: 600 0.74rem var(--font-body);
  color: var(--ink-soft);
  white-space: nowrap;
}
.sync-status svg {
  width: 13px;
  height: 13px;
  flex: none;
}
.sync-status.waiting {
  color: var(--sync-waiting);
}

/* Home: who's signed in, with the status under it, top right. */
.account-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 3px;
  background: none;
  border: none;
  padding: 4px 0 0;
  cursor: pointer;
  min-width: 0;
  max-width: 62%;
  text-align: right;
}
/* Long emails lose the end of the part before the @, never the domain. */
.account-email {
  display: flex;
  max-width: 100%;
  font: 600 0.78rem var(--font-body);
  color: var(--ink);
  white-space: nowrap;
}
.account-email .email-local {
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.account-email .email-domain {
  flex: none;
}

/* Sub-pages: the status sits under the title, beside Share on a trip. */
.header-meta-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin-top: 6px;
}
.header-meta-row .share-chip {
  margin-top: 0;
}
.sync-btn {
  background: none;
  border: none;
  padding: 4px 0;
  cursor: pointer;
}

/* Home banner when this account has no trips: names the account, so a
   sign-in on the wrong Google account is obvious. */
.banner-account {
  margin: 10px 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
.banner-account b {
  color: var(--ink);
  font-weight: 700;
  overflow-wrap: anywhere;
}
.banner-link {
  display: inline-block;
  margin-top: 6px;
  background: none;
  border: none;
  padding: 0;
  font: 700 0.84rem var(--font-body);
  color: var(--accent-vivid);
  cursor: pointer;
}

/* The panel's contents. */
.account-status-card {
  display: flex;
  gap: 10px;
  background: var(--surface);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin: 12px 0;
}
.account-status-card svg {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 1px;
  color: var(--ink-soft);
}
.account-status-card .status-title {
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--ink);
}
.account-status-card.waiting svg,
.account-status-card.waiting .status-title {
  color: var(--sync-waiting);
}
.account-status-card p {
  margin: 3px 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-soft);
}
.account-label {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-top: 4px;
}
.account-panel-email {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
  margin: 3px 0 4px;
  overflow-wrap: anywhere;
}
.account-signout {
  width: auto;
  margin-top: 14px;
  background: none;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 16px;
  font: 700 0.88rem var(--font-body);
  color: var(--danger);
  cursor: pointer;
}

/* ------------------------- Sign-in screen (LUV-40) ------------------------ */
/* Shown only when nobody is signed in on this device - see
   renderSignInScreen() in app.js and mockup/sign-in-mockup.html. One
   centered column: the lockup at a larger size, a tagline, Google's
   button, then either a help line or a message (offline / didn't
   finish). */
.signin-screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 32px 28px;
  text-align: center;
}
.signin-lockup {
  display: flex;
  align-items: center;
  font-size: 2.1rem;
  margin: 0 0 10px;
}
.signin-lockup .word-set {
  font-family: var(--font-body);
  font-weight: 800;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.signin-lockup .word-out {
  font-family: "Yeseva One", serif;
  font-weight: 400;
  color: var(--accent-vivid);
}
.signin-lockup svg {
  margin: 0 5px;
  width: 82px;
  height: 32px;
}
.signin-tagline {
  color: var(--ink-soft);
  font-size: 0.95rem;
  margin: 0 0 36px;
}
/* White button with Google's "G", following Google's own sign-in
   button guidance (light theme). */
.google-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  max-width: 280px;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 16px;
  font: 600 1rem var(--font-body);
  cursor: pointer;
  box-shadow: var(--shadow-card);
}
.google-btn:disabled {
  opacity: 0.5;
  cursor: default;
  box-shadow: none;
}
.google-btn svg {
  width: 18px;
  height: 18px;
  flex: none;
}
.signin-help {
  color: var(--ink-soft);
  font-size: 0.82rem;
  line-height: 1.5;
  margin-top: 18px;
  max-width: 280px;
}
.signin-msg {
  font-size: 0.85rem;
  line-height: 1.5;
  margin-top: 16px;
  max-width: 280px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--tint-soft);
  color: var(--ink);
}

/* -------------------- Building-view calendar (LUV-6) -------------------- */
/* Phase 3, Step 2: grid skeleton only. Structure/spacing only - colors
   reuse existing tokens (per style-reference-provisional.md, real palette
   work waits until data layer + functionality are finalized). Desktop-first,
   like the rest of Ideation/Planning/Building - not yet tested at mobile
   width (see the same open item already logged for the kanban board). */

.calendar-layout {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

.calendar-sidebar {
  width: 240px;
  flex-shrink: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  position: sticky;
  top: 16px;
}
.calendar-sidebar.drag-over {
  outline: 2px dashed var(--accent);
  outline-offset: -4px;
}
.calendar-sidebar h2 {
  font-size: 1rem;
  margin: 0 0 6px;
}
.calendar-sidebar-card {
  background: var(--surface-2);
  border-radius: 10px;
  padding: 10px 12px;
  margin-top: 10px;
  cursor: grab;
}
.calendar-sidebar-card[draggable="true"]:active {
  cursor: grabbing;
}
.calendar-sidebar-card.dragging {
  opacity: 0.35;
}

.calendar-grid-wrap {
  flex: 1;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px;
  overflow-x: auto;
}

.cal-week-block {
  padding-bottom: 12px;
  margin-bottom: 12px;
}
.cal-week-block:not(:last-child) {
  border-bottom: 1px solid var(--border);
}
.cal-week-block:last-child {
  margin-bottom: 0;
  padding-bottom: 0;
}

.cal-grid {
  display: grid;
  grid-template-columns: 90px repeat(7, minmax(110px, 1fr));
  gap: 6px;
}

.cal-corner {
  /* empty top-left cell above the row labels */
}

.cal-day-header {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--ink);
  text-align: center;
  padding: 6px 4px;
}
.cal-day-header .dow {
  display: block;
  font-weight: 500;
  color: var(--ink-soft);
  font-size: 0.72rem;
}
.cal-day-header.outside-trip {
  color: var(--ink-faint);
}

.cal-row-label {
  font-size: 0.78rem;
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  padding: 4px;
}

.cal-cell {
  background: var(--surface-2);
  border-radius: 8px;
  min-height: 48px;
  padding: 4px;
}
.cal-cell.outside-trip {
  background: none;
}
.cal-cell.drag-over {
  outline: 2px dashed var(--accent);
  outline-offset: -2px;
}

/* Placed items (Step 3) are separate grid children overlaid on top of
   the backdrop .cal-cell divs above, not nested inside them - see the
   comment on calendarPlacedItemsHtml() in app.js for why. */
.cal-placed-group {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 2px;
  min-width: 0;
  min-height: 0;
}

.cal-placed-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 6px;
  font-size: 0.78rem;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  min-height: 40px; /* room for icon+title row plus a time row without
                        relying on nested flex/grid auto-sizing to work
                        it out - confirmed 2026-09-11 after that math
                        proved unreliable in testing, see
                        product-decisions.md */
  gap: 2px;
  flex: 1;
  min-width: 0;
  cursor: grab;
  transition: filter 0.1s;
}
.cal-placed-card:hover {
  filter: brightness(0.97); /* click-to-edit affordance, same idea as
                                the confirmed mockup's hover treatment -
                                darker rather than brighter since this
                                palette is light, not dark */
}
.cal-placed-card[draggable="true"]:active {
  cursor: grabbing;
}
.cal-placed-card.dragging {
  opacity: 0.35;
}
.cal-placed-card .placed-top-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-width: 0;
}
.cal-placed-card .placed-label {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  flex: 1;
}
.cal-placed-card .placed-label svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}
.cal-placed-card .placed-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.cal-placed-card .placed-time-row {
  font-size: 0.72rem;
  color: var(--ink-soft);
  padding-left: 18px; /* lines up under the title text, after the icon */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  box-sizing: border-box;
}
.cal-placed-card.allday-bar {
  background: var(--tint);
  border-color: var(--accent);
}
.allday-continues {
  flex-shrink: 0;
  color: var(--ink-soft);
}

.placed-controls {
  display: flex;
  gap: 2px;
  flex-shrink: 0;
}
.placed-controls button {
  width: 18px;
  height: 18px;
  line-height: 1;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface-2);
  color: var(--ink);
  font-size: 0.8rem;
  padding: 0;
  cursor: pointer;
}
.placed-controls button:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.placed-controls .remove-btn {
  color: var(--danger);
  border-color: var(--danger);
}

/* Click-to-edit popover for a placed calendar card. Position (top/
   left) is set inline via JS (positionCalendarPopover() in app.js) -
   this block only owns appearance, sizing, and layout of what's
   inside. Reuses .idea-edit-fields/.idea-edit-row/.idea-edit-field/
   .confirmation-info-field for the fields themselves, same as the
   kanban card's expanded body, so an input looks identical wherever
   it's edited. */
.cal-edit-popover {
  position: fixed;
  z-index: 40;
  width: 280px;
  max-width: calc(100vw - 24px);
  max-height: calc(100vh - 24px); /* without this, a tall popover (e.g.
     Lodging's 4 date/time fields) can render past the bottom of the
     viewport with no way to see the rest - position:fixed doesn't
     respond to page scroll the way position:absolute would. Capping
     height and scrolling internally instead means the whole popover
     is always reachable regardless of window size. */
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 14px;
}
.cal-edit-popover-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}
.cal-edit-popover-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--ink);
}
.cal-edit-popover-title svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}
.cal-edit-popover-close {
  background: none;
  border: none;
  color: var(--ink-soft);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
  flex-shrink: 0;
}
.cal-edit-popover-close:hover {
  color: var(--ink);
}

/* Native date/time inputs have a browser-enforced minimum content
   width (for their day/month/year/AM-PM segments) that doesn't shrink
   with flex the way a text input does. .idea-edit-row's side-by-side
   layout works fine at the kanban card's width but overflows this
   popover's narrower 280px - so within the popover specifically,
   every row stacks to one field per line instead. Scoped to
   .cal-edit-popover only; the kanban card's own inline-edit body is
   untouched. */
.cal-edit-popover .idea-edit-row {
  flex-direction: column;
  gap: 10px;
}

/* Lodging bars (LUV-7 Step 2) - fully auto-scheduled, never manually
   dragged (the Lodging row has been locked in as non-interactive
   since Phase 3). Reuses .allday-bar's tinted treatment since it's
   visually the same "multi-day bar" idea, but overrides the cursor -
   "grab" would be misleading on something that can't actually be
   dragged. */
.cal-placed-card.lodging-bar {
  cursor: pointer;
}

/* A cross-day flight/transport's derived arrival echo - never a real
   placement (see product-decisions.md's "Phase 4, Step 2"), so it
   reads visually distinct from a real placed card: dashed border,
   muted, no drag affordance. Still clickable (pointer cursor) since
   it opens the same idea's edit popover. */
.cal-placed-card.cal-arrival-echo {
  cursor: pointer;
  border-style: dashed;
  background: var(--surface-2);
  color: var(--ink-soft);
}
.cal-placed-card.cal-arrival-echo .placed-title {
  font-style: italic;
}

/* Collision flag (LUV-7 Step 3) - ambient warning when two DIFFERENT
   ideas share the exact same footprint (see the multi-item-stacking
   decision - this is never blocked or evicted, just flagged in case
   it's an accidental double-booking rather than intentional). Scoped
   to regular slots only this pass - see product-decisions.md's
   "Phase 4, Step 3" for why All Day/Lodging aren't included yet
   (LUV-26). Reuses --danger, same token the reservation-cancellation
   confirm and delete buttons use for "pay attention here." */
.cal-placed-card.has-conflict {
  border-color: var(--danger);
}
.conflict-badge {
  color: var(--danger);
  margin-left: 2px;
  flex-shrink: 0;
}
