載入中…
計
GoKaiKei
$refs.mobileHeaderToolsButton?.focus()); }" class="gk-mobile-header-actions flex flex-nowrap items-center gap-1 sm:gap-2 justify-end flex-shrink-0">
A
A
A
ⓘ
+
clearDemoData())" type="button" class="w-full flex items-center justify-between px-3 py-2 text-xs rounded-lg border bg-white border-ink-200 text-ink-600 hover:bg-rose-50 hover:border-rose-200 hover:text-rose-700 transition">
PRO
PRO
⟳
05:00
06:00
07:00
08:00
09:00
10:00
11:00
17:00
18:00
19:00
20:00
21:00
22:00
23:00
PRO
ⓘ
ⓘ
–
ⓘ
ⓘ
ⓘ
ⓘ
ⓘ
%
ⓘ
ⓘ
ⓘ
ⓘ
PRO
新
PRO
$refs.notifBell.focus()) }" class="relative">
$refs.notifClose.focus()) }" :data-tip="t('notif_bell_aria')" :aria-label="notificationBellLabel" :aria-expanded="open" aria-haspopup="dialog" aria-controls="notification-panel" class="relative p-2 text-ink-500 hover:text-ink-800 hover:bg-white rounded-lg border border-transparent hover:border-ink-200 transition flex items-center justify-center">
$refs.notifBell.focus())" :aria-label="t('btn_close')" :title="t('btn_close')" class="p-1.5 rounded-md text-ink-500 hover:text-ink-900 hover:bg-ink-100 transition">
document.getElementById('notification-bell')?.focus())" :class="action.primary ? 'bg-amber-600 hover:bg-amber-700 text-white' : 'bg-ink-100 hover:bg-ink-200 text-ink-700'" class="px-3 py-1.5 text-xs rounded-md font-medium transition" x-text="action.label">
LINE
(returnFocus === 'sync' ? $refs.accountSync : $refs.accountProfile).focus()) }" class="relative flex items-center gap-1.5" x-show="auth.checked && auth.authenticated" x-cloak>
$refs.accountClose.focus()) }" :data-tip="syncStatus?.text" :aria-label="syncStatus?.text" :aria-expanded="open" aria-haspopup="dialog" aria-controls="account-panel" :class="{ 'bg-sky-50 text-sky-700 border-sky-200 animate-pulse': syncStatus?.kind === 'uploading' || syncStatus?.kind === 'downloading', 'bg-amber-50 text-amber-700 border-amber-200': syncStatus?.kind === 'never', 'bg-ink-100 text-ink-600 border-ink-200': syncStatus?.kind === 'offline', 'bg-rose-50 text-rose-700 border-rose-200': syncStatus?.kind === 'dirty', 'bg-sage-50 text-sage-700 border-sage-200': syncStatus?.kind === 'synced' }" class="px-2 py-1 rounded-full text-[0.6875rem] font-medium border flex items-center gap-1 transition whitespace-nowrap">
$refs.accountClose.focus()) }" class="p-1 text-ink-500 hover:text-ink-800 hover:bg-white rounded-lg border border-transparent hover:border-ink-200 transition flex items-center gap-1.5" :aria-label="auth.displayName ? t('auth_signed_in') + ': ' + auth.displayName : t('auth_signed_in')" :aria-expanded="open" aria-haspopup="dialog" aria-controls="account-panel">
(returnFocus === 'sync' ? $refs.accountSync : $refs.accountProfile).focus())" :aria-label="t('btn_close')" :title="t('btn_close')" class="ml-auto p-1.5 rounded-md text-ink-500 hover:text-ink-900 hover:bg-ink-100 transition">
(returnFocus === 'sync' ? $refs.accountSync : $refs.accountProfile).focus())" :disabled="!!cloudSync.operation" class="w-full px-3 py-2 text-sm text-left hover:bg-ink-50 flex items-center gap-2 text-ink-700 disabled:opacity-50">
(returnFocus === 'sync' ? $refs.accountSync : $refs.accountProfile).focus())" :disabled="!!cloudSync.operation" class="w-full px-3 py-2 text-sm text-left hover:bg-ink-50 flex items-center gap-2 text-ink-700 disabled:opacity-50">
:
2–5 PRO
$refs.accountClose.focus())" :disabled="loggingOut" class="w-full px-3 py-2 text-sm text-left hover:bg-red-50 flex items-center gap-2 text-rose-600 disabled:opacity-50 disabled:cursor-wait">
$refs.dataMenuClose.focus()) }" class="hidden sm:block p-2 text-ink-500 hover:text-ink-800 hover:bg-white rounded-lg border border-transparent hover:border-ink-200 transition" :data-tip="t('tip_data')" :aria-label="t('tip_data')" :aria-expanded="open" aria-haspopup="dialog" aria-controls="data-menu-panel">
undoPreAISnapshot())" class="w-full px-3 py-2 text-sm text-left bg-amber-50 hover:bg-amber-100 flex items-start gap-2 text-amber-900 border-b border-amber-200">
openDailySnapshotsModal(document.getElementById(returnFocusId)))" class="w-full px-3 py-2 text-sm text-left hover:bg-ink-50 flex items-center gap-2 text-ink-700">
openLoginRequiredUpgrade())" class="w-full px-3 py-2 text-sm text-left hover:bg-ink-50 flex items-center gap-2 text-ink-400">
openLoginRequiredUpgrade())" class="w-full px-3 py-2 text-sm text-left hover:bg-ink-50 flex items-center gap-2 text-ink-400">
openHistory())" class="w-full px-3 py-2 text-sm text-left hover:bg-ink-50 flex items-center gap-2 text-ink-700">
openBulkPriceAdjust())" class="w-full px-3 py-2 text-sm text-left hover:bg-ink-50 flex items-center gap-2 text-ink-700" :data-tip="t('bulk_price_btn_tip')">
PRO
resetAllData())" class="w-full px-3 py-2 text-sm text-left hover:bg-red-50 flex items-center gap-2 text-rose-600">
$refs.mobileHeaderToolsButton?.focus())" class="sm:hidden fixed inset-0 z-[51] bg-ink-900/50" aria-hidden="true">
openTemplatePicker($refs.mobileHeaderToolsButton))" class="gk-mobile-tool-item">
openSettings($refs.mobileHeaderToolsButton))" class="gk-mobile-tool-item">
openHelp($refs.mobileHeaderToolsButton))" class="gk-mobile-tool-item">
openStoresManager($refs.mobileHeaderToolsButton))" class="gk-mobile-tool-item">
openModesModal($refs.mobileHeaderToolsButton))" class="gk-mobile-mode-info" :aria-label="t('modes_modal_open')" :title="t('modes_modal_open')">
focusMobileToolsFirst($refs.mobileHeaderToolsMenu))" :aria-expanded="mobileToolsOpen" aria-haspopup="menu" aria-controls="mobile-header-tools-menu" :aria-label="t('mobile_header_tools')" :title="t('mobile_header_tools')" class="sm:hidden w-9 h-9 rounded-lg text-ink-500 hover:text-ink-800 hover:bg-white border border-transparent hover:border-ink-200 transition flex items-center justify-center">
/
scrollToAnchor('ingredients-workspace'))" :class="activeTab === 'ingredients' ? 'bg-ink-900 text-white shadow-card' : 'text-ink-600 hover:text-ink-900'" class="px-4 sm:px-5 py-2 rounded-lg text-sm font-medium transition flex items-center gap-2">
−
−
−
−
=
·
scrollToAnchor('ingredients-workspace'))" href="#" class="flex items-center gap-1.5 px-3 py-2 bg-white dark:bg-ink-800 border border-ink-200 dark:border-ink-700 rounded-lg hover:border-amber-400 transition cursor-pointer">
①
→
②
→
③
scrollToAnchor('ana-menu'), 400)" href="#" class="block p-3 sm:p-4 gk-card gk-card-hover transition cursor-pointer">
{ if (recipes.length > 0) { selRec = recipes[0]; drillTab = 'pricing'; } }, 200)" href="#" class="block p-3 sm:p-4 gk-card gk-card-hover transition cursor-pointer">
*
≈
1
=
$
1
=
=
$
1
=
=
$
:
/
「
」
→
→
$
→
$
/
−
+
scrollToAnchor('ingredients-workspace'))" class="underline font-medium" x-text="t('link_go_ingredients')">
.
—
%
*
×
PRO
Number(g.max || 1)) g.min = g.max" type="number" min="1" max="10" step="1" inputmode="decimal" class="w-16 px-2 py-1.5 bg-white border border-ink-300 rounded-lg text-sm text-right num">
▲
▼
%
+ foodpanda
+ UberEats
%
%
(
%)
▼
0) openMethodCard(r); ">
$refs.moreButton?.focus()); }" class="absolute top-2 right-2 flex gap-0.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 sm:focus-within:opacity-100 transition bg-white/90 backdrop-blur-sm rounded-lg p-0.5 shadow-card z-20">
$refs.firstRecipeAction?.focus())" :disabled="_isRecipeQuickActionBusy(r.id)" :data-tip="t('recipe_more_actions')" :aria-label="t('recipe_more_actions') + ': ' + r.name" :title="t('recipe_more_actions') + ': ' + r.name" :aria-expanded="moreOpen" :aria-controls="'recipe-actions-' + r.id" class="p-1.5 text-ink-400 hover:text-accent-600 hover:bg-accent-50 rounded disabled:opacity-40 disabled:cursor-wait">
AI
·
・
・
・
+
▾
/
›
›
·
·
SELLING PRICE
−
TOTAL COST
=
MARGIN
COST BREAKDOWN
·
sub-recipe
FOOD COST TOTAL
30 DAY MARGIN TREND
HOURLY × WEEKDAY HEATMAP
·
sub-recipe
VARIABLE COST TOTAL
+
*
+
=
*
–
+
(
)
SPLH
Labor Cost %
—
$refs.moreButton?.focus()); }" class="relative flex gap-0.5 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 sm:focus-within:opacity-100 transition flex-shrink-0">
$refs.firstStaffAction?.focus())" :disabled="staffSaving || deletingNow" :data-tip="t('staff_more_actions')" data-tip-pos="top-end" :aria-label="t('staff_more_actions') + ': ' + s.name" :title="t('staff_more_actions') + ': ' + s.name" :aria-expanded="moreOpen" :aria-controls="'staff-actions-' + s.id" class="p-1.5 text-ink-400 hover:text-accent-600 hover:bg-accent-50 rounded disabled:opacity-40 disabled:cursor-wait">
*
–
+
(
)
*
0 && (!_recipeById.get(editingSale.recipe_id) || Number(editingSale.unit_price) !== effectiveSellPrice(_recipeById.get(editingSale.recipe_id))))" :aria-label="t('sale_recipe')" class="w-full min-h-11 px-3 py-2.5 bg-white border border-ink-300 rounded-lg">
--
(
)
−
+
·
0 && (!_recipeById.get(editingSale.recipe_id) || Number(editingSale.unit_price) !== effectiveSellPrice(_recipeById.get(editingSale.recipe_id))))" :aria-label="t('sale_recipe')" class="w-full min-h-11 px-2 py-1.5 bg-white border border-ink-300 rounded text-xs">
--
新
×
×
←
×
×
hr ×
hr ×
×
×
1 ? 1 : 0); showPurchaseList = false" class="px-2 py-1 text-[0.6875rem] gk-primary-btn rounded font-medium whitespace-nowrap" x-text="t('btn_received')">
×
$
r.id === tip.action.recipeId)); if (tip.action.ingredientId) editIngredient(ingredients.find(i => i.id === tip.action.ingredientId)); if (tip.action.anchor) $nextTick(() => scrollToAnchor(tip.action.anchor)); }" class="ml-0 sm:ml-4 inline-flex text-xs px-2.5 py-1 rounded-md bg-rose-600 hover:bg-rose-700 text-white transition flex-shrink-0 font-medium" x-text="t('health_check_action_btn')">
$
→
$
(
+$
)
→
/
·
scrollToAnchor(item.anchor))" class="p-2.5 rounded-lg border text-left transition hover:shadow-card" :class="{ 'bg-rose-50 border-rose-200 hover:border-rose-300': item.severity === 'error', 'bg-amber-50 border-amber-200 hover:border-amber-300': item.severity === 'warn', 'bg-sage-50 border-sage-200 hover:border-sage-300': item.severity === 'ok', 'bg-ink-50 border-ink-200 hover:border-ink-300': item.severity === 'neutral' }">
→
−
−
=
−
→
‹
›
—
—
—
—
0
0
hr
/
·
·
PRO
PRO
PRO
PRO
PRO
‹
›
PRO
PRO
$refs.mobileMoreButton?.focus()); }">
$refs.mobileMoreButton?.focus())" class="sm:hidden fixed inset-0 z-[39] bg-ink-900/50" aria-hidden="true">
scrollToAnchor('ingredients-workspace'))" :class="activeTab === 'ingredients' ? 'text-accent-700' : 'text-ink-500'" class="flex-1 min-w-0 flex flex-col items-center gap-0.5 px-1 py-2 text-[0.625rem] font-medium transition">
focusMobileToolsFirst($refs.mobileMoreMenu))" :class="['staff', 'expenses', 'records', 'analytics'].includes(activeTab) ? 'text-accent-700' : 'text-ink-500'" :aria-expanded="mobileMoreOpen" aria-haspopup="menu" class="flex-1 min-w-0 flex flex-col items-center gap-0.5 px-1 py-2 text-[0.625rem] font-medium transition">
/
·
$refs.conciergeInput?.focus())" type="button" class="px-3 py-1.5 rounded-lg border border-ink-200 dark:border-ink-700 text-xs text-ink-700 dark:text-ink-200 hover:bg-ink-50 dark:hover:bg-ink-800" x-text="t('voice_redo')">
:
·
·
—
—
—
—
% ·
→
ESC
:
—
—
openUpgradeModal())" class="mt-2 w-full px-4 py-2 text-sm font-medium rounded-lg bg-amber-500 hover:bg-amber-600 text-white transition flex items-center justify-center gap-2">
(
chars)
⟳
(
/
)
/
(
/
)
$
(
)
⟳
AI
AI
it._selected = $event.target.checked)" class="w-4 h-4">
AI
*
→
PRO
#
PRO
×
PRO
×
·
⌘K
Ctrl+K
?
Esc
↵
%
:
:
(
)
1.
2.
3.
1
2
3
·
:
:
:
:
·
:
|
:
|
:
:
①
②
③
④
⑤
⑥
:
·
·
·
·
·
·
·
: