Hello from MCP server

List Files | Just Commands | Repo | Logs

← back |
<template>
  <BaseLayout title="Technician">
    <div class="edit-job-container">
      <div v-if="loading" class="loading-message">Loading job data...</div>

      <div v-else-if="!currentJob" class="no-job-message">Job not found</div>

      <div v-else>
        <h1 class="page-title">Edit Job</h1>

        <!-- Job Name -->
        <h2 class="job-name">
          {{ editedJobName || currentJob?.problem?.name || "Untitled Job" }}
        </h2>

        <!-- Action Buttons -->
        <div class="action-buttons">
          <ion-button fill="solid" color="primary" @click="handleConfirmJob">
            Confirm Job
          </ion-button>
          <ion-button fill="solid" color="danger" @click="handleCancel">
            Cancel
          </ion-button>
        </div>

        <!-- Data Table -->
        <ion-grid v-if="menuData" class="data-table">
          <!-- Header Row -->
          <ion-row class="table-header">
            <ion-col size="3">Field</ion-col>
            <ion-col size="6">Value</ion-col>
            <ion-col size="3">Default</ion-col>
          </ion-row>

          <!-- Job Name Row -->
          <ion-row class="table-row editable-row" @click="focusJobNameInput">
            <ion-col size="3">
              <div class="cell-label">Job Name</div>
            </ion-col>
            <ion-col size="6">
              <div class="cell-input">
                <ion-icon :icon="pencilOutline" class="cell-edit-icon"></ion-icon>
                <ion-input
                  ref="jobNameInputRef"
                  v-model="editedJobName"
                  placeholder="Enter job name"
                  class="inline-input"
                ></ion-input>
              </div>
            </ion-col>
            <ion-col size="3">
              <div class="cell-default">{{ currentJob?.problem?.name || '—' }}</div>
            </ion-col>
          </ion-row>

          <!-- Menu Title Row -->
          <ion-row class="table-row editable-row" @click="focusMenuTitleInput">
            <ion-col size="3">
              <div class="cell-label">Menu Title</div>
            </ion-col>
            <ion-col size="6">
              <div class="cell-input">
                <ion-icon :icon="pencilOutline" class="cell-edit-icon"></ion-icon>
                <ion-input
                  ref="menuTitleInputRef"
                  v-model="editedMenuTitle"
                  placeholder="Enter menu title"
                  class="inline-input"
                ></ion-input>
              </div>
            </ion-col>
            <ion-col size="3">
              <div class="cell-default">{{ menuData.name }}</div>
            </ion-col>
          </ion-row>

          <!-- Tiers -->
          <template v-if="menuData.tiers && menuData.tiers.length > 0">
            <template v-for="tier in menuData.tiers" :key="tier.id">
              <!-- Tier Header Row -->
              <ion-row class="table-row tier-row" :class="{ 'tier-removing': removingTiers.has(tier.id) }">
                <ion-col size="3">
                  <div class="cell-label tier-label">{{ tier.name }}</div>
                </ion-col>
                <ion-col size="6">
                  <div class="cell-tier-info">
                    <span class="tier-title">{{ tier.tier?.name || tier.name }}</span>
                    <span class="tier-ref">{{ tier.offer?.refId || tier.refId }}</span>
                  </div>
                </ion-col>
                <ion-col size="3">
                  <ion-button
                    size="small"
                    color="danger"
                    fill="clear"
                    @click="removeTier(tier.id)"
                    :disabled="removingTiers.has(tier.id)"
                  >
                    <ion-icon :icon="trashOutline" slot="icon-only"></ion-icon>
                  </ion-button>
                </ion-col>
              </ion-row>

              <!-- Offer Title Row -->
              <ion-row
                class="table-row editable-row sub-row"
                :class="{ 'tier-removing': removingTiers.has(tier.id) }"
              >
                <ion-col size="3">
                  <div class="cell-label">Offer Title</div>
                </ion-col>
                <ion-col size="6">
                  <div class="cell-input">
                    <ion-icon :icon="pencilOutline" class="cell-edit-icon"></ion-icon>
                    <ion-input
                      v-model="editedTiers[tier.id].offerTitle"
                      placeholder="Enter offer title"
                      class="inline-input"
                    ></ion-input>
                  </div>
                </ion-col>
                <ion-col size="3">
                  <div class="cell-default">{{ getTierTitleItem(tier) || '—' }}</div>
                </ion-col>
              </ion-row>

              <!-- Offer Details Row -->
              <ion-row
                class="table-row editable-row sub-row"
                :class="{ 'tier-removing': removingTiers.has(tier.id) }"
                @click="openDetailsModal(tier)"
              >
                <ion-col size="3">
                  <div class="cell-label">Details</div>
                </ion-col>
                <ion-col size="9">
                  <div class="cell-details">
                    <div class="cell-input">
                      <ion-icon :icon="pencilOutline" class="cell-edit-icon"></ion-icon>
                      <div class="details-preview">
                        <template v-if="getEditedContentItems(tier.id).length > 0">
                          <div
                            v-for="item in getEditedContentItems(tier.id).slice(0, 3)"
                            :key="item.id"
                            class="detail-item"
                          >
                            • {{ item.content }}
                          </div>
                          <div v-if="getEditedContentItems(tier.id).length > 3" class="detail-item more-items">
                            ... and {{ getEditedContentItems(tier.id).length - 3 }} more
                          </div>
                        </template>
                        <div v-else class="no-content">No content items</div>
                      </div>
                    </div>
                  </div>
                </ion-col>
              </ion-row>
            </template>
          </template>

          <ion-row v-else class="table-row">
            <ion-col size="12">
              <div class="no-content">No tiers available</div>
            </ion-col>
          </ion-row>
        </ion-grid>

        <div v-else-if="!loading" class="empty-state">
          No menu data available
        </div>
      </div>
    </div>

    <!-- Details Edit Modal -->
    <ion-modal :is-open="showDetailsModal" @didDismiss="closeDetailsModal">
      <ion-header>
        <ion-toolbar>
          <ion-title>Edit Details</ion-title>
          <ion-buttons slot="end">
            <ion-button @click="closeDetailsModal">Done</ion-button>
          </ion-buttons>
        </ion-toolbar>
      </ion-header>
      <ion-content class="ion-padding">
        <div class="details-modal-content">
          <div class="modal-tier-name">{{ editingTier?.tier?.name || editingTier?.name }}</div>

          <!-- In This Tier Section -->
          <div class="bullets-section">
            <div class="section-label">In This Tier</div>
            <div v-if="tierBullets.length === 0" class="empty-section">
              No bullets assigned to this tier
            </div>
            <div v-else class="content-items-list">
              <div
                v-for="item in tierBullets"
                :key="item.id"
                class="content-item-row"
              >
                <template v-if="editingBulletId === item.id">
                  <ion-input
                    v-model="editingBulletContent"
                    placeholder="Enter detail..."
                    class="content-item-input"
                    @keyup.enter="saveEditBullet"
                    @blur="saveEditBullet"
                  ></ion-input>
                  <ion-button fill="clear" color="success" size="small" @click="saveEditBullet">
                    <ion-icon :icon="checkmarkOutline" slot="icon-only"></ion-icon>
                  </ion-button>
                </template>
                <template v-else>
                  <span class="bullet-content" @click="startEditBullet(item)">• {{ item.content }}</span>
                  <div class="bullet-actions">
                    <ion-button fill="clear" color="primary" size="small" @click="startEditBullet(item)" title="Edit">
                      <ion-icon :icon="createOutline" slot="icon-only"></ion-icon>
                    </ion-button>
                    <ion-button fill="clear" color="danger" size="small" @click="handleRemoveFromTier(item.id)" title="Remove from tier">
                      <ion-icon :icon="removeCircleOutline" slot="icon-only"></ion-icon>
                    </ion-button>
                    <ion-button fill="clear" color="danger" size="small" @click="handleDeleteBullet(item.id)" title="Delete from all tiers">
                      <ion-icon :icon="trashOutline" slot="icon-only"></ion-icon>
                    </ion-button>
                  </div>
                </template>
              </div>
            </div>
          </div>

          <!-- Available Bullets Section -->
          <div v-if="availableBullets.length > 0" class="bullets-section">
            <div class="section-label">Available (not in this tier)</div>
            <div class="content-items-list available-list">
              <div
                v-for="item in availableBullets"
                :key="item.id"
                class="content-item-row available-item"
              >
                <span class="bullet-content">• {{ item.content }}</span>
                <ion-button fill="clear" color="success" size="small" @click="handleAssignToTier(item.id)" title="Add to tier">
                  <ion-icon :icon="addCircleOutline" slot="icon-only"></ion-icon>
                </ion-button>
              </div>
            </div>
          </div>

          <!-- Add New Bullet Section -->
          <div class="bullets-section add-section">
            <div class="section-label">Add New Bullet</div>
            <div class="add-bullet-row">
              <ion-input
                v-model="newBulletContent"
                placeholder="Enter new bullet point..."
                class="content-item-input"
                @keyup.enter="handleAddBullet"
              ></ion-input>
              <ion-button
                fill="solid"
                color="primary"
                size="small"
                @click="handleAddBullet"
                :disabled="!newBulletContent.trim()"
              >
                <ion-icon :icon="addOutline" slot="icon-only"></ion-icon>
              </ion-button>
            </div>
          </div>
        </div>
      </ion-content>
    </ion-modal>
  </BaseLayout>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, reactive } from "vue";
import BaseLayout from "@/components/BaseLayout.vue";
import {
  IonIcon,
  IonButton,
  IonInput,
  IonGrid,
  IonRow,
  IonCol,
  IonModal,
  IonHeader,
  IonToolbar,
  IonTitle,
  IonButtons,
  IonContent,
  toastController,
} from "@ionic/vue";
import {
  trashOutline,
  addOutline,
  checkmarkOutline,
  createOutline,
  removeCircleOutline,
  addCircleOutline,
} from "ionicons/icons";
import { mdPencil as pencilOutline } from "@/icons/customIcons";
import { useRoute, useRouter } from "vue-router";
import { useTnfrStore, type JobRecord } from "@/stores/tnfr";

const route = useRoute();
const router = useRouter();
const tnfrStore = useTnfrStore();

const currentJob = ref<JobRecord | null>(null);
const loading = ref(true);
const menuData = ref<any>(null);

// Edited values
const editedMenuTitle = ref("");
const editedJobName = ref("");
const editedTiers = reactive<
  Record<string, { offerTitle: string; offerDetails: string }>
>({});
const jobNameInputRef = ref<InstanceType<typeof IonInput> | null>(null);
const menuTitleInputRef = ref<InstanceType<typeof IonInput> | null>(null);

// Details modal state
const showDetailsModal = ref(false);
const editingTier = ref<any>(null);
const newBulletContent = ref('');
const editingBulletId = ref<string | null>(null);
const editingBulletContent = ref('');

const focusJobNameInput = () => {
  jobNameInputRef.value?.$el?.setFocus();
};

const focusMenuTitleInput = () => {
  menuTitleInputRef.value?.$el?.setFocus();
};

const getTierTitleItem = (tier: any): string | null => {
  const titleItem = tier.contentItems?.find((item: any) =>
    item.refId?.includes("_title"),
  );
  return titleItem?.content || null;
};

const getContentItemsText = (tier: any): string => {
  // Priority: use menuCopy if available (same as MenuTemplateDev)
  if (tier.menuCopy && tier.menuCopy.length > 0) {
    const allItems: string[] = [];
    tier.menuCopy.forEach((copy: any) => {
      if (copy.contentItems && copy.contentItems.length > 0) {
        copy.contentItems.forEach((item: any) => {
          allItems.push(item.content);
        });
      }
    });
    return allItems.join("\n");
  }

  // Fallback: use contentItems directly
  if (!tier.contentItems || tier.contentItems.length === 0) {
    return "";
  }
  // Filter out title items (same logic as menu template)
  return tier.contentItems
    .filter((item: any) => !item.refId?.includes("_title"))
    .map((item: any) => item.content)
    .join("\n");
};

// Get content items for a tier (from edited state or original)
const getContentItemsForTier = (tier: any): Array<{ id: string; content: string }> => {
  const items: Array<{ id: string; content: string }> = [];

  if (tier.menuCopy && tier.menuCopy.length > 0) {
    tier.menuCopy.forEach((copy: any) => {
      if (copy.contentItems && copy.contentItems.length > 0) {
        copy.contentItems.forEach((item: any) => {
          items.push({ id: item.id, content: item.content });
        });
      }
    });
  } else if (tier.contentItems && tier.contentItems.length > 0) {
    tier.contentItems
      .filter((item: any) => !item.refId?.includes("_title"))
      .forEach((item: any) => {
        items.push({ id: item.id, content: item.content });
      });
  }

  return items;
};

// Get edited content items using tnfrStore's tier bullets
const getEditedContentItems = (tierId: string): Array<{ id: string; content: string }> => {
  if (!currentJob.value) return [];

  // Use tnfrStore's getTierBullets which reflects all edits
  const bullets = tnfrStore.getTierBullets(currentJob.value.id, tierId);
  if (bullets.length > 0) {
    return bullets;
  }

  // Fall back to original tier content if no bullets in store yet
  const tier = menuData.value?.tiers?.find((t: any) => t.id === tierId);
  if (tier) {
    return getContentItemsForTier(tier);
  }
  return [];
};

// Computed: bullets in this tier
const tierBullets = computed(() => {
  if (!currentJob.value || !editingTier.value) return [];
  return tnfrStore.getTierBullets(currentJob.value.id, editingTier.value.id);
});

// Computed: bullets available but not in this tier
const availableBullets = computed(() => {
  if (!currentJob.value || !editingTier.value) return [];
  const allBullets = tnfrStore.getMenuBullets(currentJob.value.id);
  const tierBulletIds = new Set(tierBullets.value.map(b => b.id));
  return allBullets.filter(b => !tierBulletIds.has(b.id));
});

// Open details modal for a tier
const openDetailsModal = (tier: any) => {
  editingTier.value = tier;
  newBulletContent.value = '';
  editingBulletId.value = null;
  editingBulletContent.value = '';
  showDetailsModal.value = true;
};

// Close details modal
const closeDetailsModal = () => {
  showDetailsModal.value = false;
  editingTier.value = null;
  editingBulletId.value = null;
};

// Start editing a bullet
const startEditBullet = (item: { id: string; content: string }) => {
  editingBulletId.value = item.id;
  editingBulletContent.value = item.content;
};

// Save edited bullet
const saveEditBullet = async () => {
  if (!currentJob.value || !editingBulletId.value) return;

  if (editingBulletContent.value.trim()) {
    await tnfrStore.editMenuBullet(currentJob.value.id, editingBulletId.value, editingBulletContent.value.trim());
    const toast = await toastController.create({
      message: 'Bullet updated',
      duration: 1500,
      color: 'success',
      position: 'bottom',
    });
    await toast.present();
  }

  editingBulletId.value = null;
  editingBulletContent.value = '';
};

// Add new bullet
const handleAddBullet = async () => {
  if (!currentJob.value || !newBulletContent.value.trim()) return;

  await tnfrStore.addMenuBullet(currentJob.value.id, newBulletContent.value.trim());
  newBulletContent.value = '';

  const toast = await toastController.create({
    message: 'Bullet added to all tiers',
    duration: 1500,
    color: 'success',
    position: 'bottom',
  });
  await toast.present();
};

// Remove bullet from this tier only
const handleRemoveFromTier = async (bulletId: string) => {
  if (!currentJob.value || !editingTier.value) return;

  await tnfrStore.removeBulletFromTier(currentJob.value.id, editingTier.value.id, bulletId);

  const toast = await toastController.create({
    message: 'Removed from tier',
    duration: 1500,
    color: 'warning',
    position: 'bottom',
  });
  await toast.present();
};

// Assign bullet to this tier
const handleAssignToTier = async (bulletId: string) => {
  if (!currentJob.value || !editingTier.value) return;

  await tnfrStore.assignMenuBulletToTier(currentJob.value.id, editingTier.value.id, bulletId);

  const toast = await toastController.create({
    message: 'Added to tier',
    duration: 1500,
    color: 'success',
    position: 'bottom',
  });
  await toast.present();
};

// Delete bullet from all tiers
const handleDeleteBullet = async (bulletId: string) => {
  if (!currentJob.value) return;

  await tnfrStore.removeMenuBullet(currentJob.value.id, bulletId);

  const toast = await toastController.create({
    message: 'Deleted from all tiers',
    duration: 1500,
    color: 'danger',
    position: 'bottom',
  });
  await toast.present();
};

// Track tiers being removed for animation
const removingTiers = ref<Set<string>>(new Set());

const removeTier = async (tierId: string) => {
  if (!menuData.value?.tiers) return;

  const tier = menuData.value.tiers.find((t: any) => t.id === tierId);
  const tierName = tier?.name || 'Tier';

  // Add to removing set to trigger animation
  removingTiers.value.add(tierId);

  // Wait for animation
  await new Promise(resolve => setTimeout(resolve, 300));

  // Remove the tier from menuData
  const tierIndex = menuData.value.tiers.findIndex((t: any) => t.id === tierId);
  if (tierIndex !== -1) {
    menuData.value.tiers.splice(tierIndex, 1);
  }

  // Remove from editedTiers and removingTiers
  delete editedTiers[tierId];
  removingTiers.value.delete(tierId);

  // Show toast
  const toast = await toastController.create({
    message: `${tierName} removed`,
    duration: 1500,
    color: 'warning',
    position: 'bottom',
  });
  await toast.present();
};

const handleConfirmJob = async () => {
  if (!currentJob.value) return;

  // Update job name directly on the job object (before confirming)
  if (editedJobName.value.trim()) {
    currentJob.value.title = editedJobName.value.trim();
  }

  // Update menu title if edited
  if (editedMenuTitle.value.trim() && menuData.value) {
    menuData.value.name = editedMenuTitle.value.trim();
  }

  // Update offer titles in tier contentItems
  if (menuData.value?.tiers) {
    for (const tier of menuData.value.tiers) {
      const editedTitle = editedTiers[tier.id]?.offerTitle;
      if (editedTitle && tier.contentItems) {
        const titleItem = tier.contentItems.find((item: any) => item.refId?.includes('_title'));
        if (titleItem) {
          titleItem.content = editedTitle;
          titleItem.name = editedTitle;
        }
      }
    }
  }

  // Update the job's menu data with removed tiers
  if (currentJob.value.menus && currentJob.value.menus.length > 0) {
    currentJob.value.menus[0] = menuData.value;
  }

  // Mark job as edited
  currentJob.value.edited = true;

  // Confirm the pending job (moves to jobs array)
  await tnfrStore.confirmPendingJob();

  // Show success toast
  const toast = await toastController.create({
    message: "Job confirmed",
    duration: 1500,
    color: "success",
    position: "bottom",
  });
  await toast.present();

  // Navigate to cart
  router.push('/cart');
};

const handleCancel = async () => {
  await tnfrStore.clearPendingJob();
  router.push('/directory');
};

onMounted(async () => {
  loading.value = true;
  await tnfrStore.load();

  const jobId = route.params.jobId as string;

  if (jobId) {
    // Check pendingJob first, then jobs array
    const job = tnfrStore.pendingJob?.id === jobId
      ? tnfrStore.pendingJob
      : tnfrStore.jobs.find((j) => j.id === jobId);

    if (job) {
      currentJob.value = job as any;

      // Initialize job name from existing title or problem name
      editedJobName.value = job.title || job.problem?.name || "";

      // Use menu data from the job's menus array (already loaded in tnfrStore)
      if (job.menus && job.menus.length > 0) {
        const menu = job.menus[0];
        menuData.value = menu;

        // Initialize edited values
        const existingMods = (job as any).menuModifications;
        editedMenuTitle.value = existingMods?.menuTitle || menu.name || "";

        // Initialize tier editing state
        menu.tiers?.forEach((tier: any) => {
          const tierMod = existingMods?.tierModifications?.[tier.id];

          // Get tier title from content items with _title refId
          const titleItem = tier.contentItems?.find((item: any) =>
            item.refId?.includes("_title"),
          );
          const defaultTitle = titleItem?.content || tier.offer?.name || "";

          editedTiers[tier.id] = {
            offerTitle: tierMod?.offerTitle || defaultTitle,
            offerDetails:
              tierMod?.offerDetails || getContentItemsText(tier) || "",
          };
        });
      }
    }
  }

  loading.value = false;
});
</script>

<style scoped>
.edit-job-container {
  padding: 20px;
  max-width: 800px;
  margin: 0 auto;
}

.page-title {
  margin: 0 0 8px 0;
  color: var(--ion-color-medium);
  font-size: 14px;
  font-weight: 500;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.job-name {
  margin: 0 0 24px 0;
  color: var(--ion-text-color);
  font-size: 24px;
  font-weight: 600;
  text-align: center;
}

.action-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-bottom: 24px;
}

.loading-message,
.no-job-message,
.empty-state {
  text-align: center;
  padding: 40px 20px;
  color: var(--ion-color-medium);
  font-size: 14px;
}

/* Data Table - PriceList style */
.data-table {
  background: var(--ion-color-light);
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: 24px;
}

.table-header {
  background: var(--ion-color-primary);
  color: var(--ion-color-primary-contrast);
  font-weight: 600;
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.table-header ion-col {
  padding: 12px 16px;
}

.table-row {
  border-bottom: 1px solid var(--ion-color-light-shade);
  background: var(--ion-background-color);
}

.table-row:last-child {
  border-bottom: none;
}

.table-row ion-col {
  padding: 12px 16px;
  display: flex;
  align-items: center;
}

.editable-row {
  cursor: pointer;
  transition: background-color 0.2s;
}

.editable-row:hover {
  background: var(--ion-color-light);
}

.tier-row {
  background: var(--ion-color-light);
  border-top: 2px solid var(--ion-color-medium);
  transition: opacity 0.3s ease, transform 0.3s ease, background-color 0.3s ease;
}

.tier-removing {
  opacity: 0;
  transform: translateX(-20px);
  background-color: var(--ion-color-danger-tint) !important;
}

.sub-row {
  background: var(--ion-background-color);
  transition: opacity 0.3s ease, transform 0.3s ease, background-color 0.3s ease;
}

.cell-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--ion-color-medium);
}

.tier-label {
  font-weight: 600;
  color: var(--ion-color-dark);
  font-size: 16px;
}

.cell-input {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}

.cell-edit-icon {
  font-size: 16px;
  color: var(--ion-color-primary);
  flex-shrink: 0;
}

.cell-value {
  font-size: 14px;
  color: var(--ion-color-dark);
}

.inline-input {
  --padding-start: 0;
  --padding-end: 0;
  font-size: 14px;
}

.cell-default {
  font-size: 13px;
  color: var(--ion-color-medium);
  font-style: italic;
}

.cell-tier-info {
  display: flex;
  align-items: center;
  gap: 12px;
}

.tier-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--ion-color-dark);
  text-transform: capitalize;
}

.tier-ref {
  font-size: 12px;
  color: var(--ion-color-medium);
  font-family: monospace;
}

.cell-details {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.detail-item {
  font-size: 13px;
  color: var(--ion-color-dark);
  line-height: 1.4;
}

.no-content {
  font-size: 13px;
  color: var(--ion-color-medium);
  font-style: italic;
}

.details-preview {
  flex: 1;
}

.more-items {
  color: var(--ion-color-medium);
  font-style: italic;
}

/* Details Modal Styles */
.details-modal-content {
  padding: 16px;
}

.modal-tier-name {
  font-size: 20px;
  font-weight: 700;
  color: var(--ion-text-color);
  text-transform: capitalize;
  margin-bottom: 20px;
  text-align: center;
}

.content-items-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 20px;
}

.content-item-row {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--ion-color-light);
  border-radius: 8px;
  padding: 4px 8px 4px 16px;
}

.content-item-input {
  flex: 1;
  --padding-start: 0;
  --padding-end: 0;
  font-size: 15px;
}

/* Bullets Section Styles */
.bullets-section {
  margin-bottom: 24px;
}

.section-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--ion-color-medium);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 12px;
}

.empty-section {
  font-size: 14px;
  color: var(--ion-color-medium);
  font-style: italic;
  padding: 12px;
  text-align: center;
  background: var(--ion-color-light);
  border-radius: 8px;
}

.bullet-content {
  flex: 1;
  font-size: 15px;
  color: var(--ion-text-color);
  cursor: pointer;
  padding: 8px 0;
}

.bullet-content:hover {
  color: var(--ion-color-primary);
}

.bullet-actions {
  display: flex;
  gap: 0;
}

.available-list .content-item-row {
  background: var(--ion-color-light-tint);
}

.available-item {
  opacity: 0.8;
}

.add-section {
  border-top: 1px solid var(--ion-color-light-shade);
  padding-top: 20px;
}

.add-bullet-row {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--ion-color-light);
  border-radius: 8px;
  padding: 4px 8px 4px 16px;
}

/* Mobile adjustments */
@media (max-width: 767px) {
  .edit-job-container {
    padding: 16px;
  }

  .table-header {
    display: none;
  }

  .table-row ion-col {
    padding: 8px 12px;
  }

  .action-buttons {
    flex-direction: column;
  }
}
</style>