Hello from MCP server

List Files | Just Commands | Repo | Logs

← back |
<template>
  <BaseLayout title="Technician - Check Hours">
    <!-- Debug Toolbar -->
    <DebugToolbar
      ref="debugToolbar"
      :function-groups="functionGroups"
      :reactive-data="reactiveVarsData"
    >
      <template #info-sections>
        <div class="debug-section">
          <strong>Problem:</strong> {{ problem?.name || 'N/A' }}
        </div>
        <div class="debug-section">
          <strong>Band-Aid Hours:</strong> {{ bandAidHours }}
        </div>
        <div class="debug-section">
          <strong>Display Hours:</strong> {{ displayHours }}
        </div>
        <div class="debug-section">
          <strong>Issues:</strong> {{ localChecklistIssues.length }}
        </div>
      </template>
    </DebugToolbar>

    <div class="check-hours-container">
      <h2 class="check-hours-title">I can do this job in:</h2>

      <!-- Hours slider - always visible, disabled until issues exist -->
      <div class="slider-section">
        <div class="hours-display">{{ displayHours.toFixed(1) }} hours</div>
        <ion-range
          :min="bandAidHours"
          :max="bandAidHours + 5"
          :step="0.5"
          v-model="sliderValue"
          @ionInput="handleSliderInput"
          @ionChange="handleSliderChange"
          :color="localChecklistIssues.length > 0 ? 'primary' : 'medium'"
          :ticks="true"
          :snaps="true"
          :pin="false"
          :disabled="localChecklistIssues.length === 0"
          class="hours-slider"
          :class="{ 'slider-disabled': localChecklistIssues.length === 0 }"
        >
          <ion-icon slot="start" :icon="remove" size="large"></ion-icon>
          <ion-icon slot="end" :icon="add" size="large"></ion-icon>
        </ion-range>
        <div class="slider-labels">
          <span>{{ bandAidHours.toFixed(1) }}</span>
          <span>{{ (bandAidHours + 5).toFixed(1) }}</span>
        </div>
      </div>

      <!-- Action buttons -->
      <div class="confirm-section">
        <ion-button
          size="large"
          color="success"
          @click="handleConfirm"
        >
          Confirm Hours
        </ion-button>
        <ion-button
          size="large"
          color="danger"
          @click="handleCancel"
        >
          Cancel
        </ion-button>
      </div>

      <div class="content-section">
        <!-- Check Hours Checklist - Always displayed -->
        <div class="checklist-card">
          <div
            v-for="(item, index) in CHECK_HOURS_ITEMS"
            :key="index"
            class="checklist-row"
            :class="{ 'has-issue': checklistAnswers[index] === false }"
            @click="toggleAnswer(index)"
          >
            <span class="checklist-text">{{ item }}</span>
            <div class="check-icon-container" @click.stop="toggleAnswer(index)">
              <ion-icon
                v-if="checklistAnswers[index]"
                :icon="checkmarkCircle"
                class="check-icon check-yes"
              ></ion-icon>
              <ion-icon
                v-else
                :icon="closeCircle"
                class="check-icon check-no"
              ></ion-icon>
            </div>
          </div>

          <!-- Anything else? text area -->
          <div class="anything-else-section">
            <label class="anything-else-label">Anything else?</label>
            <div class="anything-else-input-row">
              <ion-textarea
                v-model="anythingElseNotes"
                :rows="2"
                placeholder="Add any additional notes about this job..."
                class="anything-else-textarea"
                @ionInput="handleNotesInput"
              ></ion-textarea>
              <button
                class="submit-note-button"
                :disabled="!anythingElseNotes.trim()"
                @click="submitNote"
              >
                Add
              </button>
            </div>
            <!-- Submitted notes list -->
            <div v-if="submittedNotes.length > 0" class="submitted-notes-list">
              <div
                v-for="(note, index) in submittedNotes"
                :key="index"
                class="submitted-note-item"
              >
                <span class="submitted-note-text">{{ note }}</span>
                <button class="remove-note-button" @click="removeSubmittedNote(index)">
                  <ion-icon :icon="closeCircle"></ion-icon>
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>


    <!-- Price Preview (Edit Mode Only) -->
    <div v-if="tnfrStore.editMode && pricePreviewTiers.length > 0" class="price-preview-section">
      <h3 class="price-preview-title">Price Preview</h3>
      <div class="price-preview-grid">
        <div
          v-for="tier in pricePreviewTiers"
          :key="tier.id"
          class="price-preview-item"
          :class="getTierPreviewClass(tier.name)"
        >
          <span class="tier-name">{{ tier.name }}</span>
          <span class="tier-price"><ShowCurrency :currencyIn="tier.price" /></span>
        </div>
      </div>
    </div>

  </BaseLayout>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onBeforeMount, onBeforeUnmount, onUnmounted, onActivated, onDeactivated, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import {
  IonRange,
  IonIcon,
  IonTextarea,
  IonButton,
} from "@ionic/vue";
import { add, remove, warning, closeCircle, checkmarkCircle } from "ionicons/icons";
import BaseLayout from "@/components/BaseLayout.vue";
import ShowCurrency from "@/components/ShowCurrency.vue";
import DebugToolbar, { type FunctionGroup } from "@/components/DebugToolbar.vue";
import { useOrganizationStore } from "@/stores/organization";
import { useTnfrStore } from "@/stores/tnfr";
import { calculateTierPrices, type MenuDataWithPrices } from "@/lib/calculateTierPrices";

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

// Problem ID from route params
const problemId = computed(() => route.params.problemId as string || '');

// Use pendingJob from the store
const pendingJob = computed(() => tnfrStore.pendingJob);

// Problem data loaded directly from problemId
const jobContentData = ref<any>(null);

// Derived values from loaded job content (not from tnfrStore job)
const problem = computed(() => jobContentData.value?.problem || null);
const menuData = computed(() => jobContentData.value?.menus?.[0] || null);

// Calculate band-aid hours from the offer data
const bandAidHours = computed(() => {
  const firstMenu = menuData.value;
  if (!firstMenu?.tiers?.length) return 0;

  // Band-aid tier is the last tier
  const bandAidTier = firstMenu.tiers[firstMenu.tiers.length - 1];
  const hours = bandAidTier?.offer?.costsTime?.reduce(
    (sum: number, cost: any) => sum + (cost.hours || 0),
    0
  ) || 0;

  console.log('[CheckHours] bandAidHours calculated:', hours);
  return hours;
});

// Check Hours Checklist
const CHECK_HOURS_ITEMS = [
  "I can easily access the work area.",
  "I can work comfortably in the space.",
  "I can complete this job with standard tools.",
  "I can complete this job without delays.",
  "I can complete this job with standard materials and methods.",
];

// Negated versions for when items are marked "No"
const CHECK_HOURS_ITEMS_NEGATED = [
  "I can not easily access the work area.",
  "I can not work comfortably in the space.",
  "I can not complete this job with standard tools.",
  "I can not complete this job without delays.",
  "I can not complete this job with standard materials and methods.",
];

// Helper to get the negated version of a checklist item
const getNegatedItem = (index: number): string => CHECK_HOURS_ITEMS_NEGATED[index];

// Helper to check if a note matches a checklist item (original or negated)
const isChecklistNote = (note: string): boolean => {
  return CHECK_HOURS_ITEMS.includes(note) || CHECK_HOURS_ITEMS_NEGATED.includes(note);
};

// Helper to find which checklist index a note belongs to
const getChecklistIndex = (note: string): number => {
  let index = CHECK_HOURS_ITEMS_NEGATED.indexOf(note);
  if (index === -1) {
    index = CHECK_HOURS_ITEMS.indexOf(note);
  }
  return index;
};

const CHECK_HOURS_DOCS = [
  "Covers: ladder, roof, attic, crawl space, stairs, building access",
  "Covers: confined space, room to move, sanitary conditions",
  "Covers: lift equipment, specialty tools, equipment rentals",
  "Covers: waiting for other providers, excessive travel distance",
  "Covers: material costs, finished ceiling protection, special methods",
];

// UI state
const displayHours = ref<number>(0);
const sliderValue = ref<number>(1);
const calculatedMenuData = ref<MenuDataWithPrices | null>(null);
const checklistAnswers = ref<boolean[]>(CHECK_HOURS_ITEMS.map(() => true));
const anythingElseNotes = ref<string>("");
const submittedNotes = ref<string[]>([]);

// Local UI state for checklist (computed from answers and notes)
const localChecklistIssues = computed(() => {
  const checklistItemIssues = CHECK_HOURS_ITEMS.filter((_, index) => checklistAnswers.value[index] === false);
  const issues = [...checklistItemIssues, ...submittedNotes.value];
  console.log('[CheckHours] localChecklistIssues:', issues.length, issues);
  console.log('[CheckHours] checklistAnswers:', checklistAnswers.value);
  return issues;
});

// Debug Toolbar
const debugToolbar = ref<InstanceType<typeof DebugToolbar> | null>(null);

// Debug function groups
const functionGroups = ref<FunctionGroup[]>([
  {
    label: 'View Functions',
    functions: [
      { label: 'handleConfirm()', value: 'handleConfirm' },
      { label: 'handleNext()', value: 'handleNext' },
      { label: 'toggleAnswer(index)', value: 'toggleAnswer' },
      { label: 'submitNote()', value: 'submitNote' },
      { label: 'removeNote(index)', value: 'removeNote' },
      { label: 'recalculatePrices()', value: 'recalculatePrices' },
      { label: 'resetAndLoadJob()', value: 'resetAndLoadJob' },
    ],
  },
  {
    label: '@/stores/organization',
    functions: [
      { label: 'orgStore.loadVariables()', value: 'orgStore.loadVariables' },
    ],
  },
  {
    label: 'vue-router',
    functions: [
      { label: 'router.push(path)', value: 'router.push' },
    ],
  },
]);

// Helper to log executions via the toolbar
function logExecution(name: string, args?: any[]) {
  debugToolbar.value?.logExecution(name, args);
}

// Track lifecycle
onBeforeMount(() => debugToolbar.value?.logLifecycle('onBeforeMount'));
onBeforeUnmount(() => debugToolbar.value?.logLifecycle('onBeforeUnmount'));
onUnmounted(() => debugToolbar.value?.logLifecycle('onUnmounted'));
onActivated(() => debugToolbar.value?.logLifecycle('onActivated'));
onDeactivated(() => debugToolbar.value?.logLifecycle('onDeactivated'));

// Computed: All reactive variables for debug display
const reactiveVarsData = computed(() => ({
  // Route params
  'route.params.problemId': route.params.problemId,
  'pendingJob.id': pendingJob.value?.id,
  // Refs
  problem: problem.value,
  bandAidHours: bandAidHours.value,
  displayHours: displayHours.value,
  sliderValue: sliderValue.value,
  sliderEnabled: localChecklistIssues.value.length > 0,
  localChecklistIssues: localChecklistIssues.value,
  checklistAnswers: checklistAnswers.value,
  submittedNotes: submittedNotes.value,
  pendingJobId: pendingJob.value?.id,
  menuData: menuData.value,
  calculatedMenuData: calculatedMenuData.value,
  // Computed
  pricePreviewTiers: pricePreviewTiers.value,
  // Store state
  'tnfrStore.editMode': tnfrStore.editMode,
  'orgStore.hourlyFee': orgStore.hourlyFee,
  'orgStore.serviceCallFee': orgStore.serviceCallFee,
}));

// Recalculate tier prices based on current hours
const recalculatePrices = () => {
  if (!menuData.value) return;

  const extraHours = localChecklistIssues.value.length === 0 ? 0 : (displayHours.value - bandAidHours.value);

  calculatedMenuData.value = calculateTierPrices(
    menuData.value,
    {
      hourlyFee: orgStore.hourlyFee,
      serviceCallFee: orgStore.serviceCallFee,
      saDiscount: orgStore.saDiscount,
      salesTax: orgStore.salesTax,
    },
    bandAidHours.value,
    extraHours
  );
};

// Price preview tiers for edit mode
const pricePreviewTiers = computed(() => {
  if (!calculatedMenuData.value?.tiers) return [];
  return calculatedMenuData.value.tiers;
});

// Get CSS class for tier preview based on tier name
const getTierPreviewClass = (tierName: string): string => {
  const name = tierName?.toLowerCase() || '';
  if (name.includes('platinum')) return 'tier-platinum';
  if (name.includes('gold')) return 'tier-gold';
  if (name.includes('silver')) return 'tier-silver';
  if (name.includes('bronze')) return 'tier-bronze';
  if (name.includes('band')) return 'tier-bandaid';
  return '';
};

// Handle confirm button click
const handleConfirm = () => {
  handleNext();
};

// Handle cancel button click
const handleCancel = () => {
  router.back();
};

// Toggle answer between Yes and No
const toggleAnswer = async (index: number) => {
  console.log('[CheckHours] toggleAnswer called, index:', index, 'current value:', checklistAnswers.value[index]);

  // Check if slider was previously disabled (no issues)
  const wasSliderDisabled = localChecklistIssues.value.length === 0;

  const newValue = !checklistAnswers.value[index];
  // Use splice to ensure Vue reactivity is triggered
  checklistAnswers.value.splice(index, 1, newValue);
  console.log('[CheckHours] toggleAnswer after toggle:', checklistAnswers.value[index]);
  console.log('[CheckHours] localChecklistIssues.length:', localChecklistIssues.value.length);

  // Auto-advance slider by one increment when first issue is added (slider becomes enabled)
  if (wasSliderDisabled && newValue === false && localChecklistIssues.value.length > 0) {
    const newSliderValue = bandAidHours.value + 0.5; // One increment (step is 0.5)
    sliderValue.value = newSliderValue;
    displayHours.value = newSliderValue;
    recalculatePrices();
    console.log('[CheckHours] Auto-advanced slider to:', newSliderValue);
  }

  // Reset slider to band-aid minimum when all issues are cleared
  if (localChecklistIssues.value.length === 0) {
    sliderValue.value = bandAidHours.value;
    displayHours.value = bandAidHours.value;
    recalculatePrices();
    console.log('[CheckHours] Reset slider to band-aid minimum:', bandAidHours.value);
  }

  // Add or remove the checklist item as a note (using negated version)
  if (pendingJob.value?.id) {
    const negatedItem = getNegatedItem(index);
    if (newValue === false) {
      // Toggled to "No" - add negated version as note
      await tnfrStore.addNote(pendingJob.value.id, negatedItem);
    } else {
      // Toggled to "Yes" - remove negated note
      await tnfrStore.removeNote(pendingJob.value.id, negatedItem);
    }
  }
};

// Handle notes input
const handleNotesInput = (event: CustomEvent) => {
  anythingElseNotes.value = event.detail.value || "";
};

// Submit a note as a checklist issue
const submitNote = async () => {
  const note = anythingElseNotes.value.trim();
  if (note && pendingJob.value?.id) {
    submittedNotes.value.push(note);
    await tnfrStore.addNote(pendingJob.value.id, note);
    anythingElseNotes.value = "";
  }
};

// Remove a submitted note
const removeSubmittedNote = async (index: number) => {
  const note = submittedNotes.value[index];
  submittedNotes.value.splice(index, 1);
  if (pendingJob.value?.id && note) {
    await tnfrStore.removeNote(pendingJob.value.id, note);
  }
};

const handleSliderInput = (event: CustomEvent) => {
  let value = event.detail.value;
  // Prevent sliding to base position when issues exist
  if (localChecklistIssues.value.length > 0 && value <= bandAidHours.value) {
    value = bandAidHours.value + 0.5;
  }
  sliderValue.value = value;
  displayHours.value = value;
};

const handleSliderChange = (event: CustomEvent) => {
  let value = event.detail.value;
  // Prevent sliding to base position when issues exist
  if (localChecklistIssues.value.length > 0 && value <= bandAidHours.value) {
    value = bandAidHours.value + 0.5;
  }
  sliderValue.value = value;
  displayHours.value = value;
  // Recalculate prices when slider changes (for edit mode preview)
  recalculatePrices();
};

// Function to reset state and load job
const resetAndLoadJob = async () => {
  // Reset UI state
  checklistAnswers.value = CHECK_HOURS_ITEMS.map(() => true);
  calculatedMenuData.value = null;
  anythingElseNotes.value = "";
  submittedNotes.value = [];

  // Load tnfr store and org variables
  await tnfrStore.load();
  await orgStore.loadVariables();

  // Load job content directly from problemId
  if (problemId.value) {
    const { loadJobContentByProblemId } = await import("@/framework/jobContent");
    const content = await loadJobContentByProblemId(problemId.value);
    jobContentData.value = content;
    console.log('[CheckHours] Loaded job content:', content);
    console.log('[CheckHours] bandAidHours after load:', bandAidHours.value);
  }

  // Restore checklist state from existing job notes (if pending job exists)
  if (pendingJob.value?.notes && pendingJob.value.notes.length > 0) {
    // Restore checklist answers - if negated note exists, that item was marked "No"
    checklistAnswers.value = CHECK_HOURS_ITEMS_NEGATED.map(negatedItem =>
      !pendingJob.value!.notes!.includes(negatedItem)
    );

    // Separate custom notes from checklist items (check both original and negated)
    submittedNotes.value = pendingJob.value.notes.filter(
      note => !isChecklistNote(note)
    );
  }

  // Initialize slider from baseHours + any existing extraTime
  const existingExtraTime = pendingJob.value?.extraTime || 0;
  displayHours.value = bandAidHours.value + existingExtraTime;
  sliderValue.value = bandAidHours.value + existingExtraTime;
  console.log('[CheckHours] Initialized slider - displayHours:', displayHours.value, 'sliderValue:', sliderValue.value);

  // Calculate initial prices
  recalculatePrices();
};

// Watch for route changes to reset state when switching problems
watch(
  () => route.params.problemId,
  async (newVal, oldVal) => {
    if (newVal !== oldVal) {
      await resetAndLoadJob();
    }
  }
);

onMounted(async () => {
  console.log('[CheckHours] onMounted - initial checklistAnswers:', checklistAnswers.value);
  await resetAndLoadJob();
  console.log('[CheckHours] onMounted - after resetAndLoadJob, checklistAnswers:', checklistAnswers.value);
  console.log('[CheckHours] onMounted - localChecklistIssues:', localChecklistIssues.value);
});

const handleNext = async () => {
  // extraTime is the additional hours from slider adjustment (0 if no issues/adjustment)
  const extraHours = localChecklistIssues.value.length === 0 ? 0 : (displayHours.value - bandAidHours.value);

  // Update the tnfr store with the extra time and confirm hours (if pending job exists)
  if (pendingJob.value?.id) {
    console.log('[CheckHours] Updating tnfr store with pendingJob id:', pendingJob.value.id);
    await tnfrStore.updateExtraTime(pendingJob.value.id, extraHours);
    await tnfrStore.setHoursConfirmed(pendingJob.value.id, true);
    await tnfrStore.save();
  }

  // Navigate to edit screen
  router.push(`/edit/${pendingJob.value?.id || problemId.value}`);
};
</script>

<style scoped>
:deep(.ion-page) {
  animation: none !important;
  transform: none !important;
  transition: none !important;
}

.check-hours-container {
  padding: 20px;
  padding-bottom: 200px;
  max-width: 1200px;
  margin: 0 auto;
  animation: none !important;
  transform: none !important;
  transition: none !important;
}

.check-hours-title {
  margin: 0 0 8px 0;
  color: var(--ion-text-color);
  font-size: 24px;
  font-weight: 600;
  text-align: center;
}

.confirm-section {
  max-width: 400px;
  margin: 0 auto 16px;
  display: flex;
  gap: 12px;
  justify-content: center;
}

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

.content-section {
  padding: 0 20px 100px 20px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.checklist-card {
  background-color: var(--ion-background-color);
  border-radius: 12px;
  padding: 24px;
  max-width: 800px;
  width: 100%;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
}

.checklist-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 0;
  border-bottom: 1px solid var(--ion-color-light-shade);
  gap: 16px;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

.checklist-row:hover {
  background-color: rgba(var(--ion-color-primary-rgb), 0.05);
}

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

.checklist-row.has-issue {
  background-color: rgba(var(--ion-color-warning-rgb), 0.1);
  margin: 0 -24px;
  padding: 16px 24px;
}

.checklist-text {
  color: var(--ion-text-color);
  font-size: 16px;
  line-height: 1.4;
  flex: 1;
}

.check-icon-container {
  flex-shrink: 0;
  cursor: pointer;
  padding: 4px;
}

.check-icon {
  font-size: 32px;
  transition: transform 0.2s ease;
}

.check-icon:hover {
  transform: scale(1.1);
}

.check-icon.check-yes {
  color: var(--ion-color-success);
}

.check-icon.check-no {
  color: var(--ion-color-danger);
}

/* Anything else section */
.anything-else-section {
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid var(--ion-color-light-shade);
}

.anything-else-label {
  display: block;
  font-size: 16px;
  font-weight: 600;
  color: var(--ion-text-color);
  margin-bottom: 12px;
}

.anything-else-textarea {
  --background: var(--ion-color-light);
  --color: var(--ion-text-color);
  --padding-start: 16px;
  --padding-end: 16px;
  --padding-top: 12px;
  --padding-bottom: 12px;
  border: 1px solid var(--ion-color-medium);
  border-radius: 8px;
  font-size: 16px;
  line-height: 1.5;
}

.anything-else-textarea:focus-within {
  border-color: var(--ion-color-primary);
}

.anything-else-input-row {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.anything-else-input-row .anything-else-textarea {
  flex: 1;
}

.submit-note-button {
  padding: 12px 24px;
  font-size: 16px;
  font-weight: 600;
  color: var(--ion-color-primary-contrast);
  background-color: var(--ion-color-primary);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s ease;
  white-space: nowrap;
  align-self: stretch;
}

.submit-note-button:hover:not(:disabled) {
  transform: scale(1.05);
  background-color: var(--ion-color-primary-shade);
}

.submit-note-button:active:not(:disabled) {
  transform: scale(0.95);
}

.submit-note-button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.submitted-notes-list {
  margin-top: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.submitted-note-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background-color: rgba(var(--ion-color-warning-rgb), 0.15);
  border-left: 4px solid var(--ion-color-warning);
  border-radius: 8px;
}

.submitted-note-text {
  flex: 1;
  font-size: 14px;
  color: var(--ion-text-color);
  line-height: 1.4;
}

.remove-note-button {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--ion-color-medium);
  font-size: 20px;
  transition: color 0.2s ease;
}

.remove-note-button:hover {
  color: var(--ion-color-danger);
}

/* Notification bubbles */
:global(.notification-bubbles) {
  position: fixed;
  top: 70px;
  right: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 400px;
  z-index: 10000;
}

:global(.notification-bubble) {
  background-color: var(--ion-color-warning);
  color: var(--ion-color-dark);
  padding: 16px 20px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
  animation: slideIn 0.3s ease-out;
  display: flex;
  align-items: center;
  gap: 12px;
}

:global(.notification-icon) {
  font-size: 24px;
  flex-shrink: 0;
  color: var(--ion-color-dark);
}

:global(.notification-text) {
  flex: 1;
}

@keyframes slideIn {
  from {
    transform: translateX(100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

/* Slider Section */
.slider-section {
  padding: 16px 20px 8px;
  max-width: 600px;
  margin: 0 auto;
}

.hours-display {
  text-align: center;
  font-size: 48px;
  font-weight: 700;
  color: var(--ion-color-primary);
  margin-bottom: 8px;
  font-variant: tabular-nums;
}

.slider-labels {
  display: flex;
  justify-content: space-between;
  padding: 0 8px;
  font-size: 14px;
  color: var(--ion-color-medium);
  font-variant: tabular-nums;
}

.slider-disabled {
  opacity: 0.5;
}

.hours-slider {
  --bar-height: 8px;
  --bar-background: var(--ion-color-medium);
  --bar-background-active: var(--ion-color-primary);
  --knob-size: 32px;
  padding: 10px 0;
}

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

  .check-hours-title {
    font-size: 20px;
  }

  .hours-display {
    font-size: 36px;
  }

  .checklist-card {
    padding: 16px;
  }

  .checklist-row {
    padding: 12px 0;
    gap: 12px;
  }

  .checklist-row.has-issue {
    margin: 0 -16px;
    padding: 12px 16px;
  }

  .checklist-text {
    font-size: 14px;
  }

  .check-icon {
    font-size: 28px;
  }

  :global(.notification-bubbles) {
    right: 12px;
    top: 60px;
    max-width: calc(100% - 24px);
  }

  :global(.notification-bubble) {
    font-size: 13px;
    padding: 12px 16px;
  }
}

/* Info Modal Styles */
.info-content {
  color: var(--ion-color-dark);
}

.info-content pre {
  background: var(--ion-color-light);
  padding: 16px;
  border-radius: 8px;
  overflow-x: auto;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}

/* Price Preview Section (Edit Mode) */
.price-preview-section {
  max-width: 800px;
  margin: 24px auto;
  padding: 20px;
  background-color: var(--ion-color-warning);
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.price-preview-title {
  margin: 0 0 16px 0;
  font-size: 18px;
  font-weight: 700;
  color: var(--ion-color-warning-contrast);
  text-align: center;
  font-variant: small-caps;
}

.price-preview-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.price-preview-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  border-radius: 8px;
  background-color: rgba(255, 255, 255, 0.9);
}

.price-preview-item .tier-name {
  font-size: 16px;
  font-weight: 600;
  color: #000;
  font-variant: small-caps;
}

.price-preview-item .tier-price {
  font-size: 18px;
  font-weight: 700;
  color: #000;
}

.price-preview-item.tier-platinum {
  border-left: 4px solid var(--menu-color-platinum, #3db4d6);
}

.price-preview-item.tier-gold {
  border-left: 4px solid var(--menu-color-gold, #ffd83b);
}

.price-preview-item.tier-silver {
  border-left: 4px solid var(--menu-color-silver, #bfbfbf);
}

.price-preview-item.tier-bronze {
  border-left: 4px solid var(--menu-color-bronze, #ffad2b);
}

.price-preview-item.tier-bandaid {
  border-left: 4px solid var(--menu-color-bandaid, #ff8073);
}
</style>