@hbslovely/baby-feeding 2026.7.2 → 2026.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ import { CommonModule, DecimalPipe } from '@angular/common';
6
6
  import { ActivatedRoute } from '@angular/router';
7
7
  import { map, catchError, tap, switchMap, mergeMap, scan, takeLast, startWith, finalize, concatMap } from 'rxjs/operators';
8
8
  import { throwError, of, from, Subject, interval, firstValueFrom, forkJoin } from 'rxjs';
9
- import { HttpClient, HttpHeaders } from '@angular/common/http';
9
+ import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
10
10
  import * as i1 from '@angular/forms';
11
11
  import { FormsModule } from '@angular/forms';
12
12
  import { DomSanitizer } from '@angular/platform-browser';
@@ -19,6 +19,9 @@ const DEFAULT_FEEDING_CONFIG = {
19
19
  googleClientId: '',
20
20
  enableExplorer: false,
21
21
  appsScriptDirect: false,
22
+ hfInferenceUrl: '/api/hf-chat',
23
+ hfApiToken: '',
24
+ hfModel: 'mistralai/Mistral-7B-Instruct-v0.3',
22
25
  };
23
26
  const FEEDING_CONFIG_TOKEN = new InjectionToken('FEEDING_CONFIG', {
24
27
  providedIn: 'root',
@@ -14529,9 +14532,13 @@ class HeroHeaderComponent {
14529
14532
  this.weightLabel = input(null, ...(ngDevMode ? [{ debugName: "weightLabel" }] : /* istanbul ignore next */ []));
14530
14533
  this.isAnyLoading = input(false, ...(ngDevMode ? [{ debugName: "isAnyLoading" }] : /* istanbul ignore next */ []));
14531
14534
  this.showRefresh = input(true, ...(ngDevMode ? [{ debugName: "showRefresh" }] : /* istanbul ignore next */ []));
14535
+ /** Hiện/ẩn nút mở trợ lý chat (mặc định hiện). */
14536
+ this.showChat = input(true, ...(ngDevMode ? [{ debugName: "showChat" }] : /* istanbul ignore next */ []));
14532
14537
  this.refresh = output();
14533
14538
  /** Hamburger trên hero → mở float menu (xử lý ở parent). */
14534
14539
  this.openMenu = output();
14540
+ /** Nút chat trên hero → mở subroute trợ lý AI (xử lý ở parent). */
14541
+ this.openChat = output();
14535
14542
  }
14536
14543
  get genderEmoji() {
14537
14544
  const g = this.profile().gender;
@@ -14554,12 +14561,12 @@ class HeroHeaderComponent {
14554
14561
  return parts.join(' ');
14555
14562
  }
14556
14563
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HeroHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14557
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: HeroHeaderComponent, isStandalone: true, selector: "app-hero-header", inputs: { profile: { classPropertyName: "profile", publicName: "profile", isSignal: true, isRequired: true, transformFunction: null }, age: { classPropertyName: "age", publicName: "age", isSignal: true, isRequired: true, transformFunction: null }, user: { classPropertyName: "user", publicName: "user", isSignal: true, isRequired: true, transformFunction: null }, weightLabel: { classPropertyName: "weightLabel", publicName: "weightLabel", isSignal: true, isRequired: false, transformFunction: null }, isAnyLoading: { classPropertyName: "isAnyLoading", publicName: "isAnyLoading", isSignal: true, isRequired: false, transformFunction: null }, showRefresh: { classPropertyName: "showRefresh", publicName: "showRefresh", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { refresh: "refresh", openMenu: "openMenu" }, ngImport: i0, template: "<div class=\"hero-header\">\n <!-- \u2500\u2500 ROW A: Identity \u2500\u2500 -->\n <div class=\"hero-header__identity\">\n <!-- Avatar -->\n <div class=\"hero-header__avatar\" aria-hidden=\"true\">\n {{ genderEmoji }}\n </div>\n\n <!-- Name + meta -->\n <div class=\"hero-header__info\">\n <div class=\"hero-header__name-row\">\n <h1 class=\"hero-header__name\">{{ profile().babyName }}</h1>\n <span class=\"hero-header__age-chip\">{{ ageChip }}</span>\n </div>\n <p class=\"hero-header__meta\">\n <span>{{ age().weeks }} tu\u1EA7n</span>\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span>{{ profile().birthDate | date: 'dd/MM/yyyy' }}</span>\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span>{{ user() }}</span>\n @if (weightLabel()) {\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"hero-header__weight\">\n <i class=\"pi pi-heart-fill\" aria-hidden=\"true\"></i>\n {{ weightLabel() }}\n </span>\n }\n </p>\n </div>\n\n <!-- Actions -->\n <div class=\"hero-header__actions\">\n <!-- Activity log is projected via ng-content -->\n <ng-content select=\"[slot=activity-log]\"></ng-content>\n\n @if (showRefresh()) {\n <button\n type=\"button\"\n class=\"hero-header__icon-btn\"\n (click)=\"refresh.emit()\"\n [disabled]=\"isAnyLoading()\"\n [title]=\"isAnyLoading() ? '\u0110ang t\u1EA3i\u2026' : 'T\u1EA3i l\u1EA1i'\"\n aria-label=\"T\u1EA3i l\u1EA1i d\u1EEF li\u1EC7u\"\n >\n <i class=\"pi pi-refresh\" [class.spin]=\"isAnyLoading()\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <!-- Float menu trigger (hamburger) -->\n <button\n type=\"button\"\n class=\"hero-header__icon-btn\"\n (click)=\"openMenu.emit()\"\n title=\"Menu\"\n aria-label=\"Menu\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n</div>\n", styles: [".hero-header{padding:12px 16px 10px}.hero-header__identity{display:flex;align-items:center;gap:10px}.hero-header__avatar{width:44px;height:44px;border-radius:14px;background:var(--primary);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;border:2px solid rgba(91,108,255,.25)}.hero-header__info{flex:1;min-width:0}.hero-header__name-row{display:flex;align-items:center;gap:7px;margin-bottom:3px}.hero-header__name{font-size:18px;font-weight:700;color:var(--text);letter-spacing:-.3px;white-space:nowrap;margin:0;line-height:1.2}.hero-header__age-chip{padding:2px 8px;border-radius:20px;background:var(--primary);color:#fff;font-size:11px;font-weight:600;white-space:nowrap;flex-shrink:0}.hero-header__meta{display:flex;gap:4px;align-items:center;overflow:hidden;white-space:nowrap;margin:0;font-size:10px;color:var(--muted)}.hero-header__dot{color:var(--muted-2);font-size:9px}.hero-header__weight{display:inline-flex;align-items:center;gap:3px}.hero-header__weight .pi{font-size:9px;color:var(--accent)}.hero-header__actions{display:flex;gap:5px;align-items:center;flex-shrink:0}.hero-header__icon-btn{width:34px;height:34px;border-radius:10px;background:#5b6cff0f;border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--muted);cursor:pointer;transition:background .15s,color .15s;list-style:none}.hero-header__icon-btn:hover:not([disabled]){background:#5b6cff1f;color:var(--primary)}.hero-header__icon-btn[disabled]{opacity:.45;cursor:not-allowed}.hero-header__icon-btn .spin{animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.hero-header__menu{position:relative}.hero-header__menu-trigger::-webkit-details-marker{display:none}.hero-header__menu-panel{position:absolute;top:calc(100% + 6px);right:0;z-index:100;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:4px;min-width:190px;box-shadow:0 4px 16px #0f172a1f}.hero-header__menu-item{display:flex;align-items:center;gap:9px;width:100%;padding:9px 11px;border-radius:8px;font-size:13px;font-weight:500;color:var(--text);background:transparent;border:none;cursor:pointer;text-align:left;transition:background .12s}.hero-header__menu-item .pi{font-size:14px;color:var(--muted);width:16px;text-align:center}.hero-header__menu-item:hover{background:var(--primary-soft);color:var(--primary)}.hero-header__menu-item:hover .pi{color:var(--primary)}.hero-header__menu-item--danger,.hero-header__menu-item--danger .pi{color:var(--rose)}.hero-header__menu-item--danger:hover{background:var(--rose-soft);color:var(--rose)}.hero-header__menu-divider{border:none;border-top:1px solid var(--border);margin:3px 8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
14564
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: HeroHeaderComponent, isStandalone: true, selector: "app-hero-header", inputs: { profile: { classPropertyName: "profile", publicName: "profile", isSignal: true, isRequired: true, transformFunction: null }, age: { classPropertyName: "age", publicName: "age", isSignal: true, isRequired: true, transformFunction: null }, user: { classPropertyName: "user", publicName: "user", isSignal: true, isRequired: true, transformFunction: null }, weightLabel: { classPropertyName: "weightLabel", publicName: "weightLabel", isSignal: true, isRequired: false, transformFunction: null }, isAnyLoading: { classPropertyName: "isAnyLoading", publicName: "isAnyLoading", isSignal: true, isRequired: false, transformFunction: null }, showRefresh: { classPropertyName: "showRefresh", publicName: "showRefresh", isSignal: true, isRequired: false, transformFunction: null }, showChat: { classPropertyName: "showChat", publicName: "showChat", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { refresh: "refresh", openMenu: "openMenu", openChat: "openChat" }, ngImport: i0, template: "<div class=\"hero-header\">\n <!-- \u2500\u2500 ROW A: Identity \u2500\u2500 -->\n <div class=\"hero-header__identity\">\n <!-- Avatar -->\n <div class=\"hero-header__avatar\" aria-hidden=\"true\">\n {{ genderEmoji }}\n </div>\n\n <!-- Name + meta -->\n <div class=\"hero-header__info\">\n <div class=\"hero-header__name-row\">\n <h1 class=\"hero-header__name\">{{ profile().babyName }}</h1>\n <span class=\"hero-header__age-chip\">{{ ageChip }}</span>\n </div>\n <p class=\"hero-header__meta\">\n <span>{{ age().weeks }} tu\u1EA7n</span>\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span>{{ profile().birthDate | date: 'dd/MM/yyyy' }}</span>\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span>{{ user() }}</span>\n @if (weightLabel()) {\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"hero-header__weight\">\n <i class=\"pi pi-heart-fill\" aria-hidden=\"true\"></i>\n {{ weightLabel() }}\n </span>\n }\n </p>\n </div>\n\n <!-- Actions -->\n <div class=\"hero-header__actions\">\n <!-- Activity log is projected via ng-content -->\n <ng-content select=\"[slot=activity-log]\"></ng-content>\n\n @if (showRefresh()) {\n <button\n type=\"button\"\n class=\"hero-header__icon-btn\"\n (click)=\"refresh.emit()\"\n [disabled]=\"isAnyLoading()\"\n [title]=\"isAnyLoading() ? '\u0110ang t\u1EA3i\u2026' : 'T\u1EA3i l\u1EA1i'\"\n aria-label=\"T\u1EA3i l\u1EA1i d\u1EEF li\u1EC7u\"\n >\n <i class=\"pi pi-refresh\" [class.spin]=\"isAnyLoading()\" aria-hidden=\"true\"></i>\n </button>\n }\n\n @if (showChat()) {\n <button\n type=\"button\"\n class=\"hero-header__icon-btn hero-header__icon-btn--chat\"\n (click)=\"openChat.emit()\"\n title=\"Tr\u1EE3 l\u00FD AI\"\n aria-label=\"M\u1EDF tr\u1EE3 l\u00FD AI\"\n >\n <i class=\"pi pi-comments\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <!-- Float menu trigger (hamburger) -->\n <button\n type=\"button\"\n class=\"hero-header__icon-btn\"\n (click)=\"openMenu.emit()\"\n title=\"Menu\"\n aria-label=\"Menu\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n</div>\n", styles: [".hero-header{padding:12px 16px 10px}.hero-header__identity{display:flex;align-items:center;gap:10px}.hero-header__avatar{width:44px;height:44px;border-radius:14px;background:var(--primary);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;border:2px solid rgba(91,108,255,.25)}.hero-header__info{flex:1;min-width:0}.hero-header__name-row{display:flex;align-items:center;gap:7px;margin-bottom:3px}.hero-header__name{font-size:18px;font-weight:700;color:var(--text);letter-spacing:-.3px;white-space:nowrap;margin:0;line-height:1.2}.hero-header__age-chip{padding:2px 8px;border-radius:20px;background:var(--primary);color:#fff;font-size:11px;font-weight:600;white-space:nowrap;flex-shrink:0}.hero-header__meta{display:flex;gap:4px;align-items:center;overflow:hidden;white-space:nowrap;margin:0;font-size:10px;color:var(--muted)}.hero-header__dot{color:var(--muted-2);font-size:9px}.hero-header__weight{display:inline-flex;align-items:center;gap:3px}.hero-header__weight .pi{font-size:9px;color:var(--accent)}.hero-header__actions{display:flex;gap:5px;align-items:center;flex-shrink:0}.hero-header__icon-btn{width:34px;height:34px;border-radius:10px;background:#5b6cff0f;border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--muted);cursor:pointer;transition:background .15s,color .15s;list-style:none}.hero-header__icon-btn:hover:not([disabled]){background:#5b6cff1f;color:var(--primary)}.hero-header__icon-btn[disabled]{opacity:.45;cursor:not-allowed}.hero-header__icon-btn .spin{animation:spin .8s linear infinite}.hero-header__icon-btn--chat{background:var(--accent-soft);border-color:transparent;color:var(--accent)}.hero-header__icon-btn--chat:hover:not([disabled]){background:color-mix(in srgb,var(--accent-soft) 70%,var(--accent) 10%);color:var(--accent)}@keyframes spin{to{transform:rotate(360deg)}}.hero-header__menu{position:relative}.hero-header__menu-trigger::-webkit-details-marker{display:none}.hero-header__menu-panel{position:absolute;top:calc(100% + 6px);right:0;z-index:100;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:4px;min-width:190px;box-shadow:0 4px 16px #0f172a1f}.hero-header__menu-item{display:flex;align-items:center;gap:9px;width:100%;padding:9px 11px;border-radius:8px;font-size:13px;font-weight:500;color:var(--text);background:transparent;border:none;cursor:pointer;text-align:left;transition:background .12s}.hero-header__menu-item .pi{font-size:14px;color:var(--muted);width:16px;text-align:center}.hero-header__menu-item:hover{background:var(--primary-soft);color:var(--primary)}.hero-header__menu-item:hover .pi{color:var(--primary)}.hero-header__menu-item--danger,.hero-header__menu-item--danger .pi{color:var(--rose)}.hero-header__menu-item--danger:hover{background:var(--rose-soft);color:var(--rose)}.hero-header__menu-divider{border:none;border-top:1px solid var(--border);margin:3px 8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
14558
14565
  }
14559
14566
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HeroHeaderComponent, decorators: [{
14560
14567
  type: Component,
14561
- args: [{ selector: 'app-hero-header', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"hero-header\">\n <!-- \u2500\u2500 ROW A: Identity \u2500\u2500 -->\n <div class=\"hero-header__identity\">\n <!-- Avatar -->\n <div class=\"hero-header__avatar\" aria-hidden=\"true\">\n {{ genderEmoji }}\n </div>\n\n <!-- Name + meta -->\n <div class=\"hero-header__info\">\n <div class=\"hero-header__name-row\">\n <h1 class=\"hero-header__name\">{{ profile().babyName }}</h1>\n <span class=\"hero-header__age-chip\">{{ ageChip }}</span>\n </div>\n <p class=\"hero-header__meta\">\n <span>{{ age().weeks }} tu\u1EA7n</span>\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span>{{ profile().birthDate | date: 'dd/MM/yyyy' }}</span>\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span>{{ user() }}</span>\n @if (weightLabel()) {\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"hero-header__weight\">\n <i class=\"pi pi-heart-fill\" aria-hidden=\"true\"></i>\n {{ weightLabel() }}\n </span>\n }\n </p>\n </div>\n\n <!-- Actions -->\n <div class=\"hero-header__actions\">\n <!-- Activity log is projected via ng-content -->\n <ng-content select=\"[slot=activity-log]\"></ng-content>\n\n @if (showRefresh()) {\n <button\n type=\"button\"\n class=\"hero-header__icon-btn\"\n (click)=\"refresh.emit()\"\n [disabled]=\"isAnyLoading()\"\n [title]=\"isAnyLoading() ? '\u0110ang t\u1EA3i\u2026' : 'T\u1EA3i l\u1EA1i'\"\n aria-label=\"T\u1EA3i l\u1EA1i d\u1EEF li\u1EC7u\"\n >\n <i class=\"pi pi-refresh\" [class.spin]=\"isAnyLoading()\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <!-- Float menu trigger (hamburger) -->\n <button\n type=\"button\"\n class=\"hero-header__icon-btn\"\n (click)=\"openMenu.emit()\"\n title=\"Menu\"\n aria-label=\"Menu\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n</div>\n", styles: [".hero-header{padding:12px 16px 10px}.hero-header__identity{display:flex;align-items:center;gap:10px}.hero-header__avatar{width:44px;height:44px;border-radius:14px;background:var(--primary);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;border:2px solid rgba(91,108,255,.25)}.hero-header__info{flex:1;min-width:0}.hero-header__name-row{display:flex;align-items:center;gap:7px;margin-bottom:3px}.hero-header__name{font-size:18px;font-weight:700;color:var(--text);letter-spacing:-.3px;white-space:nowrap;margin:0;line-height:1.2}.hero-header__age-chip{padding:2px 8px;border-radius:20px;background:var(--primary);color:#fff;font-size:11px;font-weight:600;white-space:nowrap;flex-shrink:0}.hero-header__meta{display:flex;gap:4px;align-items:center;overflow:hidden;white-space:nowrap;margin:0;font-size:10px;color:var(--muted)}.hero-header__dot{color:var(--muted-2);font-size:9px}.hero-header__weight{display:inline-flex;align-items:center;gap:3px}.hero-header__weight .pi{font-size:9px;color:var(--accent)}.hero-header__actions{display:flex;gap:5px;align-items:center;flex-shrink:0}.hero-header__icon-btn{width:34px;height:34px;border-radius:10px;background:#5b6cff0f;border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--muted);cursor:pointer;transition:background .15s,color .15s;list-style:none}.hero-header__icon-btn:hover:not([disabled]){background:#5b6cff1f;color:var(--primary)}.hero-header__icon-btn[disabled]{opacity:.45;cursor:not-allowed}.hero-header__icon-btn .spin{animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.hero-header__menu{position:relative}.hero-header__menu-trigger::-webkit-details-marker{display:none}.hero-header__menu-panel{position:absolute;top:calc(100% + 6px);right:0;z-index:100;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:4px;min-width:190px;box-shadow:0 4px 16px #0f172a1f}.hero-header__menu-item{display:flex;align-items:center;gap:9px;width:100%;padding:9px 11px;border-radius:8px;font-size:13px;font-weight:500;color:var(--text);background:transparent;border:none;cursor:pointer;text-align:left;transition:background .12s}.hero-header__menu-item .pi{font-size:14px;color:var(--muted);width:16px;text-align:center}.hero-header__menu-item:hover{background:var(--primary-soft);color:var(--primary)}.hero-header__menu-item:hover .pi{color:var(--primary)}.hero-header__menu-item--danger,.hero-header__menu-item--danger .pi{color:var(--rose)}.hero-header__menu-item--danger:hover{background:var(--rose-soft);color:var(--rose)}.hero-header__menu-divider{border:none;border-top:1px solid var(--border);margin:3px 8px}\n"] }]
14562
- }], propDecorators: { profile: [{ type: i0.Input, args: [{ isSignal: true, alias: "profile", required: true }] }], age: [{ type: i0.Input, args: [{ isSignal: true, alias: "age", required: true }] }], user: [{ type: i0.Input, args: [{ isSignal: true, alias: "user", required: true }] }], weightLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "weightLabel", required: false }] }], isAnyLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isAnyLoading", required: false }] }], showRefresh: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRefresh", required: false }] }], refresh: [{ type: i0.Output, args: ["refresh"] }], openMenu: [{ type: i0.Output, args: ["openMenu"] }] } });
14568
+ args: [{ selector: 'app-hero-header', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"hero-header\">\n <!-- \u2500\u2500 ROW A: Identity \u2500\u2500 -->\n <div class=\"hero-header__identity\">\n <!-- Avatar -->\n <div class=\"hero-header__avatar\" aria-hidden=\"true\">\n {{ genderEmoji }}\n </div>\n\n <!-- Name + meta -->\n <div class=\"hero-header__info\">\n <div class=\"hero-header__name-row\">\n <h1 class=\"hero-header__name\">{{ profile().babyName }}</h1>\n <span class=\"hero-header__age-chip\">{{ ageChip }}</span>\n </div>\n <p class=\"hero-header__meta\">\n <span>{{ age().weeks }} tu\u1EA7n</span>\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span>{{ profile().birthDate | date: 'dd/MM/yyyy' }}</span>\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span>{{ user() }}</span>\n @if (weightLabel()) {\n <span class=\"hero-header__dot\" aria-hidden=\"true\">\u00B7</span>\n <span class=\"hero-header__weight\">\n <i class=\"pi pi-heart-fill\" aria-hidden=\"true\"></i>\n {{ weightLabel() }}\n </span>\n }\n </p>\n </div>\n\n <!-- Actions -->\n <div class=\"hero-header__actions\">\n <!-- Activity log is projected via ng-content -->\n <ng-content select=\"[slot=activity-log]\"></ng-content>\n\n @if (showRefresh()) {\n <button\n type=\"button\"\n class=\"hero-header__icon-btn\"\n (click)=\"refresh.emit()\"\n [disabled]=\"isAnyLoading()\"\n [title]=\"isAnyLoading() ? '\u0110ang t\u1EA3i\u2026' : 'T\u1EA3i l\u1EA1i'\"\n aria-label=\"T\u1EA3i l\u1EA1i d\u1EEF li\u1EC7u\"\n >\n <i class=\"pi pi-refresh\" [class.spin]=\"isAnyLoading()\" aria-hidden=\"true\"></i>\n </button>\n }\n\n @if (showChat()) {\n <button\n type=\"button\"\n class=\"hero-header__icon-btn hero-header__icon-btn--chat\"\n (click)=\"openChat.emit()\"\n title=\"Tr\u1EE3 l\u00FD AI\"\n aria-label=\"M\u1EDF tr\u1EE3 l\u00FD AI\"\n >\n <i class=\"pi pi-comments\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <!-- Float menu trigger (hamburger) -->\n <button\n type=\"button\"\n class=\"hero-header__icon-btn\"\n (click)=\"openMenu.emit()\"\n title=\"Menu\"\n aria-label=\"Menu\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n</div>\n", styles: [".hero-header{padding:12px 16px 10px}.hero-header__identity{display:flex;align-items:center;gap:10px}.hero-header__avatar{width:44px;height:44px;border-radius:14px;background:var(--primary);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;border:2px solid rgba(91,108,255,.25)}.hero-header__info{flex:1;min-width:0}.hero-header__name-row{display:flex;align-items:center;gap:7px;margin-bottom:3px}.hero-header__name{font-size:18px;font-weight:700;color:var(--text);letter-spacing:-.3px;white-space:nowrap;margin:0;line-height:1.2}.hero-header__age-chip{padding:2px 8px;border-radius:20px;background:var(--primary);color:#fff;font-size:11px;font-weight:600;white-space:nowrap;flex-shrink:0}.hero-header__meta{display:flex;gap:4px;align-items:center;overflow:hidden;white-space:nowrap;margin:0;font-size:10px;color:var(--muted)}.hero-header__dot{color:var(--muted-2);font-size:9px}.hero-header__weight{display:inline-flex;align-items:center;gap:3px}.hero-header__weight .pi{font-size:9px;color:var(--accent)}.hero-header__actions{display:flex;gap:5px;align-items:center;flex-shrink:0}.hero-header__icon-btn{width:34px;height:34px;border-radius:10px;background:#5b6cff0f;border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:14px;color:var(--muted);cursor:pointer;transition:background .15s,color .15s;list-style:none}.hero-header__icon-btn:hover:not([disabled]){background:#5b6cff1f;color:var(--primary)}.hero-header__icon-btn[disabled]{opacity:.45;cursor:not-allowed}.hero-header__icon-btn .spin{animation:spin .8s linear infinite}.hero-header__icon-btn--chat{background:var(--accent-soft);border-color:transparent;color:var(--accent)}.hero-header__icon-btn--chat:hover:not([disabled]){background:color-mix(in srgb,var(--accent-soft) 70%,var(--accent) 10%);color:var(--accent)}@keyframes spin{to{transform:rotate(360deg)}}.hero-header__menu{position:relative}.hero-header__menu-trigger::-webkit-details-marker{display:none}.hero-header__menu-panel{position:absolute;top:calc(100% + 6px);right:0;z-index:100;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:4px;min-width:190px;box-shadow:0 4px 16px #0f172a1f}.hero-header__menu-item{display:flex;align-items:center;gap:9px;width:100%;padding:9px 11px;border-radius:8px;font-size:13px;font-weight:500;color:var(--text);background:transparent;border:none;cursor:pointer;text-align:left;transition:background .12s}.hero-header__menu-item .pi{font-size:14px;color:var(--muted);width:16px;text-align:center}.hero-header__menu-item:hover{background:var(--primary-soft);color:var(--primary)}.hero-header__menu-item:hover .pi{color:var(--primary)}.hero-header__menu-item--danger,.hero-header__menu-item--danger .pi{color:var(--rose)}.hero-header__menu-item--danger:hover{background:var(--rose-soft);color:var(--rose)}.hero-header__menu-divider{border:none;border-top:1px solid var(--border);margin:3px 8px}\n"] }]
14569
+ }], propDecorators: { profile: [{ type: i0.Input, args: [{ isSignal: true, alias: "profile", required: true }] }], age: [{ type: i0.Input, args: [{ isSignal: true, alias: "age", required: true }] }], user: [{ type: i0.Input, args: [{ isSignal: true, alias: "user", required: true }] }], weightLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "weightLabel", required: false }] }], isAnyLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isAnyLoading", required: false }] }], showRefresh: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRefresh", required: false }] }], showChat: [{ type: i0.Input, args: [{ isSignal: true, alias: "showChat", required: false }] }], refresh: [{ type: i0.Output, args: ["refresh"] }], openMenu: [{ type: i0.Output, args: ["openMenu"] }], openChat: [{ type: i0.Output, args: ["openChat"] }] } });
14563
14570
 
14564
14571
  class HeroStatsStripComponent {
14565
14572
  constructor() {
@@ -14832,6 +14839,1210 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
14832
14839
  args: [{ selector: 'app-settings-menu', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<section class=\"sm-root\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Menu\">\n <header class=\"sm-header\">\n <h1 class=\"sm-title\">C\u00E0i \u0111\u1EB7t</h1>\n <span class=\"sm-spacer\"></span>\n <button\n type=\"button\"\n class=\"sm-close\"\n (click)=\"close.emit()\"\n aria-label=\"\u0110\u00F3ng\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n </header>\n\n <div class=\"sm-body\">\n <!-- \u2500\u2500 Profile actions \u2500\u2500 -->\n <nav class=\"sm-list\" role=\"menu\">\n <button\n type=\"button\"\n class=\"sm-item\"\n role=\"menuitem\"\n (click)=\"onSelect('edit')\"\n >\n <i class=\"pi pi-pencil sm-item__icon\" aria-hidden=\"true\"></i>\n <span class=\"sm-item__body\">\n <span class=\"sm-item__label\">S\u1EEDa profile b\u00E9</span>\n <span class=\"sm-item__hint\">\u0110\u1ED5i t\u00EAn, ng\u00E0y sinh, gi\u1EDBi t\u00EDnh</span>\n </span>\n </button>\n\n <button\n type=\"button\"\n class=\"sm-item\"\n role=\"menuitem\"\n (click)=\"onSelect('settings')\"\n >\n <i class=\"pi pi-sliders-h sm-item__icon\" aria-hidden=\"true\"></i>\n <span class=\"sm-item__body\">\n <span class=\"sm-item__label\">C\u00E0i \u0111\u1EB7t chung</span>\n <span class=\"sm-item__hint\">C\u1EA3nh b\u00E1o, ng\u01B0\u1EE1ng c\u1EEF, th\u00F4ng b\u00E1o\u2026</span>\n </span>\n </button>\n </nav>\n\n <hr class=\"sm-divider\" />\n\n <!-- \u2500\u2500 Subroute entries \u2500\u2500 -->\n <nav class=\"sm-list\" role=\"menu\">\n <button\n type=\"button\"\n class=\"sm-item\"\n role=\"menuitem\"\n (click)=\"onSelect('mom')\"\n >\n <i class=\"pi pi-sun sm-item__icon\" aria-hidden=\"true\"></i>\n <span class=\"sm-item__body\">\n <span class=\"sm-item__label\">M\u1EB9</span>\n <span class=\"sm-item__hint\">S\u1EE9c kho\u1EBB & dinh d\u01B0\u1EE1ng m\u1EB9</span>\n </span>\n <i class=\"pi pi-chevron-right sm-item__chev\" aria-hidden=\"true\"></i>\n </button>\n\n @if (showDocuments()) {\n <button\n type=\"button\"\n class=\"sm-item\"\n role=\"menuitem\"\n (click)=\"onSelect('documents')\"\n >\n <i class=\"pi pi-folder sm-item__icon\" aria-hidden=\"true\"></i>\n <span class=\"sm-item__body\">\n <span class=\"sm-item__label\">Explorer</span>\n <span class=\"sm-item__hint\">Kho t\u00E0i li\u1EC7u c\u1EE7a b\u00E9</span>\n </span>\n <i class=\"pi pi-chevron-right sm-item__chev\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"sm-item\"\n role=\"menuitem\"\n (click)=\"onSelect('notifications')\"\n >\n <i class=\"pi pi-bell sm-item__icon\" aria-hidden=\"true\"></i>\n <span class=\"sm-item__body\">\n <span class=\"sm-item__label\">Th\u00F4ng b\u00E1o</span>\n <span class=\"sm-item__hint\">M\u1EDBi, \u0111\u00E3 \u0111\u1ECDc & c\u0169 h\u01A1n</span>\n </span>\n @if (unreadCount() > 0) {\n <span class=\"sm-item__badge\">{{ unreadCount() }}</span>\n } @else {\n <i class=\"pi pi-chevron-right sm-item__chev\" aria-hidden=\"true\"></i>\n }\n </button>\n </nav>\n\n <!-- \u2500\u2500 About inline \u2500\u2500 -->\n <section class=\"sm-about\" aria-label=\"About\">\n <div class=\"sm-about__icon\" aria-hidden=\"true\">\n <i class=\"pi pi-info-circle\"></i>\n </div>\n <div class=\"sm-about__body\">\n <span class=\"sm-about__name\">{{ appName() }}</span>\n <span class=\"sm-about__version\">Phi\u00EAn b\u1EA3n {{ appVersion() }}</span>\n </div>\n <span class=\"sm-about__tag\">App</span>\n </section>\n\n <!-- \u2500\u2500 Delete (bottom, danger) \u2500\u2500 -->\n <hr class=\"sm-divider sm-divider--strong\" />\n <nav class=\"sm-list sm-bottom\" role=\"menu\">\n <button\n type=\"button\"\n class=\"sm-item sm-item--danger\"\n role=\"menuitem\"\n (click)=\"onSelect('delete')\"\n >\n <i class=\"pi pi-trash sm-item__icon\" aria-hidden=\"true\"></i>\n <span class=\"sm-item__body\">\n <span class=\"sm-item__label\">Xo\u00E1 profile</span>\n <span class=\"sm-item__hint\">G\u1EE1 h\u1ED3 s\u01A1 b\u00E9 kh\u1ECFi thi\u1EBFt b\u1ECB n\u00E0y</span>\n </span>\n </button>\n </nav>\n </div>\n</section>\n", styles: ["@charset \"UTF-8\";:host{--bg: #f6f7fb;--surface: #ffffff;--border: #e6e8ef;--primary: #5b6cff;--primary-soft: #eef0ff;--accent: #ff5c8a;--accent-soft: #ffe7ef;--rose: #ef4444;--rose-soft: #fee2e2;--text: #0f172a;--muted: #475569;--muted-2: #94a3b8;position:fixed;inset:0;z-index:210;background:var(--bg);display:flex;flex-direction:column;color:var(--text);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;animation:sm-slide-in .22s cubic-bezier(.22,1,.36,1)}@keyframes sm-slide-in{0%{transform:translate(8px);opacity:0}to{transform:translate(0);opacity:1}}.sm-root{display:flex;flex-direction:column;flex:1;min-height:0}.sm-header{flex-shrink:0;display:flex;align-items:center;gap:8px;padding:8px 12px;padding-top:calc(8px + env(safe-area-inset-top,0px));background:var(--surface);border-bottom:1px solid var(--border)}.sm-title{margin:0;font-size:17px;font-weight:700;color:var(--text)}.sm-spacer{flex:1}.sm-close{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:9px;border:none;background:transparent;color:var(--muted);font-size:15px;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s,color .15s}.sm-close:hover{background:var(--primary-soft);color:var(--primary)}.sm-body{flex:1;min-height:0;overflow:auto;-webkit-overflow-scrolling:touch;padding:8px 0 calc(24px + env(safe-area-inset-bottom,0px))}.sm-list{display:flex;flex-direction:column;background:var(--surface)}.sm-divider{border:none;height:1px;background:var(--border);margin:0}.sm-divider--strong{height:8px;background:var(--bg)}.sm-item{display:flex;align-items:center;gap:14px;width:100%;padding:12px 16px;border:none;background:transparent;text-align:left;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background .15s}.sm-item:hover{background:var(--primary-soft)}.sm-item:active{background:color-mix(in srgb,var(--primary-soft) 55%,var(--surface))}.sm-item__icon{flex-shrink:0;width:22px;text-align:center;font-size:16px;color:var(--muted)}.sm-item__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.sm-item__label{font-size:15px;font-weight:600;color:var(--text)}.sm-item__hint{font-size:12px;color:var(--muted-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sm-item__chev{flex-shrink:0;font-size:13px;color:var(--muted-2)}.sm-item__badge{flex-shrink:0;min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:var(--accent);color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center}.sm-about{display:flex;align-items:center;gap:12px;margin:12px 12px 4px;padding:12px 14px;border-radius:14px;background:var(--primary-soft);border:1px solid color-mix(in srgb,var(--primary) 14%,transparent)}.sm-about__icon{flex-shrink:0;width:38px;height:38px;border-radius:999px;background:var(--surface);color:var(--primary);font-size:18px;display:flex;align-items:center;justify-content:center}.sm-about__body{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.sm-about__name{font-size:15px;font-weight:700;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sm-about__version{font-size:12px;color:var(--muted)}.sm-about__tag{flex-shrink:0;font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--primary);background:var(--surface);padding:3px 8px;border-radius:999px}.sm-bottom{background:var(--surface)}.sm-item--danger:hover{background:var(--rose-soft)}.sm-item--danger:active{background:color-mix(in srgb,var(--rose-soft) 55%,var(--surface))}.sm-item--danger .sm-item__icon{color:var(--rose)}.sm-item--danger .sm-item__label{color:var(--rose);font-weight:600}\n"] }]
14833
14840
  }], propDecorators: { appName: [{ type: i0.Input, args: [{ isSignal: true, alias: "appName", required: false }] }], appVersion: [{ type: i0.Input, args: [{ isSignal: true, alias: "appVersion", required: false }] }], showDocuments: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDocuments", required: false }] }], unreadCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "unreadCount", required: false }] }], close: [{ type: i0.Output, args: ["close"] }], select: [{ type: i0.Output, args: ["select"] }] } });
14834
14841
 
14842
+ /**
14843
+ * Khung nhập + suggestion pills ở đáy chat.
14844
+ * - Enter gửi, Shift+Enter xuống dòng.
14845
+ * - Click pill → emit send với text gợi ý.
14846
+ */
14847
+ class ChatComposerComponent {
14848
+ constructor() {
14849
+ this.send = new EventEmitter();
14850
+ this.draft = '';
14851
+ this.suggestions = [
14852
+ 'Thêm cữ bú 80ml lúc 14h',
14853
+ 'Pha sữa 90ml',
14854
+ 'Bé bú hôm nay thế nào?',
14855
+ 'Ghi cân nặng 6.2kg',
14856
+ 'Lịch tiêm kế tiếp',
14857
+ 'Tư vấn tăng cữ sữa',
14858
+ ];
14859
+ }
14860
+ onEnter(ev) {
14861
+ if (ev.shiftKey)
14862
+ return; // xuống dòng
14863
+ ev.preventDefault();
14864
+ this.submit();
14865
+ }
14866
+ submit() {
14867
+ const text = this.draft.trim();
14868
+ if (!text)
14869
+ return;
14870
+ this.send.emit(text);
14871
+ this.draft = '';
14872
+ }
14873
+ emitSend(text) {
14874
+ this.send.emit(text);
14875
+ }
14876
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ChatComposerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14877
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ChatComposerComponent, isStandalone: true, selector: "app-chat-composer", outputs: { send: "send" }, ngImport: i0, template: `
14878
+ <div class="cc-suggestions">
14879
+ @for (s of suggestions; track s) {
14880
+ <button type="button" class="cc-pill" (click)="emitSend(s)">{{ s }}</button>
14881
+ }
14882
+ </div>
14883
+ <form class="cc-row" (submit)="$event.preventDefault(); submit()">
14884
+ <textarea
14885
+ class="cc-input"
14886
+ rows="1"
14887
+ [(ngModel)]="draft"
14888
+ name="draft"
14889
+ placeholder="Nhập yêu cầu… vd: thêm cữ bú 80ml lúc 14h"
14890
+ (keydown.enter)="onEnter($event)"
14891
+ aria-label="Nhập yêu cầu cho trợ lý"
14892
+ ></textarea>
14893
+ <button type="submit" class="cc-send" [disabled]="!draft.trim()" aria-label="Gửi">
14894
+ <i class="pi pi-send" aria-hidden="true"></i>
14895
+ </button>
14896
+ </form>
14897
+ `, isInline: true, styles: [":host{display:block;border-top:1px solid var(--border);background:var(--bg);padding:8px 12px calc(10px + env(safe-area-inset-bottom,0px))}.cc-suggestions{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.cc-pill{border:1px solid var(--border);background:var(--surface);color:var(--primary);font-size:11.5px;font-weight:600;padding:5px 9px;border-radius:999px;cursor:pointer;white-space:nowrap;-webkit-tap-highlight-color:transparent}.cc-pill:hover{background:var(--primary-soft);border-color:transparent}.cc-row{display:flex;align-items:flex-end;gap:7px;background:var(--surface);border:1px solid var(--border);border-radius:18px;padding:5px 5px 5px 12px}.cc-input{flex:1;border:none;outline:none;resize:none;background:transparent;font-size:13px;line-height:1.4;color:var(--text);max-height:96px;font-family:inherit;padding:4px 0}.cc-input::placeholder{color:var(--muted-2)}.cc-send{flex-shrink:0;width:32px;height:32px;border-radius:999px;border:none;background:var(--primary);color:#fff;font-size:13px;cursor:pointer;display:flex;align-items:center;justify-content:center}.cc-send:disabled{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
14898
+ }
14899
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ChatComposerComponent, decorators: [{
14900
+ type: Component,
14901
+ args: [{ selector: 'app-chat-composer', standalone: true, imports: [CommonModule, FormsModule], template: `
14902
+ <div class="cc-suggestions">
14903
+ @for (s of suggestions; track s) {
14904
+ <button type="button" class="cc-pill" (click)="emitSend(s)">{{ s }}</button>
14905
+ }
14906
+ </div>
14907
+ <form class="cc-row" (submit)="$event.preventDefault(); submit()">
14908
+ <textarea
14909
+ class="cc-input"
14910
+ rows="1"
14911
+ [(ngModel)]="draft"
14912
+ name="draft"
14913
+ placeholder="Nhập yêu cầu… vd: thêm cữ bú 80ml lúc 14h"
14914
+ (keydown.enter)="onEnter($event)"
14915
+ aria-label="Nhập yêu cầu cho trợ lý"
14916
+ ></textarea>
14917
+ <button type="submit" class="cc-send" [disabled]="!draft.trim()" aria-label="Gửi">
14918
+ <i class="pi pi-send" aria-hidden="true"></i>
14919
+ </button>
14920
+ </form>
14921
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;border-top:1px solid var(--border);background:var(--bg);padding:8px 12px calc(10px + env(safe-area-inset-bottom,0px))}.cc-suggestions{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:8px}.cc-pill{border:1px solid var(--border);background:var(--surface);color:var(--primary);font-size:11.5px;font-weight:600;padding:5px 9px;border-radius:999px;cursor:pointer;white-space:nowrap;-webkit-tap-highlight-color:transparent}.cc-pill:hover{background:var(--primary-soft);border-color:transparent}.cc-row{display:flex;align-items:flex-end;gap:7px;background:var(--surface);border:1px solid var(--border);border-radius:18px;padding:5px 5px 5px 12px}.cc-input{flex:1;border:none;outline:none;resize:none;background:transparent;font-size:13px;line-height:1.4;color:var(--text);max-height:96px;font-family:inherit;padding:4px 0}.cc-input::placeholder{color:var(--muted-2)}.cc-send{flex-shrink:0;width:32px;height:32px;border-radius:999px;border:none;background:var(--primary);color:#fff;font-size:13px;cursor:pointer;display:flex;align-items:center;justify-content:center}.cc-send:disabled{opacity:.4;cursor:not-allowed}\n"] }]
14922
+ }], propDecorators: { send: [{
14923
+ type: Output
14924
+ }] } });
14925
+
14926
+ /**
14927
+ * Render một tin nhắn chat theo `kind`:
14928
+ * - user: bubble phải, nền accent
14929
+ * - text: bubble trái, prose tư vấn
14930
+ * - context: card tóm tắt dữ liệu (greeting)
14931
+ * - pending: thẻ chờ Confirm trước khi thực thi tool (có thể có ô nhập
14932
+ * ngày/giờ nếu model chưa biết — user phải điền trước khi bấm Xác nhận)
14933
+ * - action: thẻ xác nhận đã ghi + nút "Hoàn tác" (cũng cần xác nhận)
14934
+ * - error: callout đỏ
14935
+ */
14936
+ class ChatMessageComponent {
14937
+ constructor() {
14938
+ this.msg = input.required(...(ngDevMode ? [{ debugName: "msg" }] : /* istanbul ignore next */ []));
14939
+ /** Phát khi user bấm "Hoàn tác" — shell sẽ vào chế độ chờ xác nhận hoàn tác. */
14940
+ this.undo = new EventEmitter();
14941
+ /** Phát khi user bấm "Xác nhận" trên thẻ pending — shell sẽ dispatch tool. */
14942
+ this.confirm = new EventEmitter();
14943
+ /** Phát khi user bấm "Huỷ" trên thẻ pending — shell sẽ đánh dấu đã huỷ. */
14944
+ this.cancel = new EventEmitter();
14945
+ /** Phát khi user xác nhận hoàn tác — shell sẽ gọi undo callback thật. */
14946
+ this.confirmUndo = new EventEmitter();
14947
+ /** Phát khi user huỷ ý định hoàn tác — shell sẽ thoát chế độ chờ xác nhận. */
14948
+ this.cancelUndo = new EventEmitter();
14949
+ /** Phát khi user gõ vào ô nhập — shell cập nhật inputDraft. */
14950
+ this.inputChange = new EventEmitter();
14951
+ /** True khi mọi ô nhập required đã có giá trị — dùng để enable nút Xác nhận. */
14952
+ this.pendingReady = computed(() => {
14953
+ const action = this.msg().action;
14954
+ if (!action?.inputs || action.inputs.length === 0)
14955
+ return true;
14956
+ const draft = action.inputDraft ?? {};
14957
+ return action.inputs.every((inp) => !inp.required || (draft[inp.key]?.trim() ?? '').length > 0);
14958
+ }, ...(ngDevMode ? [{ debugName: "pendingReady" }] : /* istanbul ignore next */ []));
14959
+ }
14960
+ inputType(kind) {
14961
+ return kind;
14962
+ }
14963
+ draftValue(key) {
14964
+ return this.msg().action?.inputDraft?.[key] ?? '';
14965
+ }
14966
+ onInputChange(key, event) {
14967
+ const value = event.target.value;
14968
+ this.inputChange.emit({ id: this.msg().id, key, value });
14969
+ }
14970
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ChatMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14971
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ChatMessageComponent, isStandalone: true, selector: "app-chat-message", inputs: { msg: { classPropertyName: "msg", publicName: "msg", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { undo: "undo", confirm: "confirm", cancel: "cancel", confirmUndo: "confirmUndo", cancelUndo: "cancelUndo", inputChange: "inputChange" }, ngImport: i0, template: `
14972
+ @switch (msg().kind) {
14973
+ @case ('user') {
14974
+ <div class="cm-row cm-row--user">
14975
+ <div class="cm-bubble cm-bubble--user">{{ msg().text }}</div>
14976
+ </div>
14977
+ }
14978
+ @case ('text') {
14979
+ <div class="cm-row">
14980
+ <div class="cm-bubble cm-bubble--assistant">{{ msg().text }}</div>
14981
+ <span class="cm-ts">{{ msg().ts }}</span>
14982
+ </div>
14983
+ }
14984
+ @case ('context') {
14985
+ <div class="cm-row">
14986
+ <div class="cm-bubble cm-bubble--assistant cm-bubble--context">{{ msg().text }}</div>
14987
+ <span class="cm-ts">{{ msg().ts }}</span>
14988
+ </div>
14989
+ }
14990
+ @case ('pending') {
14991
+ <div class="cm-row">
14992
+ <div class="cm-action cm-action--pending">
14993
+ <div class="cm-action__head">
14994
+ <span class="cm-chip cm-chip--pending">
14995
+ {{ msg().action?.cancelled ? 'đã huỷ' : 'chờ xác nhận' }}
14996
+ </span>
14997
+ <span class="cm-action__detail">{{ msg().action?.detail }}</span>
14998
+ </div>
14999
+ @if (msg().action?.inputs?.length) {
15000
+ <div class="cm-inputs">
15001
+ @for (inp of msg().action!.inputs!; track inp.key) {
15002
+ <label class="cm-input">
15003
+ <span class="cm-input__label">
15004
+ {{ inp.label }}{{ inp.required ? ' *' : '' }}
15005
+ </span>
15006
+ <input
15007
+ [type]="inputType(inp.kind)"
15008
+ [value]="draftValue(inp.key)"
15009
+ (input)="onInputChange(inp.key, $event)"
15010
+ />
15011
+ </label>
15012
+ }
15013
+ </div>
15014
+ }
15015
+ <div class="cm-action__foot">
15016
+ <code class="cm-action__tool">{{ msg().action?.tool }}</code>
15017
+ @if (msg().action; as action) {
15018
+ @if (!action.cancelled) {
15019
+ <button
15020
+ type="button"
15021
+ class="cm-confirm"
15022
+ [disabled]="!pendingReady()"
15023
+ (click)="confirm.emit(msg().id)"
15024
+ >Xác nhận</button>
15025
+ <button
15026
+ type="button"
15027
+ class="cm-cancel"
15028
+ (click)="cancel.emit(msg().id)"
15029
+ >Huỷ</button>
15030
+ }
15031
+ }
15032
+ </div>
15033
+ </div>
15034
+ <span class="cm-ts">{{ msg().ts }}</span>
15035
+ </div>
15036
+ }
15037
+ @case ('action') {
15038
+ <div class="cm-row">
15039
+ <div class="cm-action">
15040
+ <div class="cm-action__head">
15041
+ <span class="cm-chip" [class.cm-chip--undone]="msg().action?.undone">
15042
+ {{ msg().action?.undone ? 'đã hoàn tác' : 'đã ghi' }}
15043
+ </span>
15044
+ <span class="cm-action__detail">{{ msg().action?.detail }}</span>
15045
+ </div>
15046
+ <div class="cm-action__foot">
15047
+ <code class="cm-action__tool">{{ msg().action?.tool }}</code>
15048
+ @if (msg().action; as action) {
15049
+ @if (!action.undone && !action.undoPending) {
15050
+ <button type="button" class="cm-undo" (click)="undo.emit(msg().id)">Hoàn tác</button>
15051
+ }
15052
+ @if (!action.undone && action.undoPending) {
15053
+ <span class="cm-undo-hint">Xác nhận hoàn tác?</span>
15054
+ <button
15055
+ type="button"
15056
+ class="cm-confirm"
15057
+ (click)="confirmUndo.emit(msg().id)"
15058
+ >Xác nhận</button>
15059
+ <button
15060
+ type="button"
15061
+ class="cm-cancel"
15062
+ (click)="cancelUndo.emit(msg().id)"
15063
+ >Huỷ</button>
15064
+ }
15065
+ }
15066
+ </div>
15067
+ </div>
15068
+ <span class="cm-ts">{{ msg().ts }}</span>
15069
+ </div>
15070
+ }
15071
+ @case ('error') {
15072
+ <div class="cm-row">
15073
+ <div class="cm-error">{{ msg().text }}</div>
15074
+ <span class="cm-ts">{{ msg().ts }}</span>
15075
+ </div>
15076
+ }
15077
+ }
15078
+ `, isInline: true, styles: [":host{display:block}.cm-row{display:flex;flex-direction:column;align-items:flex-start;gap:3px}.cm-row--user{align-items:flex-end}.cm-bubble{max-width:82%;padding:9px 12px;border-radius:14px;font-size:13px;line-height:1.42;white-space:pre-wrap;word-break:break-word}.cm-bubble--user{background:var(--primary);color:#fff;border-bottom-right-radius:4px}.cm-bubble--assistant{background:var(--surface);border:1px solid var(--border);color:var(--text);border-bottom-left-radius:4}.cm-bubble--context{background:var(--primary-soft);border-color:transparent;color:var(--text);font-size:12.5px}.cm-ts{font-size:10px;color:var(--muted-2);padding:0 4px}.cm-action{max-width:88%;background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--mint, #10b981);border-radius:12px;padding:9px 11px;display:flex;flex-direction:column;gap:7px}.cm-action__head{display:flex;align-items:center;gap:7px;flex-wrap:wrap}.cm-action__detail{font-size:12.5px;font-weight:600;color:var(--text)}.cm-action__foot{display:flex;align-items:center;justify-content:space-between;gap:8px}.cm-action__tool{font-size:10.5px;color:var(--muted-2);background:var(--bg);padding:2px 6px;border-radius:5px;font-family:SF Mono,ui-monospace,Menlo,monospace}.cm-chip{font-size:10.5px;font-weight:700;color:var(--mint, #10b981);background:var(--mint-soft, #d1fae5);padding:2px 7px;border-radius:999px;text-transform:uppercase;letter-spacing:.02em}.cm-chip--undone{color:var(--muted);background:var(--bg)}.cm-chip--pending{color:var(--amber, #d97706);background:var(--amber-soft, #fef3c7)}.cm-undo{border:none;background:transparent;color:var(--primary);font-size:11.5px;font-weight:600;cursor:pointer;padding:2px 4px;border-radius:6px}.cm-undo:hover{background:var(--primary-soft)}.cm-confirm{border:none;background:var(--primary);color:#fff;font-size:11.5px;font-weight:600;cursor:pointer;padding:4px 12px;border-radius:6px}.cm-confirm:hover{filter:brightness(1.05)}.cm-cancel{border:1px solid var(--border);background:transparent;color:var(--muted);font-size:11.5px;font-weight:600;cursor:pointer;padding:3px 10px;border-radius:6px}.cm-cancel:hover{background:var(--bg)}.cm-action--pending{border-left-color:var(--amber, #d97706)}.cm-undo-hint{font-size:11.5px;color:var(--amber, #d97706);font-weight:600}.cm-inputs{display:flex;flex-wrap:wrap;gap:8px}.cm-input{display:flex;flex-direction:column;gap:3px;flex:1 1 120px}.cm-input__label{font-size:10.5px;color:var(--muted-2);font-weight:600}.cm-input input{border:1px solid var(--border);border-radius:6px;padding:5px 8px;font-size:12.5px;color:var(--text);background:var(--bg);outline:none}.cm-input input:focus{border-color:var(--primary)}.cm-error{max-width:88%;background:var(--rose-soft, #fee2e2);color:var(--rose, #ef4444);border-left:3px solid var(--rose, #ef4444);border-radius:10px;padding:8px 11px;font-size:12.5px;line-height:1.4}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15079
+ }
15080
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ChatMessageComponent, decorators: [{
15081
+ type: Component,
15082
+ args: [{ selector: 'app-chat-message', standalone: true, imports: [CommonModule], template: `
15083
+ @switch (msg().kind) {
15084
+ @case ('user') {
15085
+ <div class="cm-row cm-row--user">
15086
+ <div class="cm-bubble cm-bubble--user">{{ msg().text }}</div>
15087
+ </div>
15088
+ }
15089
+ @case ('text') {
15090
+ <div class="cm-row">
15091
+ <div class="cm-bubble cm-bubble--assistant">{{ msg().text }}</div>
15092
+ <span class="cm-ts">{{ msg().ts }}</span>
15093
+ </div>
15094
+ }
15095
+ @case ('context') {
15096
+ <div class="cm-row">
15097
+ <div class="cm-bubble cm-bubble--assistant cm-bubble--context">{{ msg().text }}</div>
15098
+ <span class="cm-ts">{{ msg().ts }}</span>
15099
+ </div>
15100
+ }
15101
+ @case ('pending') {
15102
+ <div class="cm-row">
15103
+ <div class="cm-action cm-action--pending">
15104
+ <div class="cm-action__head">
15105
+ <span class="cm-chip cm-chip--pending">
15106
+ {{ msg().action?.cancelled ? 'đã huỷ' : 'chờ xác nhận' }}
15107
+ </span>
15108
+ <span class="cm-action__detail">{{ msg().action?.detail }}</span>
15109
+ </div>
15110
+ @if (msg().action?.inputs?.length) {
15111
+ <div class="cm-inputs">
15112
+ @for (inp of msg().action!.inputs!; track inp.key) {
15113
+ <label class="cm-input">
15114
+ <span class="cm-input__label">
15115
+ {{ inp.label }}{{ inp.required ? ' *' : '' }}
15116
+ </span>
15117
+ <input
15118
+ [type]="inputType(inp.kind)"
15119
+ [value]="draftValue(inp.key)"
15120
+ (input)="onInputChange(inp.key, $event)"
15121
+ />
15122
+ </label>
15123
+ }
15124
+ </div>
15125
+ }
15126
+ <div class="cm-action__foot">
15127
+ <code class="cm-action__tool">{{ msg().action?.tool }}</code>
15128
+ @if (msg().action; as action) {
15129
+ @if (!action.cancelled) {
15130
+ <button
15131
+ type="button"
15132
+ class="cm-confirm"
15133
+ [disabled]="!pendingReady()"
15134
+ (click)="confirm.emit(msg().id)"
15135
+ >Xác nhận</button>
15136
+ <button
15137
+ type="button"
15138
+ class="cm-cancel"
15139
+ (click)="cancel.emit(msg().id)"
15140
+ >Huỷ</button>
15141
+ }
15142
+ }
15143
+ </div>
15144
+ </div>
15145
+ <span class="cm-ts">{{ msg().ts }}</span>
15146
+ </div>
15147
+ }
15148
+ @case ('action') {
15149
+ <div class="cm-row">
15150
+ <div class="cm-action">
15151
+ <div class="cm-action__head">
15152
+ <span class="cm-chip" [class.cm-chip--undone]="msg().action?.undone">
15153
+ {{ msg().action?.undone ? 'đã hoàn tác' : 'đã ghi' }}
15154
+ </span>
15155
+ <span class="cm-action__detail">{{ msg().action?.detail }}</span>
15156
+ </div>
15157
+ <div class="cm-action__foot">
15158
+ <code class="cm-action__tool">{{ msg().action?.tool }}</code>
15159
+ @if (msg().action; as action) {
15160
+ @if (!action.undone && !action.undoPending) {
15161
+ <button type="button" class="cm-undo" (click)="undo.emit(msg().id)">Hoàn tác</button>
15162
+ }
15163
+ @if (!action.undone && action.undoPending) {
15164
+ <span class="cm-undo-hint">Xác nhận hoàn tác?</span>
15165
+ <button
15166
+ type="button"
15167
+ class="cm-confirm"
15168
+ (click)="confirmUndo.emit(msg().id)"
15169
+ >Xác nhận</button>
15170
+ <button
15171
+ type="button"
15172
+ class="cm-cancel"
15173
+ (click)="cancelUndo.emit(msg().id)"
15174
+ >Huỷ</button>
15175
+ }
15176
+ }
15177
+ </div>
15178
+ </div>
15179
+ <span class="cm-ts">{{ msg().ts }}</span>
15180
+ </div>
15181
+ }
15182
+ @case ('error') {
15183
+ <div class="cm-row">
15184
+ <div class="cm-error">{{ msg().text }}</div>
15185
+ <span class="cm-ts">{{ msg().ts }}</span>
15186
+ </div>
15187
+ }
15188
+ }
15189
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.cm-row{display:flex;flex-direction:column;align-items:flex-start;gap:3px}.cm-row--user{align-items:flex-end}.cm-bubble{max-width:82%;padding:9px 12px;border-radius:14px;font-size:13px;line-height:1.42;white-space:pre-wrap;word-break:break-word}.cm-bubble--user{background:var(--primary);color:#fff;border-bottom-right-radius:4px}.cm-bubble--assistant{background:var(--surface);border:1px solid var(--border);color:var(--text);border-bottom-left-radius:4}.cm-bubble--context{background:var(--primary-soft);border-color:transparent;color:var(--text);font-size:12.5px}.cm-ts{font-size:10px;color:var(--muted-2);padding:0 4px}.cm-action{max-width:88%;background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--mint, #10b981);border-radius:12px;padding:9px 11px;display:flex;flex-direction:column;gap:7px}.cm-action__head{display:flex;align-items:center;gap:7px;flex-wrap:wrap}.cm-action__detail{font-size:12.5px;font-weight:600;color:var(--text)}.cm-action__foot{display:flex;align-items:center;justify-content:space-between;gap:8px}.cm-action__tool{font-size:10.5px;color:var(--muted-2);background:var(--bg);padding:2px 6px;border-radius:5px;font-family:SF Mono,ui-monospace,Menlo,monospace}.cm-chip{font-size:10.5px;font-weight:700;color:var(--mint, #10b981);background:var(--mint-soft, #d1fae5);padding:2px 7px;border-radius:999px;text-transform:uppercase;letter-spacing:.02em}.cm-chip--undone{color:var(--muted);background:var(--bg)}.cm-chip--pending{color:var(--amber, #d97706);background:var(--amber-soft, #fef3c7)}.cm-undo{border:none;background:transparent;color:var(--primary);font-size:11.5px;font-weight:600;cursor:pointer;padding:2px 4px;border-radius:6px}.cm-undo:hover{background:var(--primary-soft)}.cm-confirm{border:none;background:var(--primary);color:#fff;font-size:11.5px;font-weight:600;cursor:pointer;padding:4px 12px;border-radius:6px}.cm-confirm:hover{filter:brightness(1.05)}.cm-cancel{border:1px solid var(--border);background:transparent;color:var(--muted);font-size:11.5px;font-weight:600;cursor:pointer;padding:3px 10px;border-radius:6px}.cm-cancel:hover{background:var(--bg)}.cm-action--pending{border-left-color:var(--amber, #d97706)}.cm-undo-hint{font-size:11.5px;color:var(--amber, #d97706);font-weight:600}.cm-inputs{display:flex;flex-wrap:wrap;gap:8px}.cm-input{display:flex;flex-direction:column;gap:3px;flex:1 1 120px}.cm-input__label{font-size:10.5px;color:var(--muted-2);font-weight:600}.cm-input input{border:1px solid var(--border);border-radius:6px;padding:5px 8px;font-size:12.5px;color:var(--text);background:var(--bg);outline:none}.cm-input input:focus{border-color:var(--primary)}.cm-error{max-width:88%;background:var(--rose-soft, #fee2e2);color:var(--rose, #ef4444);border-left:3px solid var(--rose, #ef4444);border-radius:10px;padding:8px 11px;font-size:12.5px;line-height:1.4}\n"] }]
15190
+ }], propDecorators: { msg: [{ type: i0.Input, args: [{ isSignal: true, alias: "msg", required: true }] }], undo: [{
15191
+ type: Output
15192
+ }], confirm: [{
15193
+ type: Output
15194
+ }], cancel: [{
15195
+ type: Output
15196
+ }], confirmUndo: [{
15197
+ type: Output
15198
+ }], cancelUndo: [{
15199
+ type: Output
15200
+ }], inputChange: [{
15201
+ type: Output
15202
+ }] } });
15203
+
15204
+ /**
15205
+ * Wrap HuggingFace chat completion qua proxy `/api/hf-chat` (mặc định).
15206
+ *
15207
+ * - Browser không gọi HF trực tiếp vì CORS + Authorization header bị block
15208
+ * (status 0). Proxy (Vercel function `api/hf-chat.js` hoặc dev server local
15209
+ * `node api/hf-chat.js` qua proxy.conf.js) giữ token ở server, inject
15210
+ * `Authorization`, và XÂY SYSTEM PROMPT từ `context` (xem api/hf-prompt.js).
15211
+ * - Client chỉ gửi `{ context, messages, model, temperature, max_tokens }`.
15212
+ * Body messages theo OpenAI shape — khớp HF Router chat-completions.
15213
+ * - Khi self-host TGI / vLLM có CORS mở, set `NG_APP_HF_INFERENCE_URL` tới
15214
+ * endpoint đó và `NG_APP_HF_API_TOKEN` (nếu cần) — service sẽ gọi thẳng.
15215
+ */
15216
+ class HfAssistantService {
15217
+ constructor() {
15218
+ this.http = inject(HttpClient);
15219
+ this.config = inject(FEEDING_CONFIG_TOKEN);
15220
+ /** Endpoint client gọi — mặc định proxy /api/hf-chat. */
15221
+ this.endpoint = this.config.hfInferenceUrl || '/api/hf-chat';
15222
+ }
15223
+ /** True khi có endpoint — UI dùng để ẩn/hiện chat. */
15224
+ get configured() {
15225
+ return !!this.endpoint;
15226
+ }
15227
+ get model() {
15228
+ return this.config.hfModel;
15229
+ }
15230
+ /**
15231
+ * Gửi context (snapshot bé) + lịch sử chat, nhận về nội dung assistant raw.
15232
+ * Server tự build system prompt từ context — client không cầm prompt/tool-spec.
15233
+ * Trả về raw text (chưa parse tool-call) — parser xử lý sau.
15234
+ */
15235
+ async send(context, history) {
15236
+ if (!this.configured) {
15237
+ throw new Error('Chưa cấu hình NG_APP_HF_INFERENCE_URL — chat assistant đang tắt.');
15238
+ }
15239
+ const headers = {
15240
+ 'Content-Type': 'application/json',
15241
+ };
15242
+ // Chỉ gửi token client-side khi user tự cấu hình (self-host / direct mode).
15243
+ // Qua proxy /api/hf-chat mặc định thì KHÔNG gửi — proxy inject server-side.
15244
+ if (this.config.hfApiToken && !this.endpoint.startsWith('/api/')) {
15245
+ headers['Authorization'] = `Bearer ${this.config.hfApiToken}`;
15246
+ }
15247
+ const body = {
15248
+ context,
15249
+ model: this.config.hfModel,
15250
+ messages: history,
15251
+ temperature: 0.3,
15252
+ max_tokens: 512,
15253
+ };
15254
+ let resp;
15255
+ try {
15256
+ resp = await firstValueFrom(this.http.post(this.endpoint, body, {
15257
+ headers: new HttpHeaders(headers),
15258
+ }));
15259
+ }
15260
+ catch (err) {
15261
+ throw new Error(this.formatHttpError(err));
15262
+ }
15263
+ if (resp.error) {
15264
+ const msg = typeof resp.error === 'string' ? resp.error : resp.error.message || JSON.stringify(resp.error);
15265
+ throw new Error(`HF: ${msg}`);
15266
+ }
15267
+ const text = resp.choices?.[0]?.message?.content ??
15268
+ resp.generated_text ??
15269
+ '';
15270
+ if (!text)
15271
+ throw new Error('HF trả về phản hồi rỗng.');
15272
+ return text;
15273
+ }
15274
+ /** Biến lỗi HttpClient thành message tiếng Việt rõ ràng. */
15275
+ formatHttpError(err) {
15276
+ if (err instanceof HttpErrorResponse) {
15277
+ if (err.status === 0) {
15278
+ return 'Không kết nối được tới trợ lý AI (status 0 — kiểm tra proxy /api/hf-chat và token HF_TOKEN).';
15279
+ }
15280
+ const body = err.error;
15281
+ const apiMsg = typeof body === 'string' ? body : body?.error?.message || body?.error || body?.message;
15282
+ return `HF ${err.status}: ${apiMsg || err.statusText || 'lỗi không xác định'}`;
15283
+ }
15284
+ return err?.message || 'lỗi mạng không xác định';
15285
+ }
15286
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HfAssistantService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
15287
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HfAssistantService, providedIn: 'root' }); }
15288
+ }
15289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HfAssistantService, decorators: [{
15290
+ type: Injectable,
15291
+ args: [{ providedIn: 'root' }]
15292
+ }] });
15293
+
15294
+ /**
15295
+ * Parse tool-call từ output của HF model.
15296
+ *
15297
+ * Quy ước: model trả về một khối ```json {...}``` chứa
15298
+ * `{ tool: string; args: Record<string, unknown> }`.
15299
+ * Nếu không có khối JSON nào → đây là trả lời prose thuần (advisory).
15300
+ */
15301
+ const FENCE_RE = /```(?:json)?\s*([\s\S]*?)```/i;
15302
+ function tryParseJson(s) {
15303
+ try {
15304
+ return JSON.parse(s);
15305
+ }
15306
+ catch {
15307
+ return null;
15308
+ }
15309
+ }
15310
+ /** Coerce một giá trị bất kỳ về ParsedToolCall hoặc null. */
15311
+ function asToolCall(v) {
15312
+ if (!v || typeof v !== 'object')
15313
+ return null;
15314
+ const obj = v;
15315
+ const toolVal = obj['tool'];
15316
+ const tool = typeof toolVal === 'string' ? toolVal.trim() : '';
15317
+ if (!tool)
15318
+ return null;
15319
+ const argsVal = obj['args'];
15320
+ const args = argsVal && typeof argsVal === 'object' ? argsVal : {};
15321
+ return { tool, args };
15322
+ }
15323
+ /**
15324
+ * Tách reply thành text hoặc tool-call. Ưu tiên tìm khối JSON fence;
15325
+ * nếu không có, thử parse toàn bộ output (model đôi khi quên fence).
15326
+ */
15327
+ function parseHfReply(raw) {
15328
+ const trimmed = raw.trim();
15329
+ if (!trimmed)
15330
+ return { kind: 'text', text: '' };
15331
+ const fenceMatch = trimmed.match(FENCE_RE);
15332
+ if (fenceMatch) {
15333
+ const parsed = asToolCall(tryParseJson(fenceMatch[1].trim()));
15334
+ if (parsed)
15335
+ return { kind: 'tool', ...parsed, raw: trimmed };
15336
+ }
15337
+ const direct = asToolCall(tryParseJson(trimmed));
15338
+ if (direct)
15339
+ return { kind: 'tool', ...direct, raw: trimmed };
15340
+ return { kind: 'text', text: trimmed };
15341
+ }
15342
+ // ── Arg validators (throw nếu sai, trả về typed arg) ────────────────
15343
+ function reqString(args, key) {
15344
+ const v = args[key];
15345
+ if (typeof v !== 'string' || !v.trim())
15346
+ throw new Error(`Thiếu tham số "${key}"`);
15347
+ return v.trim();
15348
+ }
15349
+ function reqNumber(args, key) {
15350
+ const v = args[key];
15351
+ const n = typeof v === 'number' ? v : typeof v === 'string' ? parseFloat(v) : NaN;
15352
+ if (!isFinite(n))
15353
+ throw new Error(`Tham số "${key}" không hợp lệ`);
15354
+ return n;
15355
+ }
15356
+ function optString(args, key) {
15357
+ const v = args[key];
15358
+ return typeof v === 'string' && v.trim() ? v.trim() : undefined;
15359
+ }
15360
+ /** Validate HH:mm (24h). */
15361
+ function validateTime(v) {
15362
+ if (!/^\d{1,2}:\d{2}$/.test(v))
15363
+ throw new Error(`Giờ "${v}" không đúng định dạng HH:mm`);
15364
+ const [h, m] = v.split(':').map(Number);
15365
+ if (h < 0 || h > 23 || m < 0 || m > 59)
15366
+ throw new Error(`Giờ "${v}" ngoài phạm vi`);
15367
+ return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
15368
+ }
15369
+ /** Validate YYYY-MM-DD. */
15370
+ function validateDate(v) {
15371
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(v))
15372
+ throw new Error(`Ngày "${v}" không đúng định dạng YYYY-MM-DD`);
15373
+ return v;
15374
+ }
15375
+ const ToolArgs = {
15376
+ add_feeding_session(args) {
15377
+ return { time: validateTime(reqString(args, 'time')), volumeMl: reqNumber(args, 'volume_ml'), note: optString(args, 'note') };
15378
+ },
15379
+ prepare_formula(args) {
15380
+ return { volumeMl: reqNumber(args, 'volume_ml') };
15381
+ },
15382
+ log_weight(args) {
15383
+ return { weightKg: reqNumber(args, 'weight_kg') };
15384
+ },
15385
+ query_recent(_args) {
15386
+ return {};
15387
+ },
15388
+ next_event(_args) {
15389
+ return {};
15390
+ },
15391
+ set_reminder(args) {
15392
+ const title = reqString(args, 'title');
15393
+ const dateRaw = optString(args, 'date');
15394
+ const timeRaw = optString(args, 'time');
15395
+ return {
15396
+ title,
15397
+ date: dateRaw ? validateDate(dateRaw) : undefined,
15398
+ time: timeRaw ? validateTime(timeRaw) : undefined,
15399
+ };
15400
+ },
15401
+ send_notification(args) {
15402
+ return { content: reqString(args, 'content') };
15403
+ },
15404
+ };
15405
+ const TOOL_NAMES = Object.keys(ToolArgs);
15406
+ function isToolName(s) {
15407
+ return s in ToolArgs;
15408
+ }
15409
+
15410
+ /**
15411
+ * Registry map tool-name (từ HF model) → handler gọi method có sẵn trên
15412
+ * các service hiện có. Không chứa logic nghiệp vụ mới — chỉ orchestrate.
15413
+ *
15414
+ * Mọi handler trả về ToolResult. UI tự render chip "đã ghi" + nút "Hoàn tác"
15415
+ * dựa trên `undo` có tồn tại hay không.
15416
+ */
15417
+ class ToolRegistry {
15418
+ constructor() {
15419
+ this.feeding = inject(FeedingLogService);
15420
+ this.weight = inject(WeightLogService);
15421
+ this.activity = inject(ActivityLogService);
15422
+ this.events = inject(EventLogService);
15423
+ this.notifications = inject(NotificationLogService);
15424
+ /** Danh sách tool công khai — dùng để validate / debug. */
15425
+ this.toolNames = Object.keys(ToolArgs);
15426
+ /** Tool có side-effect (ghi sheet) — cần user Confirm trước khi thực thi. */
15427
+ this.writeTools = new Set([
15428
+ 'add_feeding_session',
15429
+ 'prepare_formula',
15430
+ 'log_weight',
15431
+ 'set_reminder',
15432
+ 'send_notification',
15433
+ ]);
15434
+ }
15435
+ /** True nếu tool ghi thay đổi lên sheet — UI sẽ hiển thị thẻ Confirm trước. */
15436
+ isWriteTool(tool) {
15437
+ return this.writeTools.has(tool);
15438
+ }
15439
+ /**
15440
+ * Mô tả ngắn gọn (tiếng Việt) thao tác sắp thực thi — KHÔNG side-effect.
15441
+ * Dùng cho thẻ Confirm trước khi gọi `dispatch`. Throw nếu args không hợp lệ.
15442
+ * Trả về cả danh sách ô nhập user cần điền (vd ngày/giờ thiếu cho set_reminder).
15443
+ */
15444
+ describe(tool, rawArgs) {
15445
+ if (!isToolName(tool)) {
15446
+ return { detail: `Tool "${tool}" không được hỗ trợ` };
15447
+ }
15448
+ switch (tool) {
15449
+ case 'add_feeding_session': {
15450
+ const a = ToolArgs.add_feeding_session(rawArgs);
15451
+ return {
15452
+ detail: `Ghi cữ bú ${a.time} — ${a.volumeMl}ml${a.note ? ` (${a.note})` : ''}`,
15453
+ };
15454
+ }
15455
+ case 'prepare_formula': {
15456
+ const a = ToolArgs.prepare_formula(rawArgs);
15457
+ return {
15458
+ detail: a.volumeMl <= 0 ? 'Xoá sữa đã pha (clear bottle prep)' : `Pha sữa ${a.volumeMl}ml`,
15459
+ };
15460
+ }
15461
+ case 'log_weight': {
15462
+ const a = ToolArgs.log_weight(rawArgs);
15463
+ return { detail: `Ghi cân nặng ${a.weightKg}kg` };
15464
+ }
15465
+ case 'set_reminder': {
15466
+ const a = ToolArgs.set_reminder(rawArgs);
15467
+ const parts = [`Lên lịch "${a.title}"`];
15468
+ if (a.date && a.time)
15469
+ parts.push(`${a.date} ${a.time}`);
15470
+ else if (a.date)
15471
+ parts.push(a.date);
15472
+ else if (a.time)
15473
+ parts.push(a.time);
15474
+ else
15475
+ parts.push('(cần nhập ngày & giờ)');
15476
+ const inputs = [];
15477
+ if (!a.date) {
15478
+ inputs.push({ key: 'date', label: 'Ngày', kind: 'date', required: true });
15479
+ }
15480
+ if (!a.time) {
15481
+ inputs.push({ key: 'time', label: 'Giờ', kind: 'time', required: true });
15482
+ }
15483
+ return {
15484
+ detail: parts.join(' — '),
15485
+ inputs: inputs.length > 0 ? inputs : undefined,
15486
+ };
15487
+ }
15488
+ case 'send_notification': {
15489
+ const a = ToolArgs.send_notification(rawArgs);
15490
+ return { detail: `Gửi thông báo: ${a.content}` };
15491
+ }
15492
+ case 'query_recent':
15493
+ return { detail: 'Tóm tắt cữ bú hôm nay' };
15494
+ case 'next_event':
15495
+ return { detail: 'Xem sự kiện kế tiếp' };
15496
+ }
15497
+ }
15498
+ async dispatch(tool, rawArgs, ctx) {
15499
+ if (!isToolName(tool)) {
15500
+ return { ok: false, detail: `Tool "${tool}" không được hỗ trợ` };
15501
+ }
15502
+ try {
15503
+ switch (tool) {
15504
+ case 'add_feeding_session':
15505
+ return await this.addFeeding(ToolArgs.add_feeding_session(rawArgs), ctx);
15506
+ case 'prepare_formula':
15507
+ return await this.prepareFormula(ToolArgs.prepare_formula(rawArgs), ctx);
15508
+ case 'log_weight':
15509
+ return await this.logWeight(ToolArgs.log_weight(rawArgs), ctx);
15510
+ case 'set_reminder':
15511
+ return await this.setReminder(ToolArgs.set_reminder(rawArgs), ctx);
15512
+ case 'send_notification':
15513
+ return await this.sendNotification(ToolArgs.send_notification(rawArgs), ctx);
15514
+ case 'query_recent':
15515
+ return this.queryRecent(ctx);
15516
+ case 'next_event':
15517
+ return this.nextEvent(ctx);
15518
+ }
15519
+ }
15520
+ catch (err) {
15521
+ const msg = err instanceof Error ? err.message : 'thất bại';
15522
+ return { ok: false, detail: `Không thực thi: ${msg}` };
15523
+ }
15524
+ }
15525
+ // ── Write tools ───────────────────────────────────────────────────
15526
+ async addFeeding(a, ctx) {
15527
+ const log = {
15528
+ user: ctx.user,
15529
+ date: todayStr(),
15530
+ time: a.time,
15531
+ volume: a.volumeMl,
15532
+ note: a.note,
15533
+ };
15534
+ const resp = await firstValueFrom(this.feeding.addLog(log));
15535
+ const rowIndex = resp.rowIndex;
15536
+ // Audit trail — giống flow UI (feeding-dialogs submitLog).
15537
+ if (resp.success) {
15538
+ await firstValueFrom(this.activity.logFeeding(ctx.user, 'FEEDING_ADDED', {
15539
+ time: a.time,
15540
+ volume: a.volumeMl,
15541
+ }));
15542
+ }
15543
+ return {
15544
+ ok: resp.success,
15545
+ detail: `Đã ghi cữ bú ${a.time} — ${a.volumeMl}ml${a.note ? ` (${a.note})` : ''}`,
15546
+ undo: rowIndex
15547
+ ? async () => {
15548
+ await firstValueFrom(this.feeding.deleteLog(rowIndex));
15549
+ await firstValueFrom(this.activity.logFeeding(ctx.user, 'FEEDING_DELETED', {
15550
+ time: a.time,
15551
+ volume: a.volumeMl,
15552
+ reason: 'hoàn tác từ trợ lý AI',
15553
+ }));
15554
+ }
15555
+ : undefined,
15556
+ };
15557
+ }
15558
+ async prepareFormula(a, ctx) {
15559
+ // volumeMl <= 0 → user muốn xoá sữa đã pha, gọi clearBottlePrep thay vì set 0ml.
15560
+ if (a.volumeMl <= 0) {
15561
+ let prevVolume;
15562
+ try {
15563
+ const prev = await firstValueFrom(this.feeding.getBottlePrep());
15564
+ prevVolume = prev?.volumeMl;
15565
+ }
15566
+ catch {
15567
+ /* không chặn flow clear */
15568
+ }
15569
+ await firstValueFrom(this.feeding.clearBottlePrepOnSheet());
15570
+ await firstValueFrom(this.activity.logBottlePrepManualClear(ctx.user, prevVolume ?? 0, 'qua trợ lý AI'));
15571
+ return {
15572
+ ok: true,
15573
+ detail: prevVolume
15574
+ ? `Đã xoá ${prevVolume}ml sữa đã pha`
15575
+ : `Đã xoá sữa đã pha`,
15576
+ };
15577
+ }
15578
+ // Pha sữa mới: ghi dung tích + giờ pha lên sheet (bottle-prep tracker) rồi
15579
+ // viết activity log BOTTLE_PREP_ADDED — giống flow feeding-daily.saveBottlePrep.
15580
+ const atIso = new Date().toISOString();
15581
+ const time = toTimeStr(new Date(atIso));
15582
+ await firstValueFrom(this.feeding.setBottlePrepOnSheet({
15583
+ user: ctx.user,
15584
+ volumeMl: a.volumeMl,
15585
+ time,
15586
+ atIso,
15587
+ }));
15588
+ await firstValueFrom(this.activity.addLog({
15589
+ user: ctx.user,
15590
+ eventType: ACTIVITY_EVENT.BOTTLE_PREP_ADDED,
15591
+ content: formatLogContent(ACTIVITY_EVENT.BOTTLE_PREP_ADDED, {
15592
+ volume: a.volumeMl,
15593
+ time,
15594
+ }),
15595
+ }));
15596
+ return {
15597
+ ok: true,
15598
+ detail: `Đã pha sữa ${a.volumeMl}ml lúc ${time}`,
15599
+ // setBottlePrepOnSheet là ghi đè (không phải append) — không có undo rõ ràng qua chat.
15600
+ };
15601
+ }
15602
+ async logWeight(a, ctx) {
15603
+ const date = todayStr();
15604
+ const log = { user: ctx.user, date, weightKg: a.weightKg };
15605
+ const resp = await firstValueFrom(this.weight.addLog(log));
15606
+ if (resp.success) {
15607
+ await firstValueFrom(this.activity.logWeight(ctx.user, 'WEIGHT_ADDED', { date, weight: a.weightKg }));
15608
+ }
15609
+ return {
15610
+ ok: resp.success,
15611
+ detail: `Đã ghi cân nặng ${a.weightKg}kg`,
15612
+ undo: resp.rowIndex
15613
+ ? async () => {
15614
+ await firstValueFrom(this.weight.deleteLog(resp.rowIndex));
15615
+ await firstValueFrom(this.activity.logWeight(ctx.user, 'WEIGHT_DELETED', {
15616
+ date,
15617
+ weight: a.weightKg,
15618
+ }));
15619
+ }
15620
+ : undefined,
15621
+ };
15622
+ }
15623
+ async setReminder(a, ctx) {
15624
+ if (!a.date || !a.time) {
15625
+ return {
15626
+ ok: false,
15627
+ detail: 'Thiếu ngày hoặc giờ để lên lịch — hãy điền vào ô nhập rồi xác nhận lại.',
15628
+ };
15629
+ }
15630
+ const date = a.date;
15631
+ const time = a.time;
15632
+ const title = a.title;
15633
+ const ev = {
15634
+ user: ctx.user,
15635
+ date,
15636
+ time,
15637
+ title,
15638
+ acknowledged: false,
15639
+ };
15640
+ const resp = await firstValueFrom(this.events.addEvent(ev));
15641
+ if (resp.success) {
15642
+ await firstValueFrom(this.activity.logSchedule(ctx.user, 'SCHEDULE_ADDED', { title, date }));
15643
+ }
15644
+ return {
15645
+ ok: resp.success,
15646
+ detail: `Đã lên lịch "${title}" — ${date} ${time}`,
15647
+ undo: resp.rowIndex
15648
+ ? async () => {
15649
+ await firstValueFrom(this.events.deleteEvent(resp.rowIndex));
15650
+ await firstValueFrom(this.activity.logSchedule(ctx.user, 'SCHEDULE_DELETED', {
15651
+ title,
15652
+ date,
15653
+ }));
15654
+ }
15655
+ : undefined,
15656
+ };
15657
+ }
15658
+ async sendNotification(a, ctx) {
15659
+ const resp = await firstValueFrom(this.notifications.addNotification({ user: ctx.user, content: a.content }));
15660
+ if (resp.success) {
15661
+ await firstValueFrom(this.activity.addLog({
15662
+ user: ctx.user,
15663
+ eventType: ACTIVITY_EVENT.NOTIFICATION_CREATED,
15664
+ content: formatLogContent(ACTIVITY_EVENT.NOTIFICATION_CREATED, { content: a.content }),
15665
+ }));
15666
+ }
15667
+ return {
15668
+ ok: resp.success,
15669
+ detail: `Đã gửi thông báo tới nhóm`,
15670
+ undo: resp.rowIndex
15671
+ ? async () => {
15672
+ await firstValueFrom(this.notifications.deleteNotification(resp.rowIndex, ctx.user));
15673
+ await firstValueFrom(this.activity.addLog({
15674
+ user: ctx.user,
15675
+ eventType: ACTIVITY_EVENT.NOTIFICATION_DELETED,
15676
+ content: formatLogContent(ACTIVITY_EVENT.NOTIFICATION_DELETED, {
15677
+ content: a.content,
15678
+ }),
15679
+ }));
15680
+ }
15681
+ : undefined,
15682
+ };
15683
+ }
15684
+ // ── Read-only tools (không side-effect, trả về detail prose) ──────
15685
+ queryRecent(ctx) {
15686
+ const detail = `Hôm nay bé bú ${ctx.todayCount} cữ, tổng ${ctx.todayTotalMl}ml. Cữ gần nhất ${ctx.todayLogs[0] ? `${ctx.todayLogs[0].time} — ${ctx.todayLogs[0].volume}ml` : 'chưa có'}. Cữ tiếp theo dự kiến ${ctx.nextFeedTime ?? 'không xác định'}.`;
15687
+ return { ok: true, detail };
15688
+ }
15689
+ nextEvent(ctx) {
15690
+ const next = ctx.upcomingEvents[0];
15691
+ return {
15692
+ ok: true,
15693
+ detail: next ? `Sự kiện kế tiếp: ${next.title} — ${next.dateLabel}` : 'Không có sự kiện sắp tới.',
15694
+ };
15695
+ }
15696
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ToolRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
15697
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ToolRegistry, providedIn: 'root' }); }
15698
+ }
15699
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ToolRegistry, decorators: [{
15700
+ type: Injectable,
15701
+ args: [{ providedIn: 'root' }]
15702
+ }] });
15703
+ /** YYYY-MM-DD theo giờ địa phương. */
15704
+ function todayStr() {
15705
+ const d = new Date();
15706
+ const mm = String(d.getMonth() + 1).padStart(2, '0');
15707
+ const dd = String(d.getDate()).padStart(2, '0');
15708
+ return `${d.getFullYear()}-${mm}-${dd}`;
15709
+ }
15710
+ /** HH:mm (24h, giờ địa phương) từ Date. */
15711
+ function toTimeStr(d) {
15712
+ return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
15713
+ }
15714
+
15715
+ let idCounter = 0;
15716
+ const nextId = () => `c${++idCounter}`;
15717
+ const nowTs = () => new Date().toLocaleTimeString('vi-VN', { hour: '2-digit', minute: '2-digit' });
15718
+ /**
15719
+ * Lớp vỏ khung chat — giữ messages signal, orchestrate flow:
15720
+ * user send → build context → HF inference → parse → (text | tool) → render.
15721
+ *
15722
+ * Tool có side-effect (ghi sheet) → render thẻ «chờ xác nhận»; user bấm
15723
+ * «Xác nhận» mới dispatch. Tool read-only → dispatch ngay.
15724
+ *
15725
+ * Input `context` là snapshot dữ liệu bé từ FeedingComponent (signals).
15726
+ * `disabled` true khi chưa cấu hình HF — render callout thay vì khung nhập.
15727
+ */
15728
+ class ChatShellComponent {
15729
+ constructor() {
15730
+ this.hf = inject(HfAssistantService);
15731
+ this.tools = inject(ToolRegistry);
15732
+ /** Snapshot dữ liệu bé — parent truyền vào mỗi khi mở chat. */
15733
+ this.context = input.required(...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
15734
+ /** True khi chưa cấu hình HF — chỉ render callout. */
15735
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
15736
+ this.messages = signal([], ...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
15737
+ this.busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
15738
+ /** Map id → undo callback (lưu từ ToolResult khi dispatch). */
15739
+ this.undoMap = new Map();
15740
+ /** Map id → {tool, args} cho thẻ pending chờ user Confirm. */
15741
+ this.pendingMap = new Map();
15742
+ /** Lịch sử dạng OpenAI messages: user + assistant text + action result (model thấy kết quả tool). */
15743
+ this.history = computed(() => this.messages()
15744
+ .filter((m) => m.kind === 'user' || m.kind === 'text' || m.kind === 'action')
15745
+ .map((m) => ({
15746
+ role: m.kind === 'user' ? 'user' : 'assistant',
15747
+ content: m.kind === 'action' ? m.action?.detail ?? '' : m.text ?? '',
15748
+ })), ...(ngDevMode ? [{ debugName: "history" }] : /* istanbul ignore next */ []));
15749
+ this.greeted = false;
15750
+ // Auto-scroll tới tin mới nhất mỗi khi messages/busy thay đổi.
15751
+ // effect chạy sau khi signal update; dùng rAF để chờ DOM paint xong.
15752
+ effect(() => {
15753
+ this.messages();
15754
+ this.busy();
15755
+ this.scrollToBottom();
15756
+ });
15757
+ // Greet khi có context lần đầu.
15758
+ queueMicrotask(() => this.maybeGreet());
15759
+ }
15760
+ ngOnChanges() {
15761
+ this.maybeGreet();
15762
+ }
15763
+ maybeGreet() {
15764
+ if (this.greeted)
15765
+ return;
15766
+ const ctx = this.context();
15767
+ if (!ctx)
15768
+ return;
15769
+ this.greeted = true;
15770
+ this.messages.update((prev) => [
15771
+ ...prev,
15772
+ {
15773
+ id: nextId(),
15774
+ kind: 'context',
15775
+ text: `Xin chào! Mình là trợ lý bú sữa. Bé ${ctx.babyName || ''} ${ctx.ageLabel}, ` +
15776
+ `${ctx.weightKg !== undefined ? ctx.weightKg + 'kg' : 'chưa rõ cân nặng'}. ` +
15777
+ `Hôm nay bé bú ${ctx.todayCount} cữ, tổng ${ctx.todayTotalMl}ml. ` +
15778
+ `Bạn muốn hỏi hay ghi nhận gì?`,
15779
+ ts: nowTs(),
15780
+ },
15781
+ ]);
15782
+ }
15783
+ async onSend(text) {
15784
+ if (this.busy() || this.disabled())
15785
+ return;
15786
+ const ctx = this.context();
15787
+ // 1. append user msg
15788
+ this.messages.update((prev) => [
15789
+ ...prev,
15790
+ { id: nextId(), kind: 'user', text, ts: nowTs() },
15791
+ ]);
15792
+ this.scrollToBottom();
15793
+ this.busy.set(true);
15794
+ try {
15795
+ const raw = await this.hf.send(ctx, this.history());
15796
+ const reply = parseHfReply(raw);
15797
+ if (reply.kind === 'text') {
15798
+ this.messages.update((prev) => [
15799
+ ...prev,
15800
+ { id: nextId(), kind: 'text', text: reply.text, ts: nowTs() },
15801
+ ]);
15802
+ }
15803
+ else {
15804
+ this.routeToolCall(reply.tool, reply.args, ctx);
15805
+ }
15806
+ }
15807
+ catch (err) {
15808
+ const msg = err instanceof Error ? err.message : 'lỗi không xác định';
15809
+ this.messages.update((prev) => [
15810
+ ...prev,
15811
+ { id: nextId(), kind: 'error', text: msg, ts: nowTs() },
15812
+ ]);
15813
+ }
15814
+ finally {
15815
+ this.busy.set(false);
15816
+ this.scrollToBottom();
15817
+ }
15818
+ }
15819
+ /**
15820
+ * Phân luồng tool call:
15821
+ * - Write tool (ghi sheet) → hiển thị thẻ «chờ xác nhận», đợi user bấm Confirm.
15822
+ * - Read-only tool → dispatch ngay.
15823
+ */
15824
+ routeToolCall(tool, args, ctx) {
15825
+ let preview;
15826
+ try {
15827
+ preview = this.tools.describe(tool, args);
15828
+ }
15829
+ catch (err) {
15830
+ const msg = err instanceof Error ? err.message : 'thất bại';
15831
+ this.messages.update((prev) => [
15832
+ ...prev,
15833
+ { id: nextId(), kind: 'error', text: `Không thực thi: ${msg}`, ts: nowTs() },
15834
+ ]);
15835
+ return;
15836
+ }
15837
+ if (this.tools.isWriteTool(tool)) {
15838
+ const id = nextId();
15839
+ this.pendingMap.set(id, { tool, args });
15840
+ this.messages.update((prev) => [
15841
+ ...prev,
15842
+ {
15843
+ id,
15844
+ kind: 'pending',
15845
+ action: {
15846
+ tool,
15847
+ detail: preview.detail,
15848
+ args,
15849
+ inputs: preview.inputs,
15850
+ inputDraft: {},
15851
+ },
15852
+ ts: nowTs(),
15853
+ },
15854
+ ]);
15855
+ return;
15856
+ }
15857
+ // Read-only: dispatch ngay.
15858
+ void this.executeTool(tool, args, ctx);
15859
+ }
15860
+ /** User gõ vào ô nhập trên thẻ pending — cập nhật inputDraft. */
15861
+ onInputChange(e) {
15862
+ this.messages.update((prev) => prev.map((m) => m.id === e.id && m.action
15863
+ ? {
15864
+ ...m,
15865
+ action: {
15866
+ ...m.action,
15867
+ inputDraft: { ...(m.action.inputDraft ?? {}), [e.key]: e.value },
15868
+ },
15869
+ }
15870
+ : m));
15871
+ }
15872
+ /** User bấm «Xác nhận» trên thẻ pending — dispatch tool thật với input đã gộp. */
15873
+ async onConfirm(msgId) {
15874
+ const pending = this.pendingMap.get(msgId);
15875
+ if (!pending)
15876
+ return;
15877
+ const ctx = this.context();
15878
+ const { tool, args } = pending;
15879
+ this.pendingMap.delete(msgId);
15880
+ // Gộp giá trị user đã nhập vào ô nhập (date/time…) vào args gốc.
15881
+ const msg = this.messages().find((m) => m.id === msgId);
15882
+ const draft = msg?.action?.inputDraft ?? {};
15883
+ const mergedArgs = { ...args };
15884
+ for (const [key, value] of Object.entries(draft)) {
15885
+ if (value && value.trim())
15886
+ mergedArgs[key] = value.trim();
15887
+ }
15888
+ // Xoá thẻ pending — executeTool sẽ append thẻ action (hoặc error) mới.
15889
+ this.messages.update((prev) => prev.filter((m) => m.id !== msgId));
15890
+ await this.executeTool(tool, mergedArgs, ctx);
15891
+ }
15892
+ /** User bấm «Huỷ» trên thẻ pending — đánh dấu đã huỷ, drop args. */
15893
+ onCancel(msgId) {
15894
+ this.pendingMap.delete(msgId);
15895
+ this.messages.update((prev) => prev.map((m) => m.id === msgId && m.kind === 'pending' && m.action
15896
+ ? { ...m, action: { ...m.action, cancelled: true, args: undefined } }
15897
+ : m));
15898
+ }
15899
+ async executeTool(tool, args, ctx) {
15900
+ const result = await this.tools.dispatch(tool, args, ctx);
15901
+ const id = nextId();
15902
+ if (result.undo)
15903
+ this.undoMap.set(id, result.undo);
15904
+ if (!result.ok) {
15905
+ this.messages.update((prev) => [
15906
+ ...prev,
15907
+ { id, kind: 'error', text: result.detail, ts: nowTs() },
15908
+ ]);
15909
+ return;
15910
+ }
15911
+ this.messages.update((prev) => [
15912
+ ...prev,
15913
+ {
15914
+ id,
15915
+ kind: 'action',
15916
+ action: { tool, detail: result.detail },
15917
+ ts: nowTs(),
15918
+ },
15919
+ ]);
15920
+ // Kết quả tool đã nằm trong action card; `history` computed bao gồm action
15921
+ // (map sang assistant message) nên model thấy được — không cần text bubble thừa.
15922
+ }
15923
+ async onUndo(msgId) {
15924
+ // Bước 1: vào chế độ chờ xác nhận — KHÔNG gọi undo ngay.
15925
+ this.messages.update((prev) => prev.map((m) => m.id === msgId && m.action && !m.action.undone
15926
+ ? { ...m, action: { ...m.action, undoPending: true } }
15927
+ : m));
15928
+ }
15929
+ /** User xác nhận hoàn tác — gọi undo callback thật + ghi activity log. */
15930
+ async onConfirmUndo(msgId) {
15931
+ const undo = this.undoMap.get(msgId);
15932
+ if (!undo) {
15933
+ this.messages.update((prev) => prev.map((m) => m.id === msgId && m.action
15934
+ ? { ...m, action: { ...m.action, undoPending: false } }
15935
+ : m));
15936
+ return;
15937
+ }
15938
+ try {
15939
+ await undo();
15940
+ this.undoMap.delete(msgId);
15941
+ this.messages.update((prev) => prev.map((m) => m.id === msgId && m.action
15942
+ ? { ...m, action: { ...m.action, undone: true, undoPending: false } }
15943
+ : m));
15944
+ }
15945
+ catch (err) {
15946
+ const msg = err instanceof Error ? err.message : 'hoàn tác thất bại';
15947
+ this.messages.update((prev) => [
15948
+ ...prev.map((m) => m.id === msgId && m.action
15949
+ ? { ...m, action: { ...m.action, undoPending: false } }
15950
+ : m),
15951
+ { id: nextId(), kind: 'error', text: `Hoàn tác: ${msg}`, ts: nowTs() },
15952
+ ]);
15953
+ }
15954
+ }
15955
+ /** User huỷ ý định hoàn tác — thoát chế độ chờ xác nhận. */
15956
+ onCancelUndo(msgId) {
15957
+ this.messages.update((prev) => prev.map((m) => m.id === msgId && m.action
15958
+ ? { ...m, action: { ...m.action, undoPending: false } }
15959
+ : m));
15960
+ }
15961
+ scrollToBottom() {
15962
+ // requestAnimationFrame chờ Angular vẽ DOM xong rồi mới cuộn — tránh scrollHeight stale.
15963
+ requestAnimationFrame(() => {
15964
+ const el = this.scrollRef?.nativeElement;
15965
+ if (el)
15966
+ el.scrollTop = el.scrollHeight;
15967
+ });
15968
+ }
15969
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ChatShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15970
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: ChatShellComponent, isStandalone: true, selector: "app-chat-shell", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "scrollRef", first: true, predicate: ["scroll"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `
15971
+ <div class="cs-scroll" #scroll>
15972
+ @for (m of messages(); track m.id) {
15973
+ <app-chat-message
15974
+ [msg]="m"
15975
+ (undo)="onUndo($event)"
15976
+ (confirm)="onConfirm($event)"
15977
+ (cancel)="onCancel($event)"
15978
+ (confirmUndo)="onConfirmUndo($event)"
15979
+ (cancelUndo)="onCancelUndo($event)"
15980
+ (inputChange)="onInputChange($event)"
15981
+ ></app-chat-message>
15982
+ }
15983
+ @if (busy()) {
15984
+ <div class="cs-typing" aria-live="polite" aria-label="Trợ lý đang trả lời">
15985
+ <span class="cs-typing__bubble">
15986
+ <span class="cs-typing__dot"></span>
15987
+ <span class="cs-typing__dot"></span>
15988
+ <span class="cs-typing__dot"></span>
15989
+ </span>
15990
+ <span class="cs-typing__label">Trợ lý đang trả lời…</span>
15991
+ </div>
15992
+ }
15993
+ </div>
15994
+
15995
+ @if (disabled()) {
15996
+ <div class="cs-disabled">
15997
+ <i class="pi pi-exclamation-triangle" aria-hidden="true"></i>
15998
+ <span>Trợ lý AI chưa cấu hình. Set <code>NG_APP_HF_INFERENCE_URL</code> để bật.</span>
15999
+ </div>
16000
+ } @else {
16001
+ <app-chat-composer (send)="onSend($event)"></app-chat-composer>
16002
+ }
16003
+ `, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--bg)}.cs-scroll{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:14px 12px;display:flex;flex-direction:column;gap:12px}.cs-typing{display:inline-flex;align-items:center;gap:8px;align-self:flex-start;padding:8px 12px;background:var(--surface);border:1px solid var(--border);border-radius:14px 14px 14px 4px}.cs-typing__bubble{display:inline-flex;gap:4px}.cs-typing__dot{width:6px;height:6px;border-radius:999px;background:var(--muted-2);animation:cs-bounce 1.2s infinite ease-in-out}.cs-typing__dot:nth-child(2){animation-delay:.15s}.cs-typing__dot:nth-child(3){animation-delay:.3s}.cs-typing__label{font-size:12px;color:var(--muted-2);line-height:1}@keyframes cs-bounce{0%,80%,to{transform:translateY(0);opacity:.5}40%{transform:translateY(-3px);opacity:1}}.cs-disabled{display:flex;align-items:center;gap:8px;margin:10px 12px;padding:12px;border-radius:10px;background:var(--amber-soft, #fef3c7);color:var(--amber, #f59e0b);font-size:12.5px;line-height:1.4}.cs-disabled i{font-size:16px;flex-shrink:0}.cs-disabled code{background:#f59e0b26;padding:1px 5px;border-radius:4px;font-size:11px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ChatComposerComponent, selector: "app-chat-composer", outputs: ["send"] }, { kind: "component", type: ChatMessageComponent, selector: "app-chat-message", inputs: ["msg"], outputs: ["undo", "confirm", "cancel", "confirmUndo", "cancelUndo", "inputChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
16004
+ }
16005
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ChatShellComponent, decorators: [{
16006
+ type: Component,
16007
+ args: [{ selector: 'app-chat-shell', standalone: true, imports: [CommonModule, ChatComposerComponent, ChatMessageComponent], template: `
16008
+ <div class="cs-scroll" #scroll>
16009
+ @for (m of messages(); track m.id) {
16010
+ <app-chat-message
16011
+ [msg]="m"
16012
+ (undo)="onUndo($event)"
16013
+ (confirm)="onConfirm($event)"
16014
+ (cancel)="onCancel($event)"
16015
+ (confirmUndo)="onConfirmUndo($event)"
16016
+ (cancelUndo)="onCancelUndo($event)"
16017
+ (inputChange)="onInputChange($event)"
16018
+ ></app-chat-message>
16019
+ }
16020
+ @if (busy()) {
16021
+ <div class="cs-typing" aria-live="polite" aria-label="Trợ lý đang trả lời">
16022
+ <span class="cs-typing__bubble">
16023
+ <span class="cs-typing__dot"></span>
16024
+ <span class="cs-typing__dot"></span>
16025
+ <span class="cs-typing__dot"></span>
16026
+ </span>
16027
+ <span class="cs-typing__label">Trợ lý đang trả lời…</span>
16028
+ </div>
16029
+ }
16030
+ </div>
16031
+
16032
+ @if (disabled()) {
16033
+ <div class="cs-disabled">
16034
+ <i class="pi pi-exclamation-triangle" aria-hidden="true"></i>
16035
+ <span>Trợ lý AI chưa cấu hình. Set <code>NG_APP_HF_INFERENCE_URL</code> để bật.</span>
16036
+ </div>
16037
+ } @else {
16038
+ <app-chat-composer (send)="onSend($event)"></app-chat-composer>
16039
+ }
16040
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--bg)}.cs-scroll{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:14px 12px;display:flex;flex-direction:column;gap:12px}.cs-typing{display:inline-flex;align-items:center;gap:8px;align-self:flex-start;padding:8px 12px;background:var(--surface);border:1px solid var(--border);border-radius:14px 14px 14px 4px}.cs-typing__bubble{display:inline-flex;gap:4px}.cs-typing__dot{width:6px;height:6px;border-radius:999px;background:var(--muted-2);animation:cs-bounce 1.2s infinite ease-in-out}.cs-typing__dot:nth-child(2){animation-delay:.15s}.cs-typing__dot:nth-child(3){animation-delay:.3s}.cs-typing__label{font-size:12px;color:var(--muted-2);line-height:1}@keyframes cs-bounce{0%,80%,to{transform:translateY(0);opacity:.5}40%{transform:translateY(-3px);opacity:1}}.cs-disabled{display:flex;align-items:center;gap:8px;margin:10px 12px;padding:12px;border-radius:10px;background:var(--amber-soft, #fef3c7);color:var(--amber, #f59e0b);font-size:12.5px;line-height:1.4}.cs-disabled i{font-size:16px;flex-shrink:0}.cs-disabled code{background:#f59e0b26;padding:1px 5px;border-radius:4px;font-size:11px}\n"] }]
16041
+ }], ctorParameters: () => [], propDecorators: { context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], scrollRef: [{
16042
+ type: ViewChild,
16043
+ args: ['scroll', { static: true }]
16044
+ }] } });
16045
+
14835
16046
  const STORAGE_PREFIX = 'feeding-profile::';
14836
16047
  const INITIAL_NOTIFICATION_VISIBLE = 2;
14837
16048
  class FeedingComponent {
@@ -14855,6 +16066,22 @@ class FeedingComponent {
14855
16066
  document.body.scrollTop = 0;
14856
16067
  window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
14857
16068
  }
16069
+ /**
16070
+ * Lịch sử cữ bú của `daysBack` ngày gần đây KHÔNG tính hôm nay
16071
+ * (mới → cũ, gộp tất cả cữ của các ngày đó). Dùng cho chat context
16072
+ * để trợ lý có bối cảnh xu hướng bú mấy ngày qua.
16073
+ */
16074
+ recentFeedingLogs(daysBack) {
16075
+ const today = this.todayDateStr();
16076
+ const cutoff = this.dateStrDaysAgo(daysBack);
16077
+ return this.logs()
16078
+ .filter((l) => l.date < today && l.date >= cutoff)
16079
+ .sort((a, b) => {
16080
+ if (a.date !== b.date)
16081
+ return b.date.localeCompare(a.date);
16082
+ return b.time.localeCompare(a.time);
16083
+ });
16084
+ }
14858
16085
  constructor() {
14859
16086
  this.route = inject(ActivatedRoute);
14860
16087
  this.destroyRef = inject(DestroyRef);
@@ -14899,6 +16126,11 @@ class FeedingComponent {
14899
16126
  * Cột user chỉ để biết ai log — không lọc theo user khi lấy giá trị này.
14900
16127
  */
14901
16128
  this.latestWeightKgFromSheet = signal(undefined, ...(ngDevMode ? [{ debugName: "latestWeightKgFromSheet" }] : /* istanbul ignore next */ []));
16129
+ /**
16130
+ * Toàn bộ bản ghi cân nặng + chiều cao từ sheet Weight (mới → cũ).
16131
+ * Dùng cho chat context — trợ lý có thể thấy lịch sử cân/cao gần đây.
16132
+ */
16133
+ this.weightLogs = signal([], ...(ngDevMode ? [{ debugName: "weightLogs" }] : /* istanbul ignore next */ []));
14902
16134
  this.editing = signal(true, ...(ngDevMode ? [{ debugName: "editing" }] : /* istanbul ignore next */ []));
14903
16135
  this.now = signal(new Date(), ...(ngDevMode ? [{ debugName: "now" }] : /* istanbul ignore next */ []));
14904
16136
  // ===== Feeding log state =====
@@ -14938,6 +16170,54 @@ class FeedingComponent {
14938
16170
  this.momRouteOpen = signal(false, ...(ngDevMode ? [{ debugName: "momRouteOpen" }] : /* istanbul ignore next */ []));
14939
16171
  /** Subroute Tài liệu (full-screen, mở từ Settings menu). */
14940
16172
  this.documentsRouteOpen = signal(false, ...(ngDevMode ? [{ debugName: "documentsRouteOpen" }] : /* istanbul ignore next */ []));
16173
+ /** Subroute Trợ lý AI (full-screen, mở từ nút chat trên hero). */
16174
+ this.chatRouteOpen = signal(false, ...(ngDevMode ? [{ debugName: "chatRouteOpen" }] : /* istanbul ignore next */ []));
16175
+ /** True khi chưa cấu hình NG_APP_HF_INFERENCE_URL — chat shell render callout thay vì composer. */
16176
+ this.chatDisabled = computed(() => !this.feedingConfig.hfInferenceUrl, ...(ngDevMode ? [{ debugName: "chatDisabled" }] : /* istanbul ignore next */ []));
16177
+ /** Snapshot dữ liệu bé truyền vào ChatShell — đọc từ các signals hiện có. */
16178
+ this.chatContext = computed(() => {
16179
+ const age = this.ageBreakdown();
16180
+ const ageLabel = age
16181
+ ? `${age.years > 0 ? age.years + ' năm ' : ''}${age.months} tháng ${age.weeksInMonth} tuần`.trim()
16182
+ : 'chưa rõ';
16183
+ const today = this.todayLogs();
16184
+ const stats = this.todayStats();
16185
+ const target = this.nutritionTarget();
16186
+ return {
16187
+ babyName: this.profile()?.babyName ?? '',
16188
+ ageLabel,
16189
+ ageInDays: this.ageInDays(),
16190
+ weightKg: this.latestWeightKgFromSheet(),
16191
+ todayLogs: today,
16192
+ todayTotalMl: stats.total,
16193
+ todayCount: stats.count,
16194
+ nextFeedTime: this.prediction()?.nextTime ?? null,
16195
+ nutritionTargetLabel: target
16196
+ ? `${target.perKgFactor} ml/kg/ngày ≈ ${target.dailyMlMin}–${target.dailyMlMax} ml`
16197
+ : null,
16198
+ upcomingEvents: this.eventLogService
16199
+ .events()
16200
+ .filter((e) => {
16201
+ // Chỉ lấy sự kiện từ ngày hiện tại trở đi (so theo ngày, bỏ qua giờ).
16202
+ const dt = EventLogService.eventDateTime(e);
16203
+ if (!dt)
16204
+ return false;
16205
+ const eventDay = new Date(dt.getFullYear(), dt.getMonth(), dt.getDate()).getTime();
16206
+ const todayDay = new Date(this.now().getFullYear(), this.now().getMonth(), this.now().getDate()).getTime();
16207
+ return eventDay >= todayDay;
16208
+ })
16209
+ .map((e) => ({
16210
+ title: e.title,
16211
+ dateLabel: e.date,
16212
+ time: e.time,
16213
+ place: e.place,
16214
+ })),
16215
+ recentWeightLogs: this.weightLogs(),
16216
+ recentFeedingLogs: this.recentFeedingLogs(3),
16217
+ unreadNotifications: this.visibleNotifications().length,
16218
+ user: this.user(),
16219
+ };
16220
+ }, ...(ngDevMode ? [{ debugName: "chatContext" }] : /* istanbul ignore next */ []));
14941
16221
  this.acknowledgeAllConfirmDialogOpen = signal(false, ...(ngDevMode ? [{ debugName: "acknowledgeAllConfirmDialogOpen" }] : /* istanbul ignore next */ []));
14942
16222
  /** Ngày đang xem trên card lịch sử (mặc định: hôm qua). */
14943
16223
  this.ageInDays = computed(() => {
@@ -15233,15 +16513,16 @@ class FeedingComponent {
15233
16513
  this.activityLogService.setRefreshInterval(s.activityLogRefreshMinutes);
15234
16514
  setTimeout(() => this.loadFeedingSettings(), 600);
15235
16515
  }
15236
- /** Tải cân mới nhất từ sheet Weight (cùng nguồn với tab Cân nặng). */
16516
+ /** Tải toàn bộ bản ghi cân nặng từ sheet Weight (cùng nguồn với tab Cân nặng). */
15237
16517
  loadWeightLogs() {
15238
16518
  this.weightLogService.getLogs().subscribe({
15239
16519
  next: (rows) => {
15240
- const latest = rows[0];
15241
- this.latestWeightKgFromSheet.set(latest?.weightKg);
16520
+ this.weightLogs.set(rows);
16521
+ this.latestWeightKgFromSheet.set(rows[0]?.weightKg);
15242
16522
  },
15243
16523
  error: (err) => {
15244
16524
  console.error(err);
16525
+ this.weightLogs.set([]);
15245
16526
  this.latestWeightKgFromSheet.set(undefined);
15246
16527
  },
15247
16528
  });
@@ -15292,6 +16573,13 @@ class FeedingComponent {
15292
16573
  return;
15293
16574
  this.notifRouteOpen.set(false);
15294
16575
  }
16576
+ // ── Trợ lý AI subroute ──
16577
+ openChatRoute() {
16578
+ this.chatRouteOpen.set(true);
16579
+ }
16580
+ closeChatRoute() {
16581
+ this.chatRouteOpen.set(false);
16582
+ }
15295
16583
  // ── Settings float menu ──
15296
16584
  openSettingsMenu() {
15297
16585
  this.settingsMenuOpen.set(true);
@@ -15821,7 +17109,7 @@ class FeedingComponent {
15821
17109
  }).format(kg);
15822
17110
  }
15823
17111
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: FeedingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
15824
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: FeedingComponent, isStandalone: true, selector: "app-feeding", viewQueries: [{ propertyName: "feedingPageRef", first: true, predicate: ["feedingPage"], descendants: true, static: true }, { propertyName: "documentsCmp", first: true, predicate: DocumentsComponent, descendants: true }, { propertyName: "medicalCmp", first: true, predicate: MedicalHistoryComponent, descendants: true }, { propertyName: "weightCmp", first: true, predicate: WeightComponent, descendants: true }, { propertyName: "feedingDialogs", first: true, predicate: ["feedingDialogs"], descendants: true }], ngImport: i0, template: "<div class=\"feeding-root\">\n <div class=\"feeding-page\" #feedingPage>\n <div class=\"backdrop\"></div>\n\n <header class=\"hero\" [class.hero--profile-merged]=\"profile() && !editing() && ageBreakdown()\">\n @if (profile() && !editing() && ageBreakdown(); as age) {\n <!-- \u2550\u2550 REDESIGNED HERO \u2550\u2550 -->\n <app-hero-header\n [profile]=\"profile()!\"\n [age]=\"age\"\n [user]=\"user()\"\n [weightLabel]=\"profileHeroWeightLabel()\"\n [isAnyLoading]=\"isAnyLoading()\"\n [showRefresh]=\"bottomTab() !== 'schedule'\"\n (openMenu)=\"openSettingsMenu()\"\n (refresh)=\"refreshAll()\"\n >\n <app-activity-log slot=\"activity-log\" (activityChanged)=\"onActivityChanged()\"></app-activity-log>\n </app-hero-header>\n\n <app-hero-stats-strip\n [currentTime]=\"currentTimeStr\"\n [dateLabel]=\"heroDateLabel\"\n [nextFeedTime]=\"prediction()?.nextTime ?? null\"\n [nextFeedCountdown]=\"heroNextFeedCountdown()\"\n [weightLabel]=\"profileHeroWeightLabel()\"\n [whoStatus]=\"nutritionTarget()?.ageLabel ?? null\"\n ></app-hero-stats-strip>\n\n <div class=\"hero-notif-wrap\">\n <app-notification-banner\n [notifications]=\"visibleNotifications()\"\n [saving]=\"notificationSaving()\"\n [currentUser]=\"user()\"\n [dialogOpen]=\"notifDialogOpen()\"\n (openDialog)=\"openNotificationRoute()\"\n (closeDialog)=\"notifDialogOpen.set(false)\"\n (acknowledge)=\"acknowledgeNotification($event)\"\n (acknowledgeAll)=\"notifDialogOpen.set(false); openAcknowledgeAllConfirmDialog()\"\n (delete)=\"deleteNotification($event)\"\n (openComposer)=\"notifDialogOpen.set(false); openNotificationComposerDialog()\"\n ></app-notification-banner>\n </div>\n\n } @else {\n <!-- \u2500\u2500 Fallback: no profile / editing \u2500\u2500 -->\n <div class=\"hero-inner\">\n <div class=\"hero-brand\">\n <div class=\"hero-title-row\">\n <div class=\"hero-title\">\n <div class=\"emoji\" aria-hidden=\"true\">\uD83D\uDC76</div>\n <div class=\"hero-text\">\n <h1>B\u00E9 y\u00EAu c\u1EE7a b\u1EA1n</h1>\n <p class=\"hero-userline\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <strong>{{ user() }}</strong>\n </p>\n </div>\n </div>\n @if (profile() && !editing()) {\n <div class=\"hero-actions\">\n <app-activity-log (activityChanged)=\"onActivityChanged()\"></app-activity-log>\n <button\n class=\"btn icon-btn\"\n type=\"button\"\n (click)=\"feedingDialogs.openFeedingSettingsDialog()\"\n title=\"C\u00E0i \u0111\u1EB7t\"\n aria-label=\"C\u00E0i \u0111\u1EB7t c\u1EEF b\u00FA\"\n >\n <i class=\"pi pi-sliders-h\"></i>\n </button>\n @if (bottomTab() !== 'schedule') {\n <button\n class=\"btn icon-btn\"\n type=\"button\"\n (click)=\"refreshAll()\"\n [disabled]=\"isAnyLoading()\"\n [title]=\"\n isAnyLoading() ? '\u0110ang t\u1EA3i\u2026' : 'T\u1EA3i l\u1EA1i C\u1EEF b\u00FA, C\u00E2n, L\u1ECBch, Y t\u1EBF, T\u00E0i li\u1EC7u'\n \"\n aria-label=\"T\u1EA3i l\u1EA1i C\u1EEF b\u00FA, Th\u1EC3 tr\u1EA1ng, L\u1ECBch, Ti\u1EC1n s\u1EED y t\u1EBF v\u00E0 T\u00E0i li\u1EC7u\"\n >\n <i class=\"pi pi-refresh\" [class.spin]=\"isAnyLoading()\"></i>\n </button>\n }\n </div>\n }\n </div>\n </div>\n\n <div class=\"hero-datetime\" aria-live=\"polite\">\n <div class=\"hero-datetime-strip\">\n <div class=\"hero-datetime-strip__block hero-datetime-strip__block--date\">\n <i class=\"pi pi-calendar\" aria-hidden=\"true\"></i>\n <span class=\"hero-datetime-strip__wd\">{{ heroWeekday }}</span>\n <time class=\"hero-datetime-strip__date\" [attr.datetime]=\"todayDateStr()\">{{\n heroDateNumeric\n }}</time>\n </div>\n <span class=\"hero-datetime-strip__divider\" aria-hidden=\"true\"></span>\n <div class=\"hero-datetime-strip__block hero-datetime-strip__block--time\">\n <i class=\"pi pi-clock\" aria-hidden=\"true\"></i>\n <span class=\"hero-datetime-strip__clock\">{{ currentTimeStr }}</span>\n </div>\n </div>\n </div>\n\n <section class=\"hero-notification\" aria-label=\"Th\u00F4ng b\u00E1o n\u1ED9i b\u1ED9\">\n <!-- watermark background icons -->\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-bell\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-megaphone\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-comments\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--send\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-send\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--star\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-star\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--bolt\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-bolt\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--heart\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-heart\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--info\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-info-circle\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--check\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-check-circle\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--eye\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-eye\"></i>\n </span>\n\n <div class=\"hero-notification__head\">\n <label class=\"hero-notification__composer-label\" for=\"hero-notification-input\">\n <i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i>\n <span>Th\u00F4ng b\u00E1o</span>\n @if (visibleNotifications().length > 0) {\n <span class=\"hero-notification__unread-badge\">{{\n visibleNotifications().length\n }}</span>\n }\n </label>\n <div class=\"hero-notification__head-actions\">\n <button\n type=\"button\"\n class=\"hero-notification__mark-all\"\n (click)=\"openAcknowledgeAllConfirmDialog()\"\n [disabled]=\"notificationSaving() || visibleNotifications().length === 0\"\n title=\"\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc\"\n >\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n \u0110\u00E3 \u0111\u1ECDc t\u1EA5t c\u1EA3\n </button>\n <button\n type=\"button\"\n class=\"hero-notification__add\"\n (click)=\"openNotificationComposerDialog()\"\n aria-label=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n title=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n @if (displayedNotifications().length > 0) {\n <ul class=\"hero-notification__list\">\n @for (notice of displayedNotifications(); track notice) {\n <li class=\"hero-notification__item\">\n <div class=\"hero-notification__avatar\" aria-hidden=\"true\">\n {{ notice.user | slice: 0 : 2 | uppercase }}\n </div>\n <div class=\"hero-notification__body\">\n <div class=\"hero-notification__body-head\">\n <span class=\"hero-notification__author\">{{ notice.user }}</span>\n </div>\n <p class=\"hero-notification__content\">{{ notice.content }}</p>\n @if (notice.createdAt) {\n <span class=\"hero-notification__created\">{{\n formatNotificationCreatedAt(notice.createdAt)\n }}</span>\n }\n </div>\n <div class=\"hero-notification__item-actions\">\n <button\n type=\"button\"\n class=\"hero-notification__ack-top\"\n (click)=\"acknowledgeNotification(notice)\"\n [disabled]=\"notificationSaving()\"\n aria-label=\"\u0110\u00E3 \u0111\u1ECDc th\u00F4ng b\u00E1o\"\n title=\"\u0110\u00E3 \u0111\u1ECDc\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n @if (canDeleteNotification(notice)) {\n <button\n type=\"button\"\n class=\"hero-notification__delete\"\n (click)=\"deleteNotification(notice)\"\n [disabled]=\"notificationSaving()\"\n aria-label=\"X\u00F3a th\u00F4ng b\u00E1o\"\n title=\"X\u00F3a th\u00F4ng b\u00E1o\"\n >\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </li>\n }\n </ul>\n } @else {\n <div class=\"hero-notification__empty\">\n <i class=\"pi pi-bell hero-notification__empty-icon\" aria-hidden=\"true\"></i>\n <span class=\"hero-notification__empty-title\">Kh\u00F4ng c\u00F3 th\u00F4ng b\u00E1o m\u1EDBi</span>\n <span class=\"hero-notification__empty-sub\"\n >M\u1ECDi th\u1EE9 \u0111\u1EC1u \u1ED5n. Th\u00F4ng b\u00E1o m\u1EDBi s\u1EBD xu\u1EA5t hi\u1EC7n \u1EDF \u0111\u00E2y.</span\n >\n </div>\n }\n\n @if (hiddenNotificationCount() > 0) {\n <button\n type=\"button\"\n class=\"hero-notification__more\"\n (click)=\"openNotificationListDialog()\"\n >\n Xem th\u00EAm {{ hiddenNotificationCount() }} th\u00F4ng b\u00E1o \u2192\n </button>\n }\n </section>\n\n </div>\n } <!-- end @else no-profile -->\n </header>\n\n <!-- \u2550\u2550 NOTIFICATION DIALOGS \u2014 rendered outside <header> to avoid overflow/stacking-context clipping \u2550\u2550 -->\n @if (notificationComposerDialogOpen()) {\n <div\n class=\"dialog-overlay dialog-overlay--front\"\n (click)=\"closeNotificationComposerDialog()\"\n >\n <div\n class=\"dialog hero-notification-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\" aria-hidden=\"true\"><i class=\"pi pi-bell\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\" aria-hidden=\"true\"><i class=\"pi pi-megaphone\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--send\" aria-hidden=\"true\"><i class=\"pi pi-send\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--star\" aria-hidden=\"true\"><i class=\"pi pi-star\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\" aria-hidden=\"true\"><i class=\"pi pi-comments\"></i></span>\n\n <div class=\"dialog-head hero-notification-dialog__head\">\n <div class=\"hero-notification-dialog__title-group\">\n <div class=\"hero-notification-dialog__icon-wrap\">\n <i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i>\n </div>\n <div>\n <h2 class=\"hero-notification-dialog__title\">T\u1EA1o th\u00F4ng b\u00E1o</h2>\n <p class=\"hero-notification-dialog__subtitle\">Th\u00F4ng b\u00E1o s\u1EBD hi\u1EC3n th\u1ECB cho to\u00E0n b\u1ED9 th\u00E0nh vi\u00EAn</p>\n </div>\n </div>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeNotificationComposerDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <div class=\"hero-notification__composer-panel\">\n <div class=\"hero-notification__composer-row\">\n <div class=\"hero-notification__input-wrap\">\n <textarea\n id=\"hero-notification-input\"\n class=\"hero-notification__input\"\n [value]=\"notificationDraft()\"\n (input)=\"updateNotificationDraft($any($event.target).value)\"\n [disabled]=\"notificationSaving()\"\n maxlength=\"300\"\n placeholder=\"Nh\u1EADp n\u1ED9i dung th\u00F4ng b\u00E1o cho m\u1ECDi ng\u01B0\u1EDDi...\"\n aria-label=\"N\u1ED9i dung th\u00F4ng b\u00E1o\"\n ></textarea>\n <div class=\"hero-notification__char-ring\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 36 36\">\n <circle class=\"hero-notification__char-ring-track\" cx=\"18\" cy=\"18\" r=\"15\" />\n <circle class=\"hero-notification__char-ring-fill\" cx=\"18\" cy=\"18\" r=\"15\"\n [style.stroke-dashoffset]=\"94 - (notificationDraft().trim().length / 300) * 94\" />\n </svg>\n <span class=\"hero-notification__char-count\">{{ notificationDraft().trim().length }}</span>\n </div>\n </div>\n </div>\n <div class=\"hero-notification__composer-actions\">\n <button type=\"button\" class=\"btn ghost hero-notification__cancel\"\n (click)=\"closeNotificationComposerDialog()\" [disabled]=\"notificationSaving()\">H\u1EE7y</button>\n <button type=\"button\" class=\"btn hero-notification__send\"\n (click)=\"createNotification()\"\n [disabled]=\"notificationSaving() || !notificationDraft().trim()\">\n <i class=\"pi pi-send\"></i>\n <span>G\u1EEDi th\u00F4ng b\u00E1o</span>\n </button>\n </div>\n </div>\n @if (notificationError()) {\n <p class=\"hero-notification__error\">{{ notificationError() }}</p>\n }\n </div>\n </div>\n }\n\n @if (notificationListDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeNotificationListDialog()\">\n <div class=\"dialog hero-notification-list-dialog\" role=\"dialog\" aria-modal=\"true\"\n aria-label=\"Danh s\u00E1ch th\u00F4ng b\u00E1o\" (click)=\"$event.stopPropagation()\">\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\" aria-hidden=\"true\"><i class=\"pi pi-bell\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\" aria-hidden=\"true\"><i class=\"pi pi-megaphone\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\" aria-hidden=\"true\"><i class=\"pi pi-comments\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--star\" aria-hidden=\"true\"><i class=\"pi pi-star\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--check\" aria-hidden=\"true\"><i class=\"pi pi-check-circle\"></i></span>\n\n <div class=\"dialog-head hero-notification-list-dialog__head\">\n <div class=\"hero-notification-dialog__title-group\">\n <div class=\"hero-notification-dialog__icon-wrap\"><i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i></div>\n <div>\n <h2 class=\"hero-notification-list-dialog__title\">To\u00E0n b\u1ED9 th\u00F4ng b\u00E1o</h2>\n <p class=\"hero-notification-dialog__subtitle\">{{ visibleNotifications().length }} th\u00F4ng b\u00E1o</p>\n </div>\n </div>\n <div class=\"hero-notification-list-dialog__head-actions\">\n <button type=\"button\" class=\"hero-notification__mark-all\"\n (click)=\"openAcknowledgeAllConfirmDialog()\"\n [disabled]=\"notificationSaving() || visibleNotifications().length === 0\"\n title=\"\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc\">\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i> \u0110\u00E3 \u0111\u1ECDc t\u1EA5t c\u1EA3\n </button>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeNotificationListDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"hero-notification-list-dialog__body\">\n @if (visibleNotifications().length > 0) {\n <ul class=\"hero-notification__list\">\n @for (notice of visibleNotifications(); track notice) {\n <li class=\"hero-notification__item\">\n <div class=\"hero-notification__avatar\" aria-hidden=\"true\">{{ notice.user | slice: 0 : 2 | uppercase }}</div>\n <div class=\"hero-notification__body\">\n <div class=\"hero-notification__body-head\">\n <span class=\"hero-notification__author\">{{ notice.user }}</span>\n </div>\n <p class=\"hero-notification__content\">{{ notice.content }}</p>\n @if (notice.createdAt) {\n <span class=\"hero-notification__created\">{{ formatNotificationCreatedAt(notice.createdAt) }}</span>\n }\n </div>\n <div class=\"hero-notification__item-actions\">\n <button type=\"button\" class=\"hero-notification__ack-top\"\n (click)=\"acknowledgeNotification(notice)\" [disabled]=\"notificationSaving()\"\n aria-label=\"\u0110\u00E3 \u0111\u1ECDc th\u00F4ng b\u00E1o\" title=\"\u0110\u00E3 \u0111\u1ECDc\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n @if (canDeleteNotification(notice)) {\n <button type=\"button\" class=\"hero-notification__delete\"\n (click)=\"deleteNotification(notice)\" [disabled]=\"notificationSaving()\"\n aria-label=\"X\u00F3a th\u00F4ng b\u00E1o\" title=\"X\u00F3a th\u00F4ng b\u00E1o\">\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </li>\n }\n </ul>\n } @else {\n <div class=\"hero-notification__empty\">\n <i class=\"pi pi-bell hero-notification__empty-icon\" aria-hidden=\"true\"></i>\n <span class=\"hero-notification__empty-title\">Kh\u00F4ng c\u00F3 th\u00F4ng b\u00E1o m\u1EDBi</span>\n <span class=\"hero-notification__empty-sub\">M\u1ECDi th\u1EE9 \u0111\u1EC1u \u1ED5n. Th\u00F4ng b\u00E1o m\u1EDBi s\u1EBD xu\u1EA5t hi\u1EC7n \u1EDF \u0111\u00E2y.</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n @if (acknowledgeAllConfirmDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeAcknowledgeAllConfirmDialog()\">\n <div class=\"dialog ack-all-confirm-dialog\" role=\"alertdialog\" aria-modal=\"true\"\n aria-labelledby=\"ack-all-confirm-title\" (click)=\"$event.stopPropagation()\">\n <div class=\"ack-all-confirm-dialog__icon-wrap\" aria-hidden=\"true\"><i class=\"pi pi-check-circle\"></i></div>\n <h2 id=\"ack-all-confirm-title\" class=\"ack-all-confirm-dialog__title\">\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc?</h2>\n <p class=\"ack-all-confirm-dialog__desc\">\n T\u1EA5t c\u1EA3 {{ visibleNotifications().length }} th\u00F4ng b\u00E1o s\u1EBD \u0111\u01B0\u1EE3c \u0111\u00E1nh d\u1EA5u \u0111\u00E3 \u0111\u1ECDc v\u00E0 \u1EA9n kh\u1ECFi danh s\u00E1ch.\n </p>\n <div class=\"ack-all-confirm-dialog__actions\">\n <button type=\"button\" class=\"btn ghost\" (click)=\"closeAcknowledgeAllConfirmDialog()\" [disabled]=\"notificationSaving()\">H\u1EE7y</button>\n <button type=\"button\" class=\"btn ack-all-confirm-dialog__confirm-btn\"\n (click)=\"confirmAcknowledgeAll()\" [disabled]=\"notificationSaving()\">\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i> X\u00E1c nh\u1EADn\n </button>\n </div>\n </div>\n </div>\n }\n\n <main\n class=\"content\"\n [class.is-documents]=\"bottomTab() === 'documents'\"\n [class.is-weight]=\"bottomTab() === 'weight'\"\n [class.is-schedule]=\"bottomTab() === 'schedule'\"\n [class.is-mom]=\"bottomTab() === 'mom'\"\n [class.is-medical]=\"bottomTab() === 'medical'\"\n >\n <!--\n ============ TAB PANES ============\n D\u00F9ng `[hidden]` thay v\u00EC `*ngIf` \u0111\u1EC3 c\u00E1c tab c\u00F9ng gi\u1EEF tr\u1EA1ng th\u00E1i khi\n user qua l\u1EA1i: scroll position, search query \u0111ang g\u00F5, viewMode, folder\n \u0111ang \u0111\u1EE9ng, file \u0111ang ch\u1ECDn, draft \u0111ang nh\u1EADp\u2026 \u0111\u1EC1u kh\u00F4ng b\u1ECB reset. H\u1EC7\n qu\u1EA3: `<app-documents>` \u0111\u01B0\u1EE3c mount 1 l\u1EA7n \u1EDF app load \u2014 `loadEntries()`\n ch\u1EA1y 1 l\u1EA7n, c\u00E1c l\u1EA7n switch tab k\u1EBF ti\u1EBFp kh\u00F4ng g\u1ECDi API th\u00EAm.\n -->\n <!-- ============ TAB: DOCUMENTS \u2014 \u0111\u00E3 chuy\u1EC3n sang subroute (m\u1EDF t\u1EEB Settings menu) ============ -->\n\n <!-- ============ TAB: WEIGHT ============ -->\n <div class=\"tab-pane tab-pane--weight\" [hidden]=\"bottomTab() !== 'weight'\">\n <app-weight\n [user]=\"user()\"\n [birthDate]=\"profile()?.birthDate\"\n [gender]=\"profile()?.gender\"\n [babyName]=\"profile()?.babyName\"\n ></app-weight>\n </div>\n\n <!-- ============ TAB: L\u1ECACH \u2014 Google Sheet tab \"Event\" ============ -->\n <div class=\"tab-pane tab-pane--schedule\" [hidden]=\"bottomTab() !== 'schedule'\">\n <app-feeding-schedule [user]=\"user()\"></app-feeding-schedule>\n </div>\n\n <!-- ============ TAB: TI\u1EC0N S\u1EEC Y T\u1EBE \u2014 Medical history V2 ============ -->\n <div class=\"tab-pane tab-pane--medical\" [hidden]=\"bottomTab() !== 'medical'\">\n <app-medical-history\n [user]=\"user()\"\n (openExplorerFile)=\"openMedicalAttachmentInDocuments($event)\"\n ></app-medical-history>\n </div>\n\n <!-- ============ TAB: M\u1EB8 \u2014 \u0111\u00E3 chuy\u1EC3n sang subroute (m\u1EDF t\u1EEB Settings menu) ============ -->\n\n <!-- ============ TAB: FEEDING ============ -->\n <div class=\"tab-pane tab-pane--feeding\" [hidden]=\"bottomTab() !== 'feeding'\">\n <app-feeding-profile\n [user]=\"user()\"\n [profile]=\"profile()\"\n [draft]=\"draft()\"\n [editing]=\"editing()\"\n [maxBirthDate]=\"maxBirthDate\"\n (save)=\"save()\"\n (cancelEdit)=\"cancelEdit()\"\n (startEdit)=\"startEdit()\"\n (clearProfile)=\"clearProfile()\"\n (draftNameChange)=\"updateDraftName($event)\"\n (draftBirthChange)=\"updateDraftBirth($event)\"\n (draftGenderChange)=\"setDraftGender($event)\"\n />\n\n @if (profile() && !editing() && ageBreakdown()) {\n <app-feeding-daily\n [logs]=\"logs()\"\n [feedingSettings]=\"feedingSettings()\"\n [now]=\"now()\"\n [nutritionTarget]=\"nutritionTarget()\"\n [user]=\"user()\"\n [syncMessage]=\"syncMessage()\"\n [syncError]=\"syncError()\"\n [logDialogOpen]=\"logDialogOpen()\"\n [loadingLogs]=\"loadingLogs()\"\n [refreshToken]=\"dailyRefreshToken()\"\n (logsChanged)=\"onFeedingLogsChanged()\"\n (bottlePrepChange)=\"bottlePrep.set($event)\"\n (editLog)=\"feedingDialogs.openEditDialog($event)\"\n (historyOpen)=\"feedingDialogs.openHistoryDialog($event.filter, $event.dateStr)\"\n (feedRowClick)=\"feedingDialogs.onFeedRowClick($event)\"\n >\n <app-feeding-charts\n data-feeding-charts\n [logs]=\"logs()\"\n [now]=\"now()\"\n [nutritionTarget]=\"nutritionTarget()\"\n />\n </app-feeding-daily>\n <app-feeding-nutrition\n [nutritionTarget]=\"nutritionTarget()\"\n [todayStats]=\"todayStats()\"\n [now]=\"now()\"\n [latestWeightKg]=\"latestWeightKgFromSheet()\"\n [editing]=\"editing()\"\n (goToWeight)=\"setBottomTab('weight')\"\n />\n }\n\n <!-- ============ FAB \u00AB Ghi c\u1EEF b\u00FA \u00BB c\u0169 \u0111\u00E3 \u0111\u01B0\u1EE3c thay b\u1EB1ng FAB gi\u1EEFa bottom-nav ============ -->\n </div>\n <!-- /.tab-pane--feeding -->\n </main>\n </div>\n <!-- /.feeding-page -->\n\n <!-- ============ BOTTOM NAVIGATION (C\u1EEF b\u00FA \u00B7 Th\u1EC3 tr\u1EA1ng \u00B7 + \u00B7 L\u1ECBch \u00B7 Y t\u1EBF) ============ -->\n <nav\n class=\"bottom-nav\"\n role=\"tablist\"\n aria-label=\"\u0110i\u1EC1u h\u01B0\u1EDBng ch\u00EDnh\"\n >\n <div class=\"bn-side bn-side--left\">\n @for (tab of navLeftTabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"bn-item\"\n role=\"tab\"\n [attr.aria-selected]=\"bottomTab() === tab.id\"\n [class.active]=\"bottomTab() === tab.id\"\n (click)=\"setBottomTab(tab.id)\"\n >\n <span class=\"bn-icon-wrap\">\n <i class=\"pi {{ tab.icon }} bn-icon\" aria-hidden=\"true\"></i>\n </span>\n <span class=\"bn-label\">{{ tab.label }}</span>\n </button>\n }\n </div>\n\n <button\n type=\"button\"\n class=\"bn-fab\"\n (click)=\"feedingDialogs.openLogDialog()\"\n [disabled]=\"!profile() || editing()\"\n [title]=\"(!profile() || editing()) ? 'Ch\u1ECDn b\u00E9 tr\u01B0\u1EDBc khi ghi c\u1EEF b\u00FA' : 'Ghi nh\u1EADn c\u1EEF b\u00FA m\u1EDBi'\"\n aria-label=\"Ghi nh\u1EADn c\u1EEF b\u00FA\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n\n <div class=\"bn-side bn-side--right\">\n @for (tab of navRightTabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"bn-item\"\n role=\"tab\"\n [attr.aria-selected]=\"bottomTab() === tab.id\"\n [class.active]=\"bottomTab() === tab.id\"\n (click)=\"setBottomTab(tab.id)\"\n >\n <span class=\"bn-icon-wrap\">\n <i class=\"pi {{ tab.icon }} bn-icon\" aria-hidden=\"true\"></i>\n </span>\n <span class=\"bn-label\">{{ tab.label }}</span>\n </button>\n }\n </div>\n </nav>\n\n <!-- ============ NOTIFICATION SUBROUTE (full-screen) ============ -->\n @if (notifRouteOpen()) {\n <app-notification-list\n [notifications]=\"allNotifications()\"\n [currentUser]=\"user()\"\n [saving]=\"notificationSaving()\"\n (back)=\"closeNotificationRoute()\"\n (acknowledge)=\"acknowledgeNotification($event)\"\n (acknowledgeAll)=\"openAcknowledgeAllConfirmDialog()\"\n (delete)=\"deleteNotification($event)\"\n (openComposer)=\"openNotificationComposerDialog()\"\n />\n }\n\n <!-- ============ SETTINGS FLOAT MENU (full-screen) ============ -->\n @if (settingsMenuOpen()) {\n <app-settings-menu\n [appName]=\"appInfo.name\"\n [appVersion]=\"appInfo.version\"\n [showDocuments]=\"explorerEnabled\"\n [unreadCount]=\"visibleNotifications().length\"\n (close)=\"closeSettingsMenu()\"\n (select)=\"onSettingsMenuSelect($event)\"\n />\n }\n\n <!-- ============ M\u1EB8 SUBROUTE (full-screen) ============ -->\n @if (momRouteOpen()) {\n <app-subroute-shell\n title=\"M\u1EB9\"\n (back)=\"closeMomRoute()\"\n >\n <app-feeding-mom\n [profile]=\"profile()\"\n [editing]=\"editing()\"\n (goToFeeding)=\"closeMomRoute(); setBottomTab('feeding')\"\n ></app-feeding-mom>\n </app-subroute-shell>\n }\n\n <!-- ============ T\u00C0I LI\u1EC6U SUBROUTE (full-screen) ============ -->\n @if (documentsRouteOpen()) {\n <app-subroute-shell\n title=\"T\u00E0i li\u1EC7u\"\n (back)=\"closeDocumentsRoute()\"\n >\n <app-documents></app-documents>\n </app-subroute-shell>\n }\n\n <!-- About -->\n @if (aboutDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeAboutDialog()\">\n <div\n class=\"dialog about-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"feeding-about-title\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"dialog-head about-dialog__head\">\n <h2 id=\"feeding-about-title\" class=\"about-dialog__title\">\n <i class=\"pi pi-info-circle\" aria-hidden=\"true\"></i>\n About\n </h2>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeAboutDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <dl class=\"about-dialog__meta\">\n <div class=\"about-dialog__row\">\n <dt>\u1EE8ng d\u1EE5ng</dt>\n <dd>{{ appInfo.name }}</dd>\n </div>\n <div class=\"about-dialog__row\">\n <dt>Phi\u00EAn b\u1EA3n</dt>\n <dd>\n <code>{{ appInfo.version }}</code>\n </dd>\n </div>\n </dl>\n <div class=\"dialog-actions\">\n <button type=\"button\" class=\"btn primary\" (click)=\"closeAboutDialog()\">\u0110\u00F3ng</button>\n </div>\n </div>\n </div>\n }\n\n <!-- Nh\u1EAFc s\u1EF1 ki\u1EC7n l\u1ECBch (sheet Event + Settings) -->\n @if (eventReminderDialogOpen() && scheduleReminderEvents().length > 0) {\n <div\n class=\"dialog-overlay dialog-overlay--front dialog-overlay--event-reminder\"\n (click)=\"closeEventReminderDialog()\"\n >\n <div\n class=\"dialog event-reminder-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"dialog-head event-reminder-dialog__head\">\n <h2 class=\"event-reminder-dialog__title\">\n <i class=\"pi pi-bell\" aria-hidden=\"true\"></i>\n B\u1EA1n c\u00F3 l\u1ECBch s\u1EAFp t\u1EDBi\n </h2>\n <button\n type=\"button\"\n class=\"dialog-close\"\n (click)=\"closeEventReminderDialog()\"\n aria-label=\"\u0110\u00F3ng\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <ul class=\"event-reminder-list\">\n @for (ev of scheduleReminderEvents(); track ev) {\n <li>\n <article class=\"event-reminder-card\">\n <h3 class=\"event-reminder-card__title\">{{ ev.title }}</h3>\n <p class=\"event-reminder-card__datetime\">\n <span class=\"event-reminder-card__date\">{{ formatReminderEventWhen(ev) }}</span>\n <span class=\"event-reminder-card__sep\" aria-hidden=\"true\"> \u2013 </span>\n <span class=\"event-reminder-card__hour\">{{\n formatReminderEventTime(ev.time)\n }}</span>\n </p>\n @if (ev.place) {\n <p class=\"event-reminder-card__place\">\n <i class=\"pi pi-map-marker\" aria-hidden=\"true\"></i>\n <span>{{ ev.place }}</span>\n </p>\n }\n @if (ev.note) {\n <div class=\"event-reminder-card__content-wrap\">\n <span class=\"event-reminder-card__content-label\">N\u1ED9i dung</span>\n <p class=\"event-reminder-card__content\">{{ ev.note }}</p>\n </div>\n }\n </article>\n </li>\n }\n </ul>\n <div class=\"dialog-actions event-reminder-actions\">\n <button\n type=\"button\"\n class=\"event-reminder-actions__link\"\n (click)=\"acknowledgeAllEventReminders()\"\n >\n Kh\u00F4ng nh\u1EAFc l\u1EA1i\n </button>\n <button\n type=\"button\"\n class=\"btn primary event-reminder-actions__primary\"\n (click)=\"skipEventReminderSession()\"\n >\n \u0110\u00E3 hi\u1EC3u\n </button>\n </div>\n </div>\n </div>\n }\n\n <app-feeding-dialogs\n #feedingDialogs\n [logs]=\"logs()\"\n [user]=\"user()\"\n [now]=\"now()\"\n [bottlePrep]=\"bottlePrep()\"\n [feedingSettings]=\"feedingSettings()\"\n [prediction]=\"prediction()\"\n [todayStats]=\"todayStats()\"\n [yesterdayStats]=\"yesterdayStats()\"\n [todayLogs]=\"todayLogs()\"\n [yesterdayLogs]=\"yesterdayLogs()\"\n [maxBirthDate]=\"maxBirthDate\"\n [syncError]=\"syncError()\"\n [syncMessage]=\"syncMessage()\"\n (logsChanged)=\"onFeedingLogsChanged()\"\n (settingsChanged)=\"onFeedingSettingsChanged($event)\"\n (syncErrorChange)=\"syncError.set($event)\"\n (syncMessageChange)=\"syncMessage.set($event)\"\n (logDialogOpenChange)=\"logDialogOpen.set($event)\"\n (bottlePrepClearRequested)=\"clearBottlePrep()\"\n />\n</div>\n<!-- /.feeding-root -->\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;position:absolute;inset:0;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;--bg: #f6f7fb;--surface: #ffffff;--border: #e6e8ef;--border-strong: #d1d5db;--primary: #5b6cff;--primary-2: #4c5cf0;--primary-soft: #eef0ff;--accent: #ff5c8a;--accent-soft: #ffe7ef;--mint: #10b981;--mint-soft: #d1fae5;--amber: #f59e0b;--amber-soft: #fef3c7;--rose: #ef4444;--rose-soft: #fee2e2;--text: #0f172a;--muted: #64748b;--muted-2: #94a3b8}.feeding-root{flex:1;min-height:0;width:100%;display:flex;flex-direction:column;position:relative}.feeding-root .bp-prep-user{font-weight:800;color:#0369a1;background:#0ea5e933;padding:0 5px;margin-right:2px;border-radius:5px;white-space:nowrap;transition:color .2s,background .2s}.feeding-root .bp-prep-time{font-weight:800;font-variant-numeric:tabular-nums;color:#0284c7;background:linear-gradient(180deg,#f0f9ff,#e0f2fe);border:1px solid rgba(14,165,233,.35);padding:1px 7px;margin-left:2px;border-radius:6px;white-space:nowrap;box-shadow:0 1px #ffffffa6 inset;transition:color .2s,background .2s,border-color .2s}.feeding-page{position:relative;flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;color:var(--text);padding-bottom:calc(170px + env(safe-area-inset-bottom,0px))}.backdrop{position:fixed;inset:0;background:var(--bg);z-index:-1}.hero-notif-wrap{padding:0 16px 8px}.hero{padding:0;background:#fffffff5;border-bottom:1px solid rgba(226,232,240,.9)}@media(max-width:640px){.hero{padding-top:calc(26px + env(safe-area-inset-top,0px));padding-bottom:10px}}.hero-inner{max-width:1100px;margin:0 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:14px 18px}.hero-brand{min-width:0}.hero-title-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0;width:100%}.hero-title{display:flex;align-items:center;gap:12px;min-width:0;flex:1}.hero-title .emoji{font-size:36px;line-height:1;flex-shrink:0;filter:drop-shadow(0 2px 4px rgba(15,23,42,.08))}@media(max-width:640px){.hero-title .emoji{font-size:32px}}.hero-title .hero-text{min-width:0}.hero-title h1{margin:0;font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.02em;line-height:1.2}@media(max-width:640px){.hero-title h1{font-size:17px}}.hero-title .hero-userline{margin:5px 0 0;display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px 6px;font-size:12.5px;color:var(--muted)}.hero-title .hero-userline i{font-size:12px;color:var(--primary);opacity:.9}.hero-title .hero-userline strong{color:var(--primary);font-weight:700;letter-spacing:.01em}.hero-title .hero-userline .hero-last-update{font-size:11px;color:#94a3b8;font-weight:400}.hero--profile-merged{background:var(--primary-soft);padding-bottom:10px;margin-bottom:8px}.hero-title--merged{align-items:flex-start}.hero-title--merged .emoji{font-size:30px}.hero-title--merged h1{font-size:18px;line-height:1.15}.hero-merged-head{display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px;min-width:0;row-gap:6px}.hero-age-chip{font-size:10.5px;font-weight:800;letter-spacing:.04em;text-transform:lowercase;color:var(--primary);background:var(--primary-soft);padding:3px 9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--primary) 18%,transparent);white-space:nowrap}.hero-merged-stat{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:700;color:var(--muted);background:#94a3b824;border:1px solid rgba(148,163,184,.28);white-space:nowrap;line-height:1.25}.hero-merged-stat>i{font-size:10px;opacity:.88;color:var(--muted-2)}.hero-merged-stat--weight>i{color:var(--accent);opacity:1}.hero-merged-meta{margin:5px 0 0;display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;font-size:11.5px;line-height:1.45;color:var(--muted)}.hero-merged-meta .dot{color:var(--muted-2);font-weight:700;-webkit-user-select:none;user-select:none}.hero-merged-meta i{font-size:10px;margin-right:3px;color:var(--muted-2);opacity:.95}.hero-merged-meta strong{color:var(--primary);font-weight:700}.hero-merged-sync{color:#94a3b8;font-weight:400;font-size:11px}.hero-actions--merged{flex-shrink:0}.hero-profile-menu{position:relative;flex:0 0 auto;list-style:none}.hero-profile-menu__trigger{list-style:none}.hero-profile-menu__trigger::-webkit-details-marker{display:none}.hero-profile-menu__trigger::marker{content:\"\"}.hero-profile-menu__panel{position:absolute;top:calc(100% + 6px);right:0;z-index:30;min-width:180px;padding:6px;border-radius:12px;border:1px solid var(--border);background:#fff;box-shadow:0 8px 24px -8px #0f172a2e}.hero-profile-menu__item{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border:0;border-radius:8px;background:transparent;font:inherit;font-size:13px;font-weight:600;color:var(--text);text-align:left;cursor:pointer;transition:background .12s ease,color .12s ease}.hero-profile-menu__item i{font-size:14px;color:var(--muted-2);width:1.1em;text-align:center}.hero-profile-menu__item:hover:not(:disabled){background:var(--primary-soft, #eef0ff);color:var(--primary)}.hero-profile-menu__item:hover:not(:disabled) i{color:var(--primary)}.hero-profile-menu__item--danger:hover:not(:disabled){color:var(--rose);background:var(--rose-soft)}.hero-profile-menu__item--danger:hover:not(:disabled) i{color:var(--rose)}.about-dialog{max-width:360px}.about-dialog__head{margin-bottom:8px}.about-dialog__title{display:flex;align-items:center;gap:8px;margin:0;font-size:18px;font-weight:700}.about-dialog__title i{color:var(--primary)}.about-dialog__meta{margin:0 0 16px;padding:0}.about-dialog__row{display:grid;grid-template-columns:96px 1fr;gap:8px 12px;padding:10px 0;border-bottom:1px solid var(--border)}.about-dialog__row:last-child{border-bottom:0}.about-dialog__row dt{margin:0;font-size:13px;font-weight:600;color:var(--muted-2)}.about-dialog__row dd{margin:0;font-size:14px;font-weight:600;color:var(--text)}.about-dialog__row dd code{font-size:13px;font-weight:600;padding:2px 8px;border-radius:6px;background:var(--primary-soft, #eef0ff);color:var(--primary)}@media(max-width:640px){.hero-title--merged .emoji{font-size:26px}.hero-merged-meta{font-size:11px}.hero-merged-stat{font-size:10.5px;padding:2px 7px}}.hero-datetime{display:flex;flex-wrap:wrap;align-items:center;flex-shrink:0}.hero-datetime-strip{display:inline-flex;align-items:stretch;flex-wrap:nowrap;max-width:100%;min-height:34px;border:1px solid var(--border);border-radius:8px;background:linear-gradient(180deg,#fff,#f1f5f9);box-shadow:0 1px 1px #0f172a0d}.hero-datetime-strip__block{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;min-width:0}.hero-datetime-strip__block>.pi{font-size:12px;color:var(--primary);opacity:.82;flex-shrink:0}.hero-datetime-strip__block--date{flex-wrap:wrap;row-gap:0}.hero-datetime-strip__wd{font-size:10px;font-weight:700;color:var(--muted);text-transform:capitalize;letter-spacing:.02em;line-height:1.15;max-width:88px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hero-datetime-strip__date{font-size:12px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--text);letter-spacing:.02em;white-space:nowrap}.hero-datetime-strip__divider{align-self:stretch;width:1px;margin:5px 0;background:#94a3b866;flex-shrink:0}.hero-datetime-strip__clock{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:.04em;color:var(--primary);line-height:1;white-space:nowrap}.hero-datetime-strip__block--time{padding-right:10px}.hero-datetime-strip__block--time>.pi{font-size:11px}@media(max-width:520px){.hero-inner{flex-direction:column;align-items:stretch}.hero-datetime{width:100%;justify-content:flex-start}.hero-datetime-strip{flex:1 1 auto;width:100%;justify-content:space-between}.hero-notification__composer-row{flex-direction:column;align-items:stretch}.hero-notification__send,.hero-notification__cancel{width:100%;justify-content:center}}.hero-notification__bg-icon{position:absolute;pointer-events:none;color:var(--primary);opacity:.13;line-height:1}.hero-notification__bg-icon i{display:block}.hero-notification__bg-icon--bell{top:8%;left:6%;font-size:28px;transform:rotate(-18deg)}.hero-notification__bg-icon--megaphone{top:10%;right:8%;font-size:24px;transform:rotate(12deg)}.hero-notification__bg-icon--comments{bottom:14%;right:10%;font-size:22px;transform:rotate(-8deg)}.hero-notification__bg-icon--send{bottom:10%;left:50%;font-size:20px;transform:rotate(-22deg)}.hero-notification__bg-icon--star{bottom:16%;left:4%;font-size:18px;transform:rotate(20deg)}.hero-notification__bg-icon--bolt{top:46%;right:2%;font-size:20px;transform:rotate(-5deg)}.hero-notification__bg-icon--heart{top:38%;left:14%;font-size:17px;transform:rotate(15deg)}.hero-notification__bg-icon--info{top:4%;left:50%;font-size:18px;transform:rotate(0)}.hero-notification__bg-icon--check{bottom:24%;left:35%;font-size:17px;transform:rotate(8deg)}.hero-notification__bg-icon--eye{top:14%;left:28%;font-size:18px;transform:rotate(-10deg)}.hero-notification{flex:1 1 100%;display:flex;flex-direction:column;gap:10px;margin-top:2px;padding:10px 12px;border:1px solid rgba(148,163,184,.28);border-radius:14px;background:#fff;position:relative;overflow:hidden}.hero-notification__head{display:flex;align-items:center;justify-content:space-between;gap:10px;position:relative}.hero-notification__head-actions{display:inline-flex;align-items:center;gap:6px}.hero-notification__composer-label{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--muted)}.hero-notification__composer-label i{color:var(--primary);font-size:12px}.hero-notification__unread-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:var(--primary);color:#fff;font-size:10px;font-weight:700;line-height:1}.hero-notification__add{width:28px;height:28px;border:1px solid rgba(var(--primary-rgb, 76, 92, 240),.25);border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.1);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0}.hero-notification__add i{font-size:11px}.hero-notification__add:hover:not(:disabled){background:var(--primary);border-color:var(--primary);color:#fff}.hero-notification__mark-all{height:26px;border:none;border-radius:0;background:transparent;color:var(--primary);font-size:11px;font-weight:600;padding:0;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:4px}.hero-notification__mark-all i{font-size:10px}.hero-notification__mark-all:hover:not(:disabled){opacity:.75}.hero-notification__mark-all:disabled{color:var(--muted-2);cursor:default}.hero-notification__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px;position:relative}.hero-notification__item{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:10px;background:#f8fafc;border:1px solid #e2e8f0;position:relative;transition:border-color .18s ease,transform .18s ease}@media(hover:hover){.hero-notification__item:hover{border-color:#c7d2fe;transform:translateY(-1px)}}.hero-notification__avatar{width:34px;height:34px;border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.12);border:1.5px solid rgba(var(--primary-rgb, 76, 92, 240),.22);color:var(--primary);font-size:11px;font-weight:700;letter-spacing:.5px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.hero-notification__body{flex:1;min-width:0;padding-right:52px}.hero-notification__body-head{display:flex;align-items:center;gap:6px;margin-bottom:3px}.hero-notification__author{font-size:12px;font-weight:700;color:var(--text)}.hero-notification__content{margin:0;font-size:13.5px;line-height:1.5;color:var(--text);white-space:pre-wrap;word-break:break-word}.hero-notification__created{display:block;margin-top:4px;font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums}.hero-notification__item-actions{position:absolute;top:7px;right:8px;display:inline-flex;align-items:center;gap:4px}.hero-notification__ack-top{width:24px;height:24px;border:none;border-radius:50%;background:#eff6ff;color:#1d4ed8;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s ease,color .15s ease,transform .15s ease}.hero-notification__ack-top i{font-size:10px}.hero-notification__ack-top:active:not(:disabled){transform:scale(.96)}.hero-notification__ack-top:hover:not(:disabled){background:#dbeafe;color:#1e40af}.hero-notification__delete{width:24px;height:24px;border:none;border-radius:50%;background:transparent;color:#94a3b8;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.hero-notification__delete i{font-size:10px}.hero-notification__delete:hover:not(:disabled){background:#fee2e2;color:#b91c1c}.hero-notification__empty{display:flex;flex-direction:column;align-items:center;gap:4px;padding:16px 8px;position:relative}.hero-notification__empty-icon{font-size:28px;color:var(--primary);opacity:.45;margin-bottom:4px}.hero-notification__empty-title{font-size:13px;font-weight:600;color:var(--muted)}.hero-notification__empty-sub{font-size:11px;color:var(--muted-2);text-align:center}.hero-notification__more{align-self:flex-start;border:none;background:transparent;color:var(--primary);font-size:12px;font-weight:700;cursor:pointer;padding:0;font-family:inherit;position:relative}.hero-notification__more:hover{opacity:.75}.hero-notification__composer-row{display:flex;align-items:stretch;gap:8px;min-width:0}.hero-notification__composer-panel{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid #dbe4f3;border-radius:12px;background:#f8fbff}.hero-notification__input-wrap{flex:1;min-width:0;border-radius:11px;border:1.5px solid #cfd8e6;background:#fff;transition:border-color .15s ease;position:relative}.hero-notification__composer-row:focus-within .hero-notification__input-wrap{border-color:var(--primary)}.hero-notification__input{width:100%;min-width:0;min-height:100px;border:0;border-radius:11px;padding:10px 12px 32px;font-size:13px;line-height:1.45;color:var(--text);background:transparent;font-family:inherit;resize:vertical}.hero-notification__input:focus{outline:none}.hero-notification__char-ring{position:absolute;bottom:8px;right:10px;display:flex;align-items:center;gap:4px;pointer-events:none}.hero-notification__char-ring svg{width:22px;height:22px;transform:rotate(-90deg)}.hero-notification__char-ring-track{fill:none;stroke:#e2e8f0;stroke-width:3}.hero-notification__char-ring-fill{fill:none;stroke:var(--primary);stroke-width:3;stroke-dasharray:94 94;stroke-linecap:round;transition:stroke-dashoffset .2s ease}.hero-notification__char-count{font-size:10px;color:var(--muted-2);font-variant-numeric:tabular-nums}.hero-notification__composer-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px}.hero-notification__send,.hero-notification__cancel{height:36px;border-radius:10px;min-width:86px;padding:0 14px;font-size:12px;font-weight:700}.hero-notification__send{background:var(--primary);color:#fff}.hero-notification__send:not(:disabled):hover{background:var(--primary-2)}.hero-notification__cancel{min-width:72px}.hero-notification__error{margin:0;font-size:12px;color:#b91c1c;position:relative}.hero-notification-dialog{max-width:min(520px,100vw - 24px);overflow:hidden}.hero-notification-dialog .hero-notification__composer-row{align-items:stretch;gap:10px}.hero-notification-dialog .hero-notification__input-wrap{min-height:110px}.hero-notification-dialog__head{margin-bottom:14px}.hero-notification-dialog__title-group{display:flex;align-items:flex-start;gap:10px}.hero-notification-dialog__icon-wrap{width:34px;height:34px;border-radius:10px;background:rgba(var(--primary-rgb, 76, 92, 240),.12);border:1px solid rgba(var(--primary-rgb, 76, 92, 240),.22);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.hero-notification-dialog__icon-wrap i{font-size:14px}.hero-notification-dialog__title{margin:0;font-size:15px;font-weight:800;color:var(--text);line-height:1.3}.hero-notification-dialog__subtitle{margin:2px 0 0;font-size:11px;color:var(--muted-2)}.hero-notification-list-dialog{max-width:min(620px,100vw - 24px)}.hero-notification-list-dialog__head{margin-bottom:10px;align-items:flex-start}.hero-notification-list-dialog__head-actions{display:inline-flex;align-items:center;gap:8px;flex-shrink:0}.hero-notification-list-dialog__title{margin:0;font-size:15px;font-weight:800;color:var(--text);line-height:1.3}.hero-notification-list-dialog__body{max-height:min(60vh,480px);overflow-y:auto;padding-right:2px}.ack-all-confirm-dialog{max-width:min(380px,100vw - 24px);text-align:center;padding:28px 24px 24px;display:flex;flex-direction:column;align-items:center;gap:10px;overflow:hidden}.ack-all-confirm-dialog__icon-wrap{width:52px;height:52px;border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.1);border:1.5px solid rgba(var(--primary-rgb, 76, 92, 240),.2);color:var(--primary);display:flex;align-items:center;justify-content:center;margin-bottom:2px}.ack-all-confirm-dialog__icon-wrap i{font-size:22px}.ack-all-confirm-dialog__title{margin:0;font-size:16px;font-weight:800;color:var(--text)}.ack-all-confirm-dialog__desc{margin:0;font-size:13px;color:var(--muted);line-height:1.55;max-width:280px}.ack-all-confirm-dialog__actions{display:flex;gap:10px;margin-top:6px;width:100%;justify-content:center}.ack-all-confirm-dialog__actions .btn{min-width:96px;height:38px;border-radius:10px;font-size:13px;font-weight:700}.ack-all-confirm-dialog__confirm-btn{background:var(--primary);color:#fff;display:inline-flex;align-items:center;gap:6px}.ack-all-confirm-dialog__confirm-btn i{font-size:12px}.ack-all-confirm-dialog__confirm-btn:not(:disabled):hover{background:var(--primary-2)}.hero-actions{display:flex;gap:8px;align-items:center;flex-shrink:0;align-self:center}.content{width:100%}.content .tab-pane[hidden]{display:none!important}.content .tab-pane--feeding{max-width:1100px;margin:0 auto;padding:0 20px}.content .tab-pane--documents{max-width:none;padding:0}.content .tab-pane--weight{max-width:none;padding:0;background:linear-gradient(180deg,color-mix(in srgb,var(--primary, #5b6cff) 5%,var(--surface, #fff)) 0%,var(--surface, #fff) min(36vh,280px),var(--surface, #fff) 100%)}.content .tab-pane--mom{max-width:1100px;margin:0 auto;padding:0 20px calc(24px + env(safe-area-inset-bottom,0px))}.content .tab-pane--medical{max-width:none;padding:0;background:linear-gradient(180deg,color-mix(in srgb,var(--primary, #5b6cff) 7%,var(--surface, #fff)) 0%,var(--surface, #fff) min(42vh,320px),var(--surface, #fff) 100%)}.bottom-nav{--bn-primary: #5b6cff;--bn-primary-rgb: 91, 108, 255;--bn-inactive: #b0b7c3;--bn-height: 62px;position:fixed;left:0;right:0;bottom:0;width:100%;box-sizing:border-box;z-index:90;display:flex;align-items:center;justify-content:space-between;gap:4px;min-height:var(--bn-height);padding:0 4px env(safe-area-inset-bottom,0px);background:#fffffff5;backdrop-filter:blur(24px) saturate(200%);-webkit-backdrop-filter:blur(24px) saturate(200%);border-top:1px solid rgba(0,0,0,.055);box-shadow:0 -4px 24px -4px #0f172a14}.bottom-nav .bn-side{flex:1;display:flex;align-items:center;justify-content:space-around;min-width:0}.bottom-nav .bn-fab{flex-shrink:0;width:56px;height:56px;margin-top:-20px;border-radius:999px;border:3px solid rgba(255,255,255,.96);background:var(--bn-primary);color:#fff;font-size:22px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:transform .15s ease,background .15s ease,opacity .15s ease}.bottom-nav .bn-fab:hover:not(:disabled){background:var(--primary-2, #4c5cf0);transform:translateY(-2px)}.bottom-nav .bn-fab:active:not(:disabled){transform:translateY(0) scale(.94)}.bottom-nav .bn-fab:disabled{background:var(--bn-inactive);cursor:not-allowed;opacity:.7}.bottom-nav .bn-item{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;height:var(--bn-height);padding:0 2px;background:transparent;border:none;color:var(--bn-inactive);cursor:pointer;font-family:inherit;-webkit-tap-highlight-color:transparent;transition:color .22s ease}.bottom-nav .bn-item .bn-icon-wrap{display:flex;align-items:center;justify-content:center;width:32px;height:30px;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}.bottom-nav .bn-item .bn-icon{font-size:21px;line-height:1;transition:filter .22s ease;display:block}.bottom-nav .bn-item .bn-label{font-size:10px;font-weight:500;letter-spacing:.025em;line-height:1;transition:font-weight .22s ease}.bottom-nav .bn-item:not(.active):hover{color:rgba(var(--bn-primary-rgb),.7)}.bottom-nav .bn-item:active .bn-icon-wrap{transform:scale(.88)}.bottom-nav .bn-item.active{color:var(--bn-primary)}.bottom-nav .bn-item.active .bn-icon-wrap{transform:translateY(-3px) scale(1.15)}.bottom-nav .bn-item.active .bn-icon{filter:drop-shadow(0 2px 8px rgba(var(--bn-primary-rgb),.4))}.bottom-nav .bn-item.active .bn-label{font-weight:700}.card{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:20px;margin-bottom:16px}.card-header{margin-bottom:16px}.card-header h2{margin:0;font-size:18px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:8px}.card-header h2 i{color:var(--primary)}.card-header p{margin:6px 0 0;color:var(--muted);font-size:13px}.eyebrow{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--muted-2);letter-spacing:.06em}.eyebrow i{margin-right:4px}.form{display:flex;flex-direction:column;gap:14px}.field{display:flex;flex-direction:column;gap:6px}.field .label{font-size:12px;font-weight:600;color:var(--muted);letter-spacing:.02em;display:flex;align-items:center;gap:6px;flex-wrap:wrap}.field .label .label-hint{font-size:11px;font-weight:500;color:var(--muted-2);font-style:italic;text-transform:none;letter-spacing:0}.field input[type=text],.field input[type=date],.field input[type=time],.field input[type=number]{padding:12px 14px;border:1.5px solid var(--border);border-radius:10px;font-size:14px;font-family:inherit;color:var(--text);background:#fafbfc;width:100%;min-width:0;box-sizing:border-box;appearance:none;-webkit-appearance:none;transition:border-color .15s,background .15s;min-height:46px;font-variant-numeric:tabular-nums}.field input[type=text]:focus,.field input[type=date]:focus,.field input[type=time]:focus,.field input[type=number]:focus{outline:none;border-color:var(--primary);background:#fff}.field input[type=text]::placeholder,.field input[type=date]::placeholder,.field input[type=time]::placeholder,.field input[type=number]::placeholder{color:var(--muted-2)}.field input[type=number]{-moz-appearance:textfield}.field input[type=number]::-webkit-outer-spin-button,.field input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.radio-group{display:flex;gap:8px;flex-wrap:wrap}.chip{padding:9px 16px;border:1.5px solid var(--border);background:#fff;border-radius:999px;font-size:13px;cursor:pointer;color:var(--text);transition:all .15s;font-family:inherit}.chip:hover{border-color:var(--primary);color:var(--primary)}.chip.active{background:var(--primary);border-color:var(--primary);color:#fff}.form-actions{display:flex;gap:10px;margin-top:4px;flex-wrap:wrap}.btn{display:inline-flex;align-items:center;gap:6px;padding:10px 18px;border:none;border-radius:10px;font-size:14px;font-weight:600;font-family:inherit;cursor:pointer;transition:background .15s,color .15s,border-color .15s}.btn:disabled{opacity:.5;cursor:not-allowed}.btn.small{padding:6px 12px;font-size:12px}.btn.primary{background:var(--primary);color:#fff}.btn.primary:not(:disabled):hover{background:var(--primary-2)}.btn.ghost{background:transparent;color:var(--muted);border:1.5px solid var(--border)}.btn.ghost:hover{color:var(--text);border-color:var(--border-strong)}.btn.danger-ghost{background:transparent;color:var(--rose);border:1.5px solid var(--rose-soft)}.btn.danger-ghost:hover{background:var(--rose-soft)}.btn.icon-btn{padding:0;width:36px;height:36px;justify-content:center;background:transparent;color:var(--muted);border:1.5px solid var(--border);border-radius:10px}.btn.icon-btn i{font-size:14px}.btn.icon-btn:not(:disabled):hover{color:var(--primary);border-color:var(--primary);background:var(--primary-soft)}.btn.icon-btn .spin{animation:spin-refresh .9s linear infinite}@keyframes spin-refresh{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.age-stats{display:flex;align-items:baseline;justify-content:flex-start;gap:16px;padding:14px 16px;background:var(--primary-soft);border-radius:12px}.age-stats .stat{text-align:center}.age-stats .stat .num{font-size:26px;font-weight:700;color:var(--primary);line-height:1;font-variant-numeric:tabular-nums}.age-stats .stat .unit{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-top:3px}.age-stats .dot{color:var(--muted-2);font-size:20px}.period-card{margin-bottom:0}.period-card h2{margin:6px 0 8px;font-size:20px;font-weight:700}.period-card .period-summary{color:var(--muted);font-size:14px;margin:0 0 14px;line-height:1.55}.schedule-grid{display:grid;grid-template-columns:1fr;gap:10px}.schedule{display:flex;gap:12px;padding:12px;background:#fafbfc;border:1px solid var(--border);border-radius:12px}.schedule i{color:var(--primary);font-size:18px;margin-top:2px}.schedule .schedule-title{font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-bottom:2px}.schedule .schedule-text{font-size:14px;color:var(--text);line-height:1.5}.compare-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}@media(max-width:768px){.compare-grid{grid-template-columns:1fr}}.day-card{margin-bottom:0;min-width:0;overflow:hidden}.day-card.today{border-color:#3b82f6;background:linear-gradient(180deg,#dbeafe,#fff 50%)}.day-card.yesterday{background:#fafbfc}.day-date-nav-wrap{position:relative;margin-bottom:12px}.day-date-nav-reset{position:absolute;top:-8px;right:-8px;z-index:1;width:24px;height:24px;border:1px solid var(--border);border-radius:50%;background:#fff;color:var(--muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;box-shadow:0 1px 3px #0f172a14}.day-date-nav-reset i{font-size:10px}.day-date-nav-reset:hover{background:#fee2e2;border-color:#fecaca;color:#dc2626}.day-date-nav-reset:active{background:#fee2e2;color:#dc2626}.day-date-strip{display:grid;grid-template-columns:32px 1fr 32px;gap:6px;align-items:stretch;padding:6px 8px;border-radius:10px;background:#fff;border:1px solid var(--border);touch-action:manipulation}.day-date-strip-scroller{display:flex;gap:4px;min-width:0;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;scrollbar-width:thin;padding:1px 2px}.day-date-strip-scroller::-webkit-scrollbar{height:4px}.day-date-strip-scroller::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:999px}.day-date-strip-day{flex:0 0 64px;scroll-snap-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-width:0;padding:6px 4px;border:1px solid transparent;border-radius:8px;background:#f8fafc;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.day-date-strip-day:hover{background:#eef2ff;border-color:#c7d2fe}.day-date-strip-day.active{background:#dbeafe;border-color:#3b82f6;box-shadow:inset 0 0 0 1px #3b82f626}.day-date-strip-date{font-size:12px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.2}.day-date-strip-ml{font-size:11px;font-weight:600;color:#1d4ed8;font-variant-numeric:tabular-nums;line-height:1.2}.day-date-strip-ml.empty{color:var(--muted);font-weight:500}.day-date-strip-arrow{width:32px;min-height:52px;flex-shrink:0;border:none;border-radius:8px;background:#f1f5f9;color:var(--text);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.day-date-strip-arrow i{font-size:12px}.day-date-strip-arrow:hover:not(:disabled){background:var(--primary);color:#fff}.day-date-strip-arrow:active:not(:disabled){background:var(--primary);color:#fff}.day-date-strip-arrow:disabled{opacity:.35;cursor:not-allowed}.day-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:12px}.day-head h3{margin:4px 0 0;font-size:16px;color:var(--text);font-variant-numeric:tabular-nums}.big-total{display:flex;align-items:baseline;gap:3px}.big-total .num{font-size:32px;font-weight:800;color:var(--text);line-height:1;font-variant-numeric:tabular-nums}.big-total .unit{font-size:14px;color:var(--muted);font-weight:500}.day-stats{display:flex;flex-wrap:wrap;gap:10px 16px;padding:10px 0 0;border-top:1px solid var(--border)}.day-stats>div{font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:5px}.day-stats>div i{color:var(--primary);font-size:12px}.compare-banner{margin-top:12px;padding:12px;background:var(--primary-soft);border-radius:12px;font-size:12px;color:var(--text);display:flex;flex-direction:column;gap:8px}.compare-banner strong{color:var(--primary);font-variant-numeric:tabular-nums;font-weight:700}.compare-banner .compare-row{display:flex;align-items:center;justify-content:space-between;gap:12px}.compare-banner .compare-row:not(:last-child){padding-bottom:8px;border-bottom:1px dashed rgba(15,23,42,.1)}.compare-banner .compare-stats{display:flex;align-items:center;gap:6px;flex:1}.compare-banner .compare-stats .label{color:var(--muted);font-weight:500;font-size:11px}.compare-banner .compare-stats .count{color:var(--muted-2);font-size:11px}.compare-banner .compare-change{display:flex;align-items:center;gap:4px;font-size:11px;font-weight:600;flex-shrink:0}.compare-banner .compare-change i{font-size:10px}.compare-banner .compare-change i.up{color:var(--mint)}.compare-banner .compare-change i.down{color:var(--amber)}.compare-banner .compare-change strong{font-size:12px}.compare-banner .compare-change span{color:var(--muted-2);font-weight:500}.today-logs{margin-top:12px;padding:12px;background:#fafbfc;border:1px solid var(--border);border-radius:12px}.logs-header{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px}.logs-header span{display:flex;align-items:center;gap:6px}.logs-header span:before{content:\"\\1f37c\";font-size:14px}.logs-header .logs-more{text-transform:none;letter-spacing:0;background:transparent;border:none;color:var(--primary);font-size:12px;font-weight:600;padding:4px 8px;border-radius:6px;cursor:pointer;display:inline-flex;align-items:center;gap:3px;transition:background .2s ease}.logs-header .logs-more i{font-size:10px}.logs-header .logs-more:hover{background:var(--primary-soft)}.log-list{display:flex;flex-direction:column;gap:6px;min-width:0}.log-row{display:flex;align-items:center;gap:10px;padding:8px 10px;background:#fafbfc;border-radius:8px;font-size:13px;min-width:0;max-width:100%;transition:all .2s ease;position:relative}.log-row.low-volume .log-volume{color:#f59e0b;font-weight:900}.log-row.high-volume .log-volume{color:#10b981;font-weight:900}.log-row:hover{background:#f1f5f9;transform:translateY(-1px);box-shadow:0 2px 8px #0000000d}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}.log-time{font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;min-width:42px}.log-volume{font-weight:800;color:var(--primary);font-size:16px;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.log-gap{display:inline-flex;align-items:center;gap:3px;padding:2px 7px;background:#f3f4f6;color:#6b7280;border-radius:999px;font-size:10.5px;font-weight:600;white-space:nowrap;flex-shrink:0;font-variant-numeric:tabular-nums;transition:all .2s ease}.log-gap i{font-size:9px;opacity:.7}.log-gap.feed-gap-warn{background:linear-gradient(135deg,#f59e0b,#ea580c);color:#fff;font-weight:700;border:1px solid rgba(234,88,12,.45);box-shadow:0 0 0 1px #fff3 inset,0 2px 8px #ea580c59}.log-gap.feed-gap-warn i{opacity:.95;color:inherit}.log-note{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.log-actions{margin-left:auto;display:inline-flex;align-items:center;gap:2px}.log-edit,.log-del{background:transparent;border:none;color:var(--muted-2);cursor:pointer;padding:4px 6px;border-radius:6px;font-size:12px;transition:all .2s ease}.log-edit:hover{color:var(--primary);background:var(--primary-soft)}.log-del:hover{color:var(--rose);background:var(--rose-soft)}.empty-mini{padding:12px;text-align:center;color:var(--muted-2);font-size:13px;font-style:italic}.countdown-hero{display:flex;flex-direction:column;gap:16px;padding:18px 20px;background:#fff;border-radius:16px;border:1px solid #e6e9ff;transition:all .3s ease;margin-bottom:20px}.countdown-hero .hero-main{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:20px}.countdown-hero .feeding-time-card{flex:1;min-width:0;text-align:center}.countdown-hero .feeding-time-card .time-header{margin-bottom:12px;display:flex;justify-content:center}.countdown-hero .feeding-time-card .time-header .status-badge{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;padding:6px 12px;border-radius:14px;white-space:nowrap}.countdown-hero .feeding-time-card .time-header .status-badge i{font-size:11px}.countdown-hero .feeding-time-card .time-header .status-badge.status-waiting{background:var(--primary-soft);color:var(--primary)}.countdown-hero .feeding-time-card .time-header .status-badge.status-now{background:#fee2e2;color:#dc2626;animation:pulse-gentle 2s ease-in-out infinite;font-size:11px;text-transform:none;font-weight:700}.countdown-hero .feeding-time-card .time-header .status-badge.status-late{background:var(--rose-soft);color:var(--rose)}.countdown-hero .feeding-time-card .time-display .predicted-time{font-size:42px;font-weight:800;line-height:1;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.02em;margin-bottom:4px}.countdown-hero .feeding-time-card .time-display .time-remaining{font-size:15px;font-weight:500;color:var(--muted);font-variant-numeric:tabular-nums}.countdown-hero .countdown-next{display:flex;flex-direction:column;gap:8px;padding-left:16px;border-left:1px dashed #d8dcff;flex-shrink:0;min-width:0}.countdown-hero .next-item{display:flex;align-items:center;gap:6px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.countdown-hero .next-item i{color:var(--primary);font-size:13px}.countdown-hero .next-item strong{font-weight:700}.countdown-hero .next-item .predict-label,.countdown-hero .next-item .recommend-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-2);margin-left:4px}.countdown-hero .next-item .recommend-label{color:var(--mint)}.countdown-hero .volume-info{display:flex;flex-direction:column;gap:8px;padding-left:20px;border-left:1px dashed #d8dcff;flex-shrink:0;min-width:160px;transition:all .3s ease}.countdown-hero .volume-info .volume-row{display:flex;align-items:center;justify-content:space-between;gap:12px}.countdown-hero .volume-info .volume-row .volume-prefix{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-2);flex-shrink:0}.countdown-hero .volume-info .volume-row .volume-amount{font-size:22px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1;text-align:right}.countdown-hero .volume-info .volume-row.predicted-row .volume-prefix,.countdown-hero .volume-info .volume-row.predicted-row .volume-amount{color:var(--primary)}.countdown-hero .volume-info .volume-row.recommended-row .volume-prefix,.countdown-hero .volume-info .volume-row.recommended-row .volume-amount{color:var(--mint)}.countdown-hero[data-status=waiting]{border-color:#bbf7d0;background:linear-gradient(135deg,#f7fef8,#f0fdf4)}.countdown-hero[data-status=waiting] .feeding-time-card .time-display .predicted-time{color:#16a34a}.countdown-hero[data-status=waiting] .feeding-time-card .time-display .time-remaining{color:#15803d}.countdown-hero[data-status=waiting] .feeding-time-card .status-badge.status-waiting{background:#dcfce7!important;color:#15803d!important;border:1px solid #86efac}.countdown-hero[data-status=waiting] .volume-info .volume-amount{color:#16a34a}.countdown-hero[data-status=waiting] .volume-info .volume-prefix{color:#15803d}.countdown-hero[data-status=late]{border-color:#fca5a5;background:linear-gradient(135deg,#fef2f2,#fee2e2)}.countdown-hero[data-status=late] .feeding-time-card .time-display .predicted-time{color:#dc2626}.countdown-hero[data-status=late] .feeding-time-card .time-display .time-remaining{color:#b91c1c}.countdown-hero[data-status=late] .feeding-time-card .status-badge.status-late{background:#fee2e2;color:#dc2626;border:1px solid #fca5a5}.countdown-hero[data-status=late] .volume-info .volume-amount{color:#dc2626}.countdown-hero[data-status=late] .volume-info .volume-prefix{color:#b91c1c}.countdown-hero[data-status=now]{border-color:#fbbf24;background:linear-gradient(135deg,#fefce8,#fef3c7);animation:pulse-card 2s ease-in-out infinite}.countdown-hero[data-status=now] .feeding-time-card .time-display .predicted-time{color:#92400e}.countdown-hero[data-status=now] .feeding-time-card .time-display .time-remaining{color:#a16207}.countdown-hero[data-status=now] .feeding-time-card .status-badge.status-now{background:#fef3c7!important;color:#b45309!important;border:1px solid #f59e0b!important}.countdown-hero[data-status=now] .volume-info .volume-amount{color:#92400e}.countdown-hero[data-status=now] .volume-info .volume-prefix{color:#a16207}@media(max-width:540px){.countdown-hero .hero-main{flex-direction:column;align-items:stretch;gap:12px}.countdown-hero .hero-main .volume-info{border-left:none;border-top:1px dashed #d8dcff;padding-left:0;padding-top:12px;min-width:auto}.countdown-hero .hero-main .volume-info .volume-row{justify-content:space-between;padding:0 4px}.countdown-hero .hero-main .feeding-time-card .time-display .predicted-time{font-size:36px}.countdown-hero .hero-main .feeding-time-card .volume-info .volume-amount{font-size:20px}}@media(max-width:400px){.countdown-hero .feeding-time-card .status-badge{font-size:10px;padding:4px 10px}.countdown-hero .feeding-time-card .time-display .predicted-time{font-size:32px}.countdown-hero .volume-info .volume-amount{font-size:18px}}@keyframes pulse-soft{0%,to{opacity:1}50%{opacity:.65}}@keyframes pulse-gentle{0%,to{opacity:1}50%{opacity:.75}}@keyframes pulse-urgent{0%,to{opacity:1;text-shadow:0 0 0 rgba(239,68,68,0)}50%{opacity:.8;text-shadow:0 0 8px rgba(239,68,68,.25)}}@keyframes pulse-card{0%,to{transform:scale(1);box-shadow:0 1px 3px #0000001a,0 0 #f8717100}50%{transform:scale(1.02);box-shadow:0 4px 12px #00000026,0 0 0 2px #f871714d}}.burp-warning{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;margin:0 0 16px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:1px solid #f59e0b;border-radius:14px;box-shadow:0 2px 8px #f59e0b33;animation:burp-pulse 2s ease-in-out infinite}.burp-warning__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:40px;height:40px;background:#f59e0b;border-radius:50%;color:#fff;font-size:18px;animation:burp-icon-bounce 1.5s ease-in-out infinite}.burp-warning__content{flex:1;min-width:0}.burp-warning__title{font-size:15px;font-weight:700;color:#92400e;margin-bottom:4px}.burp-warning__text{font-size:13px;color:#78350f;line-height:1.5;margin-bottom:8px}.burp-warning__text strong{font-weight:600;color:#92400e}.burp-warning__countdown{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:#ffffffb3;border-radius:8px;font-size:13px;color:#92400e;font-weight:500}.burp-warning__countdown i{font-size:14px;color:#f59e0b}.burp-warning__countdown strong{font-size:16px;font-weight:700;color:#d97706}@keyframes burp-pulse{0%,to{box-shadow:0 2px 8px #f59e0b33}50%{box-shadow:0 4px 16px #f59e0b59}}@keyframes burp-icon-bounce{0%,to{transform:scale(1)}50%{transform:scale(1.1)}}.countdown-progress{margin-top:10px}.countdown-progress .cp-track{position:relative;height:6px;background:#ffffffbf;border-radius:999px;overflow:hidden}.countdown-progress .cp-fill{height:100%;background:linear-gradient(90deg,var(--primary),var(--accent));border-radius:999px;transition:width .4s ease}.countdown-progress .cp-fill[data-status=waiting]{background:linear-gradient(90deg,#22c55e,#16a34a)}.countdown-progress .cp-fill[data-status=late]{background:linear-gradient(90deg,#f87171,#dc2626)}.countdown-progress .cp-fill[data-status=now]{background:linear-gradient(90deg,#fbbf24,#d97706)}.countdown-progress .cp-labels{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:6px;font-size:11.5px;color:var(--muted)}.countdown-progress .cp-labels i{font-size:10px;margin-right:2px;color:var(--muted-2)}.countdown-progress .cp-labels .muted{color:var(--muted-2)}.countdown-progress .cp-labels .cp-right{font-weight:600;color:var(--muted);white-space:nowrap}.predict-head{display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:12px;margin-bottom:16px}.predict-head .eyebrow{color:var(--primary);display:flex;align-items:center;gap:4px}.predict-head .eyebrow.sparkle i{animation:sparkle 2s ease-in-out infinite}.predict-head h2{margin:4px 0 0;font-size:20px;font-weight:700}.last-feed{display:flex;align-items:center;gap:12px;padding:12px 14px;background:#fff;border-radius:12px;margin-bottom:14px;border:1px solid #e8e9ff}.last-feed .last-feed-icon{width:38px;height:38px;border-radius:50%;background:var(--primary-soft);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.last-feed .last-feed-icon i{color:var(--primary);font-size:16px}.last-feed .last-feed-body{flex:1;min-width:0}.last-feed .last-feed-label{font-size:10px;font-weight:700;text-transform:uppercase;color:var(--muted-2);letter-spacing:.06em;margin-bottom:2px}.last-feed .last-feed-value{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.last-feed .last-feed-value strong{color:var(--primary);font-size:18px;font-weight:800}.last-feed .last-feed-value .sep{color:var(--muted-2)}.last-feed .last-feed-value .ago{color:var(--accent);font-weight:600;font-size:13px}.last-feed .last-feed-note{margin-top:4px;font-size:12px;color:var(--muted);font-style:italic;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.predict-empty{padding:14px 16px;background:#fff;border-radius:12px;color:var(--muted);font-size:13px;display:flex;align-items:center;gap:8px}.predict-empty i{color:var(--primary)}.predict-body{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:14px}@media(max-width:640px){.predict-body{grid-template-columns:1fr}}.predict-metric{background:#fff;border-radius:12px;padding:14px;text-align:center}.predict-metric .metric-label{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px;display:flex;align-items:center;justify-content:center;gap:5px}.predict-metric .metric-label i{color:var(--primary);font-size:12px}.predict-metric .metric-value{font-size:28px;font-weight:800;line-height:1;color:var(--primary);font-variant-numeric:tabular-nums}.predict-metric .metric-value .ml-unit{font-size:14px;color:var(--muted);font-weight:500;margin-left:2px}.predict-metric .metric-sub{margin-top:6px;font-size:12px;color:var(--muted)}.reasoning{background:#fff;border-radius:12px;padding:12px 14px;margin-bottom:12px}.reasoning .reasoning-head{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--muted);letter-spacing:.05em;margin-bottom:6px}.reasoning .reasoning-head i{color:var(--primary);margin-right:4px}.reasoning ul{margin:0;padding-left:18px;list-style:disc}.reasoning li{font-size:13px;color:var(--text);line-height:1.55;margin:2px 0}.predict-actions{display:flex;justify-content:flex-end}.feed-list-card{margin-bottom:16px}.feed-list-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:12px}.feed-list-head h2{margin:4px 0 0;font-size:18px;font-weight:700}.feed-list-compact{display:flex;flex-direction:column;gap:6px}.feed-row{display:grid;grid-template-columns:68px 80px 1fr auto;gap:10px;align-items:center;padding:10px 12px;transition:all .2s ease;position:relative}.feed-row.low-volume .feed-row-volume strong{color:#f59e0b;font-weight:900}.feed-row.high-volume .feed-row-volume strong{color:#10b981;font-weight:900}.feed-row{background:#fafbfc;border-radius:10px;border:1px solid var(--border)}.feed-row .feed-row-time{display:flex;flex-direction:column;line-height:1.2;font-variant-numeric:tabular-nums;gap:3px}.feed-row .feed-row-time .time{font-weight:700;color:var(--text);font-size:14px}.feed-row .feed-row-time .date{font-size:11px;color:var(--muted-2)}.feed-row .feed-row-time .feed-row-gap{display:inline-flex;align-items:center;gap:3px;font-size:10.5px;font-weight:600;color:#6b7280;background:#f3f4f6;padding:1px 6px;border-radius:999px;width:fit-content;white-space:nowrap;font-variant-numeric:tabular-nums}.feed-row .feed-row-time .feed-row-gap i{font-size:8px;opacity:.7}.feed-row .feed-row-time .feed-row-gap.feed-gap-warn{background:linear-gradient(135deg,#f59e0b,#ea580c);color:#fff;font-weight:700;border:1px solid rgba(234,88,12,.45);box-shadow:0 0 0 1px #fff3 inset,0 2px 8px #ea580c59}.feed-row .feed-row-time .feed-row-gap.feed-gap-warn i{opacity:.95;color:inherit}.feed-row .feed-row-volume{font-variant-numeric:tabular-nums}.feed-row .feed-row-volume strong{color:var(--primary);font-size:19px;font-weight:800;letter-spacing:-.01em}.feed-row .feed-row-volume .u{font-size:11px;color:var(--muted);margin-left:2px}.feed-row .feed-row-note{font-size:13px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.feed-row .feed-row-note.muted{color:var(--muted-2);font-style:italic}.feed-row .feed-row-actions{display:inline-flex;align-items:center;gap:2px;margin-left:auto}.feed-row .feed-row-edit,.feed-row .feed-row-del{background:transparent;border:none;color:var(--muted-2);cursor:pointer;padding:6px 8px;border-radius:6px;font-size:13px}.feed-row .feed-row-edit:hover{color:var(--primary, #5b6cff);background:#5b6cff1a}.feed-row .feed-row-del:hover{color:var(--rose);background:var(--rose-soft)}@media(max-width:480px){.feed-row{grid-template-columns:58px 70px 1fr auto;gap:8px;padding:8px 10px}.feed-row .feed-row-time .time{font-size:13px}}.dialog-wide{max-width:720px;display:flex;flex-direction:column;padding:0;overflow:hidden}@media(max-width:640px){.dialog-wide{max-height:calc(100dvh - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px) - 72px);border-radius:14px}}.dialog-wide .dialog-head{position:sticky;top:0;z-index:5;background:var(--surface);padding:16px 20px;margin:0;border-bottom:1px solid var(--border);-webkit-backdrop-filter:saturate(1.2) blur(6px);backdrop-filter:saturate(1.2) blur(6px)}@media(max-width:640px){.dialog-wide .dialog-head{padding:12px 14px}}.dialog-wide .dialog-close{width:40px;height:40px;font-size:16px;background:#f1f3f7;color:var(--text)}.dialog-wide .dialog-close:hover{background:var(--rose-soft);color:var(--rose)}.dialog-wide .history-body,.dialog-wide .tips-dialog-body{padding:18px 20px 24px;overflow-y:auto;flex:1;min-height:0}@media(max-width:640px){.dialog-wide .history-body,.dialog-wide .tips-dialog-body{padding:14px 14px 20px}}.history-body{display:flex;flex-direction:column;gap:18px}.history-paging-hint{margin:0;font-size:12px;line-height:1.45}.history-load-more{display:grid;justify-items:center;width:100%;box-sizing:border-box;padding:8px 0 12px}.history-load-more .btn{width:auto;max-width:min(320px,100%);min-width:0;margin-inline:auto;justify-content:center}.tips-nav{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px;background:#f1f3f7;border-radius:12px;margin-bottom:16px}.nav-arrow{width:40px;height:40px;border-radius:50%;border:none;background:#fff;color:var(--primary);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:16px;transition:all .15s;flex-shrink:0}.nav-arrow:hover:not(:disabled){background:var(--primary);color:#fff;transform:scale(1.05)}.nav-arrow:active:not(:disabled){transform:scale(.95)}.nav-arrow:disabled{opacity:.35;cursor:not-allowed}.tips-now-btn{flex:1;padding:9px 16px;border:none;background:transparent;border-radius:999px;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;justify-content:center;gap:6px;transition:all .15s}.tips-now-btn i{font-size:12px}.tips-now-btn:hover{color:var(--primary);background:#fff}.tips-now-btn.active{background:var(--primary);color:#fff;pointer-events:none}.tips-dialog-body .period-summary{font-size:14px;color:var(--muted);line-height:1.6;margin:0 0 14px}.tips-dialog-body .schedule-grid{grid-template-columns:repeat(2,1fr);margin-bottom:16px}@media(max-width:560px){.tips-dialog-body .schedule-grid{grid-template-columns:1fr}}.dialog-tips-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.history-group .history-group-head{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;background:var(--primary-soft);border-radius:10px;margin-bottom:8px}.history-group .history-group-head .h-date{font-size:14px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums}.history-group .history-group-head .h-day{font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.05em}.history-group .history-group-head .h-total{font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.history-group .history-group-head .h-total strong{color:var(--primary);font-size:20px;font-weight:800}.history-group .history-group-head .h-total .h-count{color:var(--muted);font-size:12px;font-weight:500;margin-left:4px}.history-group .history-group-head .h-total .h-avg{color:var(--primary);font-size:12px;font-weight:600;margin-left:4px;font-variant-numeric:tabular-nums}.history-group .history-group-rows{display:flex;flex-direction:column;gap:4px}.tips-section-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px;padding:4px 4px 0}.tips-section-head .eyebrow i{margin-right:4px}.tips-section-head h2{margin:4px 0 0;font-size:20px;font-weight:700;color:var(--text)}.filter-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}.filter-chip{padding:7px 14px;border:1.5px solid var(--border);background:#fff;border-radius:999px;font-size:13px;font-weight:500;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;gap:5px;transition:all .15s;font-family:inherit}.filter-chip i{font-size:12px}.filter-chip:hover{border-color:var(--cat-color, var(--primary));color:var(--cat-color, var(--primary))}.filter-chip.active{background:var(--cat-color, var(--primary));border-color:var(--cat-color, var(--primary));color:#fff}.tips-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;margin-bottom:20px}.tip-card{background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--cat-color, var(--primary));border-radius:12px;padding:16px;transition:transform .15s}.tip-card:hover{transform:translateY(-2px)}.tip-card .tip-head{margin-bottom:8px}.tip-card .tip-pill{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;background:var(--cat-color, var(--primary));color:#fff;font-size:11px;font-weight:600;border-radius:999px;text-transform:uppercase;letter-spacing:.04em}.tip-card .tip-pill i{font-size:10px}.tip-card .tip-title{margin:6px 0 8px;font-size:15px;font-weight:700;line-height:1.35;color:var(--text)}.tip-card .tip-body{margin:0;font-size:13px;line-height:1.55;color:var(--muted)}.empty{grid-column:1/-1;padding:40px 20px;text-align:center;color:var(--muted-2)}.empty i{font-size:32px;margin-bottom:8px;display:block}.upcoming{margin-bottom:24px}.upcoming h3{margin:0 0 12px;font-size:16px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:6px}.upcoming h3 i{color:var(--primary)}.upcoming-grid{display:flex;gap:8px;flex-wrap:wrap}.upcoming-item{padding:10px 14px;background:var(--surface);border:1px solid var(--border);border-radius:10px;font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:6px}.upcoming-item i{color:var(--primary);font-size:12px}.disclaimer{padding:16px;background:var(--amber-soft);border-radius:12px;color:#78350f;font-size:13px;line-height:1.5;margin-bottom:24px;display:flex;gap:8px;align-items:flex-start}.disclaimer i{color:var(--amber);margin-top:2px}.toast{position:fixed;bottom:100px;left:50%;transform:translate(-50%);z-index:90;padding:12px 18px;border-radius:12px;font-size:14px;font-weight:500;box-shadow:0 6px 24px #0f172a1f;display:flex;align-items:center;gap:8px;animation:toastIn .3s cubic-bezier(.4,0,.2,1)}.toast.success{background:var(--mint);color:#fff}.toast.error{background:var(--rose);color:#fff}@keyframes toastIn{0%{transform:translate(-50%,20px);opacity:0}to{transform:translate(-50%);opacity:1}}.fab{position:fixed;bottom:calc(80px + env(safe-area-inset-bottom,0px));right:20px;z-index:96;display:inline-flex;align-items:center;gap:10px;padding:14px 22px 14px 18px;background:var(--primary);color:#fff;border:none;border-radius:999px;font-size:15px;font-weight:700;font-family:inherit;cursor:pointer;box-shadow:0 8px 24px #5b6cff73;transition:transform .15s,box-shadow .15s,background .15s}.fab i{font-size:18px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;background:#ffffff2e}.fab .fab-label{white-space:nowrap}.fab:hover{background:var(--primary-2);transform:translateY(-2px);box-shadow:0 12px 28px #5b6cff8c}.fab:active{transform:translateY(0)}@media(max-width:480px){.fab{padding:14px}.fab .fab-label{display:none}.fab i{font-size:22px;width:28px;height:28px}}.dialog-overlay{position:fixed;inset:0;background:#0f172a8c;z-index:110;display:flex;align-items:center;justify-content:center;padding:20px;animation:overlayIn .2s ease-out}.dialog-overlay.dialog-overlay--front{z-index:400}.dialog-overlay.dialog-overlay--event-reminder{z-index:410}@media(max-width:640px){.dialog-overlay{padding:calc(env(safe-area-inset-top,0px) + 16px) 12px calc(env(safe-area-inset-bottom,0px) + 16px);align-items:flex-start}}@keyframes overlayIn{0%{opacity:0}to{opacity:1}}.dialog{background:var(--surface);border-radius:20px;width:100%;max-width:560px;max-height:min(100vh - 40px,100dvh - 40px);overflow-y:auto;padding:24px;animation:dialogIn .25s cubic-bezier(.4,0,.2,1);box-shadow:0 20px 60px #0f172a40}@media(max-width:640px){.dialog{max-height:calc(100dvh - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px) - 32px);border-radius:16px}}@keyframes dialogIn{0%{opacity:0;transform:translateY(20px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.dialog-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:18px}.dialog-head h2{margin:4px 0 0;font-size:20px;font-weight:700;color:var(--text);display:flex;align-items:center;gap:8px}.dialog-head h2 i{color:var(--primary)}.dialog-close{background:#f1f3f7;border:none;width:36px;height:36px;border-radius:50%;cursor:pointer;color:var(--muted);font-size:14px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;transition:background .15s,color .15s}.dialog-close:hover{background:var(--rose-soft);color:var(--rose)}.log-form{display:flex;flex-direction:column;gap:14px}.log-volume-field{margin:0}.log-volume-field .log-volume-input-row{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px 10px;min-width:0}.log-volume-field .log-volume-input-row>input[type=number]{flex:0 0 118px;width:118px;max-width:min(118px,100%);min-width:0}.log-volume-field .predict-hint--inline{flex:1 1 auto;min-width:0;margin:0;padding:6px 10px;gap:6px;font-size:12px;border-radius:8px}.log-volume-field .predict-hint--inline>i{font-size:13px;flex-shrink:0}.log-volume-field .predict-hint--inline .hint-text{flex:1 1 auto;min-width:0;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.log-volume-field .predict-hint--inline .btn.small{flex-shrink:0;padding:4px 8px;font-size:11px}@media(max-width:400px){.log-volume-field .log-volume-input-row>input[type=number]{flex:1 1 100px;width:100%;max-width:none}.log-volume-field .predict-hint--inline{flex:1 1 100%;white-space:normal}.log-volume-field .predict-hint--inline .hint-text{white-space:normal;overflow:visible;text-overflow:unset}}.edit-date-banner{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:10px 14px;background:linear-gradient(135deg,#eef2ff,#f5f3ff);border:1px solid #dbe1ff;border-radius:12px;font-size:13px;color:var(--text)}.edit-date-banner>i.pi-calendar{color:var(--primary, #5b6cff);font-size:15px}.edit-date-banner .edb-label{color:var(--muted, #6b7280);font-weight:500}.edit-date-banner .edb-value{font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.01em}.edit-date-banner .edb-lock{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;flex-shrink:0;border-radius:50%;background:#ffffffe0;border:1px solid #e2e8f0;color:var(--muted, #64748b)}.edit-date-banner .edb-lock i{font-size:14px;line-height:1}.log-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.log-grid .field.full{grid-column:1/-1}.log-grid.log-grid--date-time{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:560px){.log-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:380px){.log-grid{grid-template-columns:1fr}}.quick-volumes{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.quick-volumes .quick-label{font-size:12px;color:var(--muted);font-weight:600;margin-right:4px}.quick-chip{padding:7px 13px;background:#f1f3f7;border:none;border-radius:999px;font-size:12px;font-weight:600;cursor:pointer;color:var(--muted);transition:all .15s;font-family:inherit}.quick-chip:hover{background:var(--primary-soft);color:var(--primary)}.quick-chip.now-chip{background:var(--primary-soft);color:var(--primary);display:inline-flex;align-items:center;gap:4px}.quick-chip.now-chip:hover{background:var(--primary);color:#fff}.quick-chip.formula-chip{display:inline-flex;align-items:center;gap:5px;background:#fff7ed;color:#c2410c;border:1px solid #fed7aa}.quick-chip.formula-chip i{font-size:11px;opacity:.9}.quick-chip.formula-chip:hover{background:#ffedd5;color:#9a3412;border-color:#fdba74}.quick-chip.formula-chip.active{background:#c2410c;color:#fff;border-color:#c2410c;box-shadow:0 2px 8px #c2410c40}.quick-chip.formula-chip.active:hover{background:#9a3412;border-color:#9a3412;color:#fff}.bottle-prep{background:#f0f9ff;border:1px solid #bae6fd;border-radius:12px;padding:8px 12px;margin-bottom:16px;display:flex;flex-direction:column;gap:8px;transition:background .2s,border-color .2s}.bottle-prep:has(.bp-warning){background:#fffbeb;border-color:#fde68a}.bottle-prep:has(.bp-warning) .bp-info>i{color:#f59e0b}.bottle-prep:has(.bp-warning) .bp-info strong{color:#d97706}.bottle-prep:has(.bp-warning) .bp-prep-user{color:#92400e;background:#fbbf246b}.bottle-prep:has(.bp-warning) .bp-prep-time{color:#c2410c;background:linear-gradient(180deg,#fff7ed,#ffedd5);border-color:#fb923c73}.bottle-prep:has(.bp-form){align-items:stretch;padding:10px 12px 12px}.bottle-prep .bp-warning{display:flex;align-items:center;justify-content:space-between;gap:10px;animation:slideDown .2s ease;flex-wrap:wrap}.bottle-prep .bp-warning__content{display:flex;align-items:center;gap:8px;font-size:13px;flex:1;min-width:0}.bottle-prep .bp-warning__content i{font-size:16px;flex-shrink:0}.bottle-prep .bp-warning__content strong{font-weight:700}.bottle-prep .bp-warning--expired{background:#fef2f2;border:1px solid #fecaca;border-radius:8px;padding:8px 10px;color:#991b1b}.bottle-prep .bp-warning--expired i{color:#dc2626}.bottle-prep .bp-warning--soon{background:#fefce8;border:1px solid #fde68a;border-radius:8px;padding:8px 10px;color:#92400e}.bottle-prep .bp-warning--soon i{color:#f59e0b}.bottle-prep .bp-warning__btn{flex-shrink:0;display:inline-flex;align-items:center;gap:5px;padding:7px 12px;font-size:12px;font-weight:700;font-family:inherit;color:#fff;background:linear-gradient(180deg,#f59e0b,#d97706);border:none;border-radius:8px;cursor:pointer;box-shadow:0 2px 4px #f59e0b40;transition:all .15s ease}.bottle-prep .bp-warning__btn i{font-size:12px}.bottle-prep .bp-warning__btn:hover{background:linear-gradient(180deg,#fbbf24,#f59e0b);transform:translateY(-1px);box-shadow:0 4px 8px #f59e0b59}.bottle-prep .bp-warning__btn:active{transform:translateY(0)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.bottle-prep .bp-info-row{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%}.bottle-prep:not(:has(.bp-warning)):not(:has(.bp-form)){flex-direction:row;align-items:center;justify-content:space-between;flex-wrap:wrap}.bottle-prep .bp-info{display:flex;align-items:flex-start;gap:8px;font-size:14px;color:var(--text);flex:1;min-width:0}.bottle-prep .bp-info>i{color:#0ea5e9;font-size:16px;margin-top:2px;flex-shrink:0}.bottle-prep .bp-info .bp-text{line-height:1.45;min-width:0}.bottle-prep .bp-info .bp-useby{display:inline-block;margin-top:2px;font-size:13px}.bottle-prep .bp-info strong{color:#0284c7;font-weight:800;font-variant-numeric:tabular-nums}.bottle-prep .bp-info .muted{color:var(--muted);font-size:13px}.bottle-prep .bp-actions{display:flex;gap:4px}.bottle-prep .bp-add{flex:1;background:transparent;border:none;padding:6px 4px;font-size:13px;font-weight:600;color:#0284c7;cursor:pointer;display:flex;align-items:center;gap:8px;font-family:inherit;text-align:left}.bottle-prep .bp-add>i{font-size:15px}.bottle-prep .bp-add:hover{color:#0369a1}.bottle-prep .bp-form{display:flex;flex-direction:column;gap:8px;width:100%}.bottle-prep .bp-form-head{display:flex;align-items:center;gap:6px}.bottle-prep .bp-form-head>i{color:#0ea5e9;font-size:15px}.bottle-prep .bp-form-head .bp-label{font-size:13px;color:var(--muted);font-weight:600;white-space:nowrap}.bottle-prep .bp-input-wrap{display:flex;align-items:center;gap:6px;background:#fff;border:1px solid #7dd3fc;border-radius:10px;padding:3px;transition:border-color .15s,box-shadow .15s}.bottle-prep .bp-input-wrap:focus-within{border-color:#0ea5e9;box-shadow:0 0 0 3px #0ea5e926}.bottle-prep .bp-input-wrap .bp-step{width:30px;height:30px;flex-shrink:0;border-radius:8px;border:none;background:#e0f2fe;color:#0369a1;font-size:12px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-family:inherit;transition:all .12s}.bottle-prep .bp-input-wrap .bp-step:hover{background:#bae6fd;color:#0284c7}.bottle-prep .bp-input-wrap .bp-step:active{transform:scale(.94)}.bottle-prep .bp-input-wrap .bp-step:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.bottle-prep .bp-input-wrap .bp-input{flex:1;min-width:60px;padding:4px 6px;font-size:18px;font-weight:800;border:none;background:transparent;font-variant-numeric:tabular-nums;font-family:inherit;color:#d97706;text-align:center;letter-spacing:-.01em}.bottle-prep .bp-input-wrap .bp-input:focus{outline:none}.bottle-prep .bp-input-wrap .bp-input:disabled{opacity:.55;cursor:not-allowed}.bottle-prep .bp-input-wrap .bp-unit{font-size:12px;color:var(--muted);font-weight:600;padding-right:4px}.bottle-prep .bp-quick{display:flex;flex-wrap:wrap;align-items:center;gap:5px}.bottle-prep .bp-quick .bp-quick-label{font-size:11px;color:var(--muted);font-weight:600;margin-right:2px}.bottle-prep .bp-quick .bp-quick-chip{padding:4px 9px;background:#f0f9ff;border:1px solid #7dd3fc;border-radius:999px;font-size:11.5px;font-weight:700;color:#0369a1;cursor:pointer;font-family:inherit;font-variant-numeric:tabular-nums;transition:all .12s}.bottle-prep .bp-quick .bp-quick-chip:hover{background:#e0f2fe;border-color:#38bdf8;color:#0284c7}.bottle-prep .bp-quick .bp-quick-chip:active{transform:scale(.95)}.bottle-prep .bp-quick .bp-quick-chip:disabled{opacity:.45;cursor:not-allowed}.bottle-prep .bp-form-actions{display:flex;gap:6px;justify-content:flex-end}.bottle-prep .bp-btn{width:32px;height:32px;border-radius:8px;border:none;background:#fff;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:12px;transition:all .15s;flex-shrink:0}.bottle-prep .bp-btn:hover:not(:disabled){background:#e0f2fe;color:#0284c7}.bottle-prep .bp-btn:disabled{opacity:.45;cursor:not-allowed}.bottle-prep .bp-btn.primary{background:#0ea5e9;color:#fff}.bottle-prep .bp-btn.primary:hover:not(:disabled){background:#0284c7}.bottle-prep .bp-btn.danger:hover{background:var(--rose-soft);color:var(--rose)}.calc-block{border:1px solid #fde7c2;background:#fffaf0;border-radius:12px;overflow:hidden}.calc-block .calc-head{padding:10px 14px 0}.calc-block .prep-info{display:flex;align-items:flex-start;gap:6px;font-size:13px;color:var(--text)}.calc-block .prep-info>i{color:#f59e0b;font-size:14px;margin-top:2px;flex-shrink:0}.calc-block .prep-info .prep-info-text{line-height:1.45;min-width:0}.calc-block .prep-info strong{color:#d97706;font-weight:800;font-variant-numeric:tabular-nums}.calc-block .prep-info .muted{color:var(--muted-2);font-size:12px;display:inline-block;margin-top:2px}.calc-block .calc-body{padding:8px 14px 14px;display:flex;flex-direction:column;gap:10px}.calc-block .field.mini.remaining-input{position:relative;margin:0;display:flex;flex-direction:column}.calc-block .field.mini.remaining-input .label{font-size:11px;font-weight:600;color:var(--muted);margin-bottom:4px}.calc-block .field.mini.remaining-input input{width:100%;padding:10px 36px 10px 12px;font-size:16px;font-weight:700;border:1px solid #fadf9e;border-radius:8px;background:#fff;font-variant-numeric:tabular-nums;font-family:inherit;color:#d97706}.calc-block .field.mini.remaining-input input:focus{outline:none;border-color:#f59e0b;box-shadow:0 0 0 3px #f59e0b26}.calc-block .field.mini.remaining-input .suffix{position:absolute;right:12px;top:50%;transform:translateY(4px);font-size:12px;color:var(--muted-2);pointer-events:none}.calc-block .calc-result-row{display:flex;align-items:center;justify-content:space-between;gap:10px}.calc-block .calc-result{display:flex;align-items:baseline;gap:4px;font-variant-numeric:tabular-nums}.calc-block .calc-result .calc-label{font-size:13px;color:var(--muted);font-weight:600}.calc-block .calc-result strong{font-size:22px;font-weight:800;color:var(--primary)}.calc-block .calc-result .u{font-size:12px;color:var(--primary);margin-left:2px}.calc-block .calc-result .muted{color:var(--muted-2);font-size:18px}.calc-block .calc-apply{flex-shrink:0}.calc-block .calc-apply:disabled{background:#e5e7eb;color:var(--muted-2);cursor:not-allowed;box-shadow:none}.predict-hint{display:flex;align-items:center;gap:10px;padding:10px 14px;background:linear-gradient(135deg,var(--primary-soft) 0%,var(--accent-soft) 100%);border-radius:10px;font-size:13px}.predict-hint>i{color:var(--primary);font-size:16px}.predict-hint .hint-text{flex:1;color:var(--text)}.predict-hint .hint-text strong{color:var(--primary);font-weight:700}.predict-hint.predict-hint--inline .hint-text strong{font-weight:800;font-variant-numeric:tabular-nums}.sync-error{padding:10px 14px;background:var(--rose-soft);color:#991b1b;border-radius:10px;font-size:13px;display:flex;align-items:center;gap:6px}.sync-success{padding:10px 14px;background:var(--mint-soft);color:#166534;border-radius:10px;font-size:13px;display:flex;align-items:center;gap:6px;animation:fadeIn .2s ease}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:4px}.feeding-settings-dialog .feeding-settings-hint{margin:0 0 14px;font-size:13px;line-height:1.45}.feeding-settings-dialog .feeding-settings-hint code{font-size:11px;padding:1px 5px;border-radius:4px;background:#f1f5f9}.feeding-settings-dialog .feeding-settings-grid{grid-template-columns:1fr;gap:16px}.feeding-settings-dialog .field-hint{display:block;margin-top:8px;font-size:12px;line-height:1.4;padding:8px 12px;background:#f8fafc;border-radius:8px;border-left:3px solid #e2e8f0}.feeding-settings-dialog .label{position:relative}.feeding-settings-dialog .label code{font-size:11px;font-weight:600;color:var(--primary);background:var(--primary-soft);padding:2px 6px;border-radius:4px}.feeding-settings-dialog .label .notification-badge{display:inline-flex;align-items:center;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:#fff;background:linear-gradient(135deg,#10b981,#059669);padding:2px 6px;border-radius:10px;margin-left:6px;box-shadow:0 1px 2px #10b98133;animation:gentle-pulse 2s ease-in-out infinite}.feeding-settings-dialog .notification-setting-field{position:relative}.feeding-settings-dialog .notification-setting-field input{border:1.5px solid #10b981;background:linear-gradient(to right,#fff,#f0fdf4)}.feeding-settings-dialog .notification-setting-field input:focus{border-color:#059669;box-shadow:0 0 0 3px #10b9811a;background:#fff}.feeding-settings-dialog .notification-setting-field input::placeholder{color:#6b7280;opacity:.7}.feeding-settings-dialog .notification-setting-field .field-hint{border-left-color:#10b981;background:linear-gradient(to right,#f0fdf4,#f8fafc)}@keyframes gentle-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.85;transform:scale(1.02)}}.log-time--with-badge,.feed-row-time .time--with-badge{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}.log-merge-badge,.feed-merge-badge{font:inherit;font-size:10px;font-weight:700;padding:2px 7px;border-radius:999px;border:1px solid rgba(99,102,241,.35);background:linear-gradient(135deg,#e0e7ff,#c7d2fe);color:#312e81;cursor:pointer;line-height:1.2;white-space:nowrap}.log-merge-badge:hover,.feed-merge-badge:hover{filter:brightness(1.03)}.log-row--clickable,.feed-row--clickable{cursor:pointer}.log-row--clickable:hover,.feed-row--clickable:hover{background:#6366f10f}.log-row--clickable:focus-visible,.feed-row--clickable:focus-visible{outline:2px solid rgba(99,102,241,.45);outline-offset:2px}.dialog-overlay.dialog-overlay--front.feed-group-detail-overlay{z-index:125}.dialog-overlay.dialog-overlay--front.feed-detail-overlay{z-index:140;animation:overlayIn .12s ease-out}.dialog-overlay.dialog-overlay--front.feed-detail-overlay .feed-detail-dialog{animation:feedDetailIn .14s ease-out}@keyframes feedDetailIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.feed-detail-dialog{--fd-accent: 99, 102, 241;--fd-soft: #eef2ff;--fd-strong: #4338ca;max-width:min(400px,96vw);padding:0;overflow:hidden;display:flex;flex-direction:column}.feed-detail-dialog[data-status=low]{--fd-accent: 245, 158, 11;--fd-soft: #fffbeb;--fd-strong: #b45309}.feed-detail-dialog[data-status=high]{--fd-accent: 244, 63, 94;--fd-soft: #fff1f2;--fd-strong: #e11d48}.feed-detail-dialog[data-status=ok]{--fd-accent: 16, 185, 129;--fd-soft: #ecfdf5;--fd-strong: #059669}.feed-detail-top{position:relative;padding:20px 20px 16px;text-align:center;background:radial-gradient(120% 80% at 50% -20%,rgba(var(--fd-accent),.22),transparent 55%),linear-gradient(180deg,var(--fd-soft) 0%,#ffffff 72%);border-bottom:1px solid rgba(var(--fd-accent),.12)}.feed-detail-close{position:absolute;top:12px;right:12px;width:36px;height:36px;border:none;border-radius:50%;background:#ffffffd9;color:#64748b;cursor:pointer;display:grid;place-items:center;box-shadow:0 2px 8px #0f172a14;transition:background .15s ease,color .15s ease}.feed-detail-close:hover{background:#fff;color:#0f172a}.feed-detail-eyebrow{margin:0 0 6px;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#64748b}.feed-detail-metric{display:flex;align-items:flex-end;justify-content:center;gap:4px;line-height:1;margin-bottom:10px}.feed-detail-metric__value{font-size:clamp(48px,14vw,56px);font-weight:800;letter-spacing:-.04em;color:var(--fd-strong);font-variant-numeric:tabular-nums}.feed-detail-metric__unit{font-size:18px;font-weight:700;color:rgba(var(--fd-accent),.85);padding-bottom:8px}.feed-detail-status{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:999px;font-size:12px;font-weight:700;background:#fff;border:1px solid rgba(var(--fd-accent),.28);color:var(--fd-strong);box-shadow:0 2px 6px rgba(var(--fd-accent),.1)}.feed-detail-status .pi{font-size:13px}.feed-detail-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:14px}.feed-detail-chip{display:inline-flex;align-items:center;gap:6px;padding:7px 11px;border-radius:12px;background:#ffffffeb;border:1px solid #e2e8f0;font-size:12px;font-weight:600;color:#334155;line-height:1.3;box-shadow:0 1px 4px #0f172a0a}.feed-detail-chip .pi{font-size:13px;color:#6366f1;flex-shrink:0}.feed-detail-chip em{font-style:normal;font-weight:500;color:#94a3b8;margin-left:4px}.feed-detail-chip--time .pi{color:#dc2626}.feed-detail-chip--time span{font-variant-numeric:tabular-nums;font-weight:700;color:#dc2626}.feed-detail-chip--muted{background:#f8fafc;border-color:#e2e8f0;color:#64748b;font-weight:500}.feed-detail-chip--muted .pi{color:#94a3b8}.feed-detail-body{padding:16px 18px 8px;overflow-y:auto;flex:1;min-height:0}.feed-detail-section{margin-bottom:14px}.feed-detail-section:last-child{margin-bottom:0}.feed-detail-section__title{margin:0 0 10px;font-size:12px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#64748b;display:flex;align-items:center;gap:7px}.feed-detail-section__title .pi{font-size:13px;color:#6366f1}.feed-detail-cards{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.feed-detail-card{display:flex;align-items:flex-start;gap:12px;padding:12px 13px;border-radius:14px;background:linear-gradient(180deg,#fafbff,#fff);border:1px solid #e2e8f0;box-shadow:0 2px 8px #0f172a0a}.feed-detail-card--warn,.feed-detail-card--gap.feed-detail-card--warn{border-color:#f59e0b66;background:linear-gradient(180deg,#fffbeb,#fff)}.feed-detail-card--warn .feed-detail-card__icon,.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__icon{background:#fef3c7;color:#b45309}.feed-detail-card--warn .feed-detail-card__text,.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__text{color:#92400e}.feed-detail-card--position{border-color:#8b5cf659;background:linear-gradient(180deg,#f5f3ff,#fff)}.feed-detail-card--average{border-color:#0ea5e959;background:linear-gradient(180deg,#f0f9ff,#fff)}.feed-detail-card--next{border-color:#10b98159;background:linear-gradient(180deg,#ecfdf5,#fff)}.feed-detail-card--gap:not(.feed-detail-card--warn){border-color:#64748b59;background:linear-gradient(180deg,#f8fafc,#fff)}.feed-detail-card__icon{flex-shrink:0;width:36px;height:36px;border-radius:10px;display:grid;place-items:center;background:#eef2ff;color:#4f46e5;font-size:15px}.feed-detail-card__icon[data-kind=position]{background:#ede9fe;color:#7c3aed}.feed-detail-card__icon[data-kind=average]{background:#e0f2fe;color:#0284c7}.feed-detail-card__icon[data-kind=next]{background:#d1fae5;color:#059669}.feed-detail-card__icon[data-kind=gap]{background:#e2e8f0;color:#475569}.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__icon{background:#fef3c7;color:#b45309}.feed-detail-card__body{min-width:0;flex:1}.feed-detail-card__label{display:block;font-size:11px;font-weight:800;color:#64748b;margin-bottom:3px;letter-spacing:.02em}.feed-detail-card__text{margin:0;font-size:13px;line-height:1.5;color:#0f172a}.fdc-position__head{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin-bottom:8px}.fdc-position__idx{font-size:18px;font-weight:800;color:#6d28d9;letter-spacing:-.02em}.fdc-position__of{font-size:14px;font-weight:700;color:#a78bfa}.fdc-position__tag{font-size:11px;font-weight:600;color:#64748b;padding:2px 8px;border-radius:999px;background:#8b5cf61a}.fdc-progress{height:8px;border-radius:999px;background:#ede9fe;overflow:hidden;margin-bottom:10px}.fdc-progress__fill{height:100%;border-radius:inherit;background:linear-gradient(90deg,#8b5cf6,#6366f1);transition:width .2s ease}.fdc-position__stats{display:flex;flex-wrap:wrap;gap:8px}.fdc-stat{display:inline-flex;align-items:baseline;gap:4px;padding:6px 10px;border-radius:10px;font-size:12px}.fdc-stat strong{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums}.fdc-stat small{font-size:11px;font-weight:600;opacity:.85}.fdc-stat--violet{background:#f5f3ff;color:#5b21b6}.fdc-stat--violet strong{color:#6d28d9}.fdc-stat--indigo{background:#eef2ff;color:#4338ca}.fdc-stat--indigo strong{color:#4f46e5}.fdc-avg,.fdc-next{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}.fdc-pill{display:inline-flex;padding:4px 10px;border-radius:999px;font-size:13px;font-weight:800;font-variant-numeric:tabular-nums}.fdc-pill--up{background:#dcfce7;color:#15803d}.fdc-pill--down{background:#fee2e2;color:#b91c1c}.fdc-pill--neutral{background:#f1f5f9;color:#475569}.fdc-avg__meta{font-size:12px;color:#64748b;line-height:1.4}.fdc-avg__meta strong{color:#0f172a;font-weight:700}.fdc-next__time{font-size:16px;font-weight:800;color:#dc2626;font-variant-numeric:tabular-nums}.fdc-next__vol{font-size:14px;font-weight:800;color:#059669;padding:4px 10px;border-radius:8px;background:#d1fae5}.fdc-next__gap{font-size:12px;font-weight:600;color:#64748b;display:inline-flex;align-items:center;gap:4px}.fdc-gap{display:flex;flex-direction:column;gap:10px}.fdc-gap__prev{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px;padding:10px 12px;border-radius:10px;background:#ffffffe6;border:1px solid #e2e8f0}.fdc-gap__prev-label{font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#64748b;width:100%}.fdc-gap__prev-time{font-size:17px;font-weight:800;color:#0f172a;font-variant-numeric:tabular-nums}.fdc-gap__prev-vol{font-size:14px;font-weight:800;color:#475569;padding:3px 8px;border-radius:8px;background:#f1f5f9}.fdc-gap__prev-date{font-size:11px;font-weight:600;color:#94a3b8}.fdc-gap__row{display:flex;flex-wrap:nowrap;align-items:center;gap:8px;min-width:0}.fdc-gap__interval{display:inline-flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;padding:6px 10px;border-radius:999px;font-size:12px;font-weight:700;color:#475569;background:#e2e8f0;white-space:nowrap}.fdc-gap__interval .pi{font-size:13px;flex-shrink:0}.fdc-gap__interval span{overflow:hidden;text-overflow:ellipsis}.fdc-gap__interval--warn{color:#b45309;background:#fde68a;border:1px solid rgba(245,158,11,.35)}.fdc-gap__vol-diff{flex:0 0 auto;white-space:nowrap;font-size:12px;padding:5px 10px}.feed-detail-quote{margin:0;padding:12px 14px 12px 16px;border-radius:0;border-left:3px solid #c7d2fe;background:#f8fafc;font-size:14px;line-height:1.55;color:#334155;font-style:normal}.feed-detail-footer{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#fafbff}.feed-detail-cta{display:flex;gap:8px;justify-content:stretch}.feed-detail-cta .btn{flex:1;justify-content:center}.feed-detail-cta .btn.primary{flex:1.2}.feed-group-detail-dialog .feed-group-detail-summary{margin:0 0 8px;padding:0 2px;font-size:13px;line-height:1.45}.feed-group-detail-dialog .feed-group-detail-hint{margin:0 0 12px;font-size:12px;line-height:1.4;display:flex;align-items:center;gap:6px}.feed-group-detail-dialog .feed-group-detail-history{margin-bottom:4px}.feed-group-detail-dialog .feed-group-detail-rows{max-height:min(58vh,420px);overflow-y:auto;padding-right:2px}.mom-food-card{--mf-tone: 244, 114, 182;--mf-soft: #fdf2f8;--mf-ring: #fbcfe8;--mf-strong: #db2777;position:relative;overflow:hidden;background:radial-gradient(900px 260px at 0% 0%,rgba(var(--mf-tone),.14),transparent 60%),#fff;border-color:rgba(var(--mf-tone),.22);padding:18px;margin-top:16px}.mom-food-card[data-accent=rose]{--mf-tone: 244, 63, 94;--mf-soft: #fff1f2;--mf-ring: #fecdd3;--mf-strong: #e11d48}.mom-food-card[data-accent=peach]{--mf-tone: 251, 146, 60;--mf-soft: #fff7ed;--mf-ring: #fed7aa;--mf-strong: #ea580c}.mom-food-card[data-accent=mint]{--mf-tone: 16, 185, 129;--mf-soft: #ecfdf5;--mf-ring: #a7f3d0;--mf-strong: #059669}.mom-food-card[data-accent=lavender]{--mf-tone: 139, 92, 246;--mf-soft: #f5f3ff;--mf-ring: #ddd6fe;--mf-strong: #7c3aed}.mom-food-card[data-accent=amber]{--mf-tone: 245, 158, 11;--mf-soft: #fffbeb;--mf-ring: #fde68a;--mf-strong: #d97706}.mf-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:12px}.mf-head__lead{min-width:0;flex:1}.mf-head .eyebrow{display:inline-flex;align-items:center;gap:6px;color:var(--mf-strong);font-weight:700}.mf-head .eyebrow i{font-size:13px}.mf-head h2{margin:4px 0 0;font-size:18px;font-weight:800;color:var(--text);line-height:1.25}.mf-headline{margin:4px 0 0;font-size:13px;color:var(--mf-strong);font-weight:600}.mf-nav{display:inline-flex;align-items:center;gap:6px;background:var(--mf-soft);border-radius:999px;padding:4px;border:1px solid rgba(var(--mf-tone),.25);flex-shrink:0}.mf-arrow{width:30px;height:30px;border-radius:50%;border:none;background:#fff;color:var(--mf-strong);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .15s ease,background .15s ease}.mf-arrow i{font-size:12px}.mf-arrow:hover:not(:disabled){transform:scale(1.08);background:var(--mf-strong);color:#fff}.mf-arrow:disabled{opacity:.35;cursor:not-allowed}.mf-step{font-variant-numeric:tabular-nums;font-size:12px;color:var(--muted);padding:0 4px}.mf-step strong{color:var(--mf-strong);font-weight:800;font-size:13px}.mf-reset{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--mf-strong);background:transparent;border:1px dashed rgba(var(--mf-tone),.5);border-radius:999px;padding:4px 12px;cursor:pointer;margin-bottom:10px;transition:background .15s ease}.mf-reset:hover{background:var(--mf-soft)}.mf-reset i{font-size:11px}.mf-desc{margin:0 0 14px;font-size:13px;color:var(--muted);line-height:1.55}.mf-columns{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px}@media(max-width:640px){.mf-columns{grid-template-columns:1fr}}.mf-col{padding:12px 14px;border-radius:14px;background:#fff;border:1px solid #eef0f3}.mf-col--good{background:linear-gradient(180deg,#f0fdf4,#fff 80%);border-color:#bbf7d0}.mf-col--bad{background:linear-gradient(180deg,#fef2f2,#fff 80%);border-color:#fecaca}.mf-col-title{display:flex;align-items:center;gap:8px;margin:0 0 10px;font-size:14px;font-weight:800;color:var(--text);letter-spacing:.01em}.mf-dot{width:22px;height:22px;border-radius:50%;display:inline-grid;place-items:center;color:#fff;flex-shrink:0;font-size:11px}.mf-dot i{font-size:10px}.mf-dot.good{background:#10b981;box-shadow:0 2px 6px #10b9814d}.mf-dot.bad{background:#ef4444;box-shadow:0 2px 6px #ef44444d}.mf-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.mf-item{display:flex;align-items:flex-start;gap:10px;padding:8px 10px;border-radius:10px;background:#ffffffb3;transition:background .15s ease,transform .15s ease}.mf-item:hover{background:#fff;transform:translate(2px)}.mf-item--bad .mf-name{color:#7f1d1d}.mf-item--good .mf-name{color:#064e3b}.mf-emoji{width:28px;height:28px;border-radius:8px;background:#fff;display:inline-grid;place-items:center;font-size:16px;flex-shrink:0;box-shadow:0 1px 2px #0f172a0f}.mf-emoji--x{background:#fef2f2;color:#ef4444}.mf-emoji--x i{font-size:12px}.mf-item-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.mf-name{font-size:13px;font-weight:700;color:var(--text);line-height:1.3}.mf-note{font-size:11.5px;color:var(--muted);line-height:1.35}.mf-tip{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;border-radius:12px;background:var(--mf-soft);border:1px solid rgba(var(--mf-tone),.22);font-size:12.5px;color:var(--text);line-height:1.5}.mf-tip i{color:var(--mf-strong);font-size:15px;margin-top:1px;flex-shrink:0}.mom-tab .card{padding:12px 14px;margin-bottom:10px;border-radius:14px}.mom-tab .mom-wellness-section,.mom-tab .mom-tips-week{margin-bottom:10px}.mom-tab .mom-food-card{padding:12px 14px;margin-top:10px}.mom-tab .mf-head{margin-bottom:8px}.mom-tab .mf-head h2{font-size:16px}.mom-tab .mf-desc{margin-bottom:10px;font-size:12px;line-height:1.45;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.mom-tab .mf-columns{gap:8px;margin-bottom:8px}.mom-tab .mf-col{padding:8px 10px}.mom-tab .mf-list{gap:6px}.mom-tab .mf-item{padding:6px 8px}.mom-tab .mf-tip{padding:8px 10px;font-size:12px}.mom-hero{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;margin-bottom:14px;background:linear-gradient(135deg,#fdf2f8,#faf5ff,#eef2ff);border:1px solid #f9a8d4;border-radius:16px}.mom-hero .mom-hero__icon{font-size:36px;line-height:1;flex-shrink:0}.mom-hero h2{margin:0 0 6px;font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.02em}.mom-hero .mom-hero__sub{margin:0;font-size:13px;line-height:1.5;color:var(--muted)}.mom-hero .mom-hero__sub strong{color:var(--text)}.mom-hero .mom-hero__sub .muted-inline{display:block;margin-top:4px;font-size:12.5px;opacity:.92}.mom-hero--compact{align-items:center;padding:10px 12px;margin-bottom:10px;border-radius:14px;gap:10px}.mom-hero--compact .mom-hero__icon{font-size:26px}.mom-hero--compact h2{margin:0;font-size:16px;letter-spacing:-.01em}.mom-hero--compact .mom-hero__title-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px}.mom-hero--compact .mom-hero__baby{font-size:12px;font-weight:700;color:#be185d;padding:2px 8px;border-radius:999px;background:#ffffffbf;border:1px solid rgba(244,114,182,.35)}.mom-hero--compact .mom-hero__sub{margin:4px 0 0;font-size:11.5px;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.mom-hero--compact .mom-hero__sub .muted-inline{display:inline;margin-top:0;font-size:11.5px}.section-head--tight{margin-bottom:8px}.section-head--tight h3{margin:0}.mom-disclaimer--compact{font-size:11px;line-height:1.4;padding:8px 10px;margin-top:4px;margin-bottom:6px}.section-head{margin-bottom:14px}.section-head h3{margin:0 0 6px;font-size:16px;font-weight:800;display:flex;align-items:center;gap:8px;color:var(--text)}.section-head h3 i{color:#db2777;font-size:15px}.section-head .section-sub{margin:0;font-size:12.5px;color:var(--muted);line-height:1.45}.mom-wellness-section{margin-bottom:16px}.mom-tab .mom-wellness-grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:8px}.mom-wellness-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.mom-w-card{padding:14px 14px 12px;border-radius:14px;border:1px solid var(--border);background:#fafafa;transition:border-color .15s,box-shadow .15s}.mom-w-card:hover{border-color:#f472b6;box-shadow:0 6px 18px -12px #db277759}.mom-w-card .mom-w-card__icon{width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,#fce7f3,#ede9fe);display:flex;align-items:center;justify-content:center;margin-bottom:10px}.mom-w-card .mom-w-card__icon i{font-size:16px;color:#be185d}.mom-w-card h4{margin:0 0 8px;font-size:13.5px;font-weight:800;color:var(--text);line-height:1.3}.mom-w-card p{margin:0;font-size:12.5px;line-height:1.5;color:var(--muted)}.mom-tips-week{margin-bottom:16px}.mom-tab .mom-tips-list{gap:6px}.mom-tab .mom-tips-list li{padding:8px 10px;border-radius:10px}.mom-tab .mom-tips-list li strong{margin-bottom:2px;font-size:12px}.mom-tab .mom-tips-list li span{font-size:11.5px;line-height:1.4}.mom-tips-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px}.mom-tips-list li{display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border-radius:12px;background:#fefce8;border:1px solid #fde047}.mom-tips-list li>i{color:#ca8a04;margin-top:2px;flex-shrink:0}.mom-tips-list li strong{display:block;font-size:13px;font-weight:800;color:var(--text);margin-bottom:4px}.mom-tips-list li span{font-size:12.5px;line-height:1.5;color:var(--muted)}.mom-disclaimer{margin-top:8px;margin-bottom:8px}.mom-empty-profile{max-width:520px;margin:24px auto 40px;text-align:center}.mom-empty-profile__inner{padding:28px 22px}.mom-empty-profile__inner .mom-empty-emoji{font-size:48px;display:block;margin-bottom:12px}.mom-empty-profile__inner h2{margin:0 0 10px;font-size:17px;font-weight:800;color:var(--text)}.mom-empty-profile__inner p{margin:0 0 18px;font-size:14px;line-height:1.55;color:var(--muted)}.event-reminder-dialog{max-width:min(520px,100vw - 28px);padding-bottom:8px}.event-reminder-dialog__head{align-items:flex-start;margin-bottom:4px}.event-reminder-dialog__title{margin:0;padding-right:40px;font-size:20px;font-weight:800;line-height:1.3;color:var(--text, #0f172a);display:flex;align-items:center;gap:10px;letter-spacing:-.02em}.event-reminder-dialog__title .pi-bell{color:#f59e0b;font-size:18px;flex-shrink:0}.event-reminder-list{list-style:none;margin:12px 0 0;padding:0;max-height:min(52vh,400px);overflow:auto;display:flex;flex-direction:column;gap:10px}.event-reminder-card{padding:14px 16px;background:linear-gradient(180deg,#fafbff,#fff);border:1px solid #e2e8f0;border-radius:14px;box-shadow:0 2px 8px #0f172a0d}.event-reminder-card__title{margin:0;font-size:16px;font-weight:800;color:var(--text, #0f172a);line-height:1.35}.event-reminder-card__datetime{margin:5px 0 0;font-size:12.5px;font-weight:500;color:#64748b;line-height:1.4}.event-reminder-card__date{color:#475569;font-weight:600}.event-reminder-card__sep{color:#94a3b8}.event-reminder-card__hour{color:#dc2626;font-weight:700;font-variant-numeric:tabular-nums}.event-reminder-card__place{margin:6px 0 0;display:flex;align-items:flex-start;gap:6px;font-size:13px;color:#475569;line-height:1.4}.event-reminder-card__place .pi-map-marker{margin-top:2px;flex-shrink:0;font-size:13px;color:var(--primary, #5b6cff)}.event-reminder-card__content-wrap{margin-top:10px;padding-top:10px;border-top:1px solid #eef1f6}.event-reminder-card__content-label{display:block;margin-bottom:4px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:#94a3b8}.event-reminder-card__content{margin:0;font-size:13.5px;color:#334155;line-height:1.5;white-space:pre-wrap}.event-reminder-actions{display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding-top:14px;border-top:1px solid var(--border, #e5e7eb)}.event-reminder-actions__link{flex:0 1 auto;min-width:0;padding:6px 4px;border:none;background:transparent;color:#64748b;font-size:13px;font-weight:600;font-family:inherit;text-decoration:underline;text-underline-offset:3px;cursor:pointer}.event-reminder-actions__link:hover:not(:disabled){color:#334155}.event-reminder-actions__link:disabled{opacity:.5;cursor:not-allowed}.event-reminder-actions__primary{flex:1 1 auto;display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:10px 18px;font-size:15px;font-weight:700;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DocumentsComponent, selector: "app-documents" }, { kind: "component", type: MedicalHistoryComponent, selector: "app-medical-history", inputs: ["user"], outputs: ["openExplorerFile"] }, { kind: "component", type: WeightComponent, selector: "app-weight", inputs: ["user", "birthDate", "gender", "babyName"] }, { kind: "component", type: ActivityLogComponent, selector: "app-activity-log", outputs: ["activityChanged"] }, { kind: "component", type: FeedingScheduleComponent, selector: "app-feeding-schedule", inputs: ["user"] }, { kind: "component", type: FeedingMomComponent, selector: "app-feeding-mom", inputs: ["profile", "editing"], outputs: ["goToFeeding"] }, { kind: "component", type: FeedingChartsComponent, selector: "app-feeding-charts", inputs: ["logs", "now", "nutritionTarget"] }, { kind: "component", type: FeedingNutritionComponent, selector: "app-feeding-nutrition", inputs: ["nutritionTarget", "todayStats", "now", "latestWeightKg", "editing"], outputs: ["goToWeight"] }, { kind: "component", type: FeedingProfileComponent, selector: "app-feeding-profile", inputs: ["user", "profile", "draft", "editing", "maxBirthDate"], outputs: ["save", "cancelEdit", "startEdit", "clearProfile", "draftNameChange", "draftBirthChange", "draftGenderChange"] }, { kind: "component", type: FeedingDialogsComponent, selector: "app-feeding-dialogs", inputs: ["logs", "user", "now", "bottlePrep", "feedingSettings", "prediction", "todayStats", "yesterdayStats", "todayLogs", "yesterdayLogs", "maxBirthDate", "syncError", "syncMessage"], outputs: ["logsChanged", "settingsChanged", "syncErrorChange", "syncMessageChange", "logDialogOpenChange", "bottlePrepClearRequested"] }, { kind: "component", type: FeedingDailyComponent, selector: "app-feeding-daily", inputs: ["logs", "feedingSettings", "now", "nutritionTarget", "user", "syncMessage", "syncError", "logDialogOpen", "loadingLogs", "refreshToken"], outputs: ["logsChanged", "bottlePrepChange", "editLog", "historyOpen", "feedRowClick"] }, { kind: "component", type: HeroHeaderComponent, selector: "app-hero-header", inputs: ["profile", "age", "user", "weightLabel", "isAnyLoading", "showRefresh"], outputs: ["refresh", "openMenu"] }, { kind: "component", type: HeroStatsStripComponent, selector: "app-hero-stats-strip", inputs: ["currentTime", "dateLabel", "nextFeedTime", "nextFeedCountdown", "weightLabel", "whoStatus"] }, { kind: "component", type: NotificationBannerComponent, selector: "app-notification-banner", inputs: ["notifications", "saving", "currentUser", "dialogOpen"], outputs: ["openDialog", "closeDialog", "acknowledge", "acknowledgeAll", "delete", "openComposer"] }, { kind: "component", type: NotificationListComponent, selector: "app-notification-list", inputs: ["notifications", "currentUser", "saving"], outputs: ["back", "acknowledge", "acknowledgeAll", "delete", "openComposer"] }, { kind: "component", type: SubrouteShellComponent, selector: "app-subroute-shell", inputs: ["title"], outputs: ["back"] }, { kind: "component", type: SettingsMenuComponent, selector: "app-settings-menu", inputs: ["appName", "appVersion", "showDocuments", "unreadCount"], outputs: ["close", "select"] }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.SlicePipe, name: "slice" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
17112
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: FeedingComponent, isStandalone: true, selector: "app-feeding", viewQueries: [{ propertyName: "feedingPageRef", first: true, predicate: ["feedingPage"], descendants: true, static: true }, { propertyName: "documentsCmp", first: true, predicate: DocumentsComponent, descendants: true }, { propertyName: "medicalCmp", first: true, predicate: MedicalHistoryComponent, descendants: true }, { propertyName: "weightCmp", first: true, predicate: WeightComponent, descendants: true }, { propertyName: "feedingDialogs", first: true, predicate: ["feedingDialogs"], descendants: true }], ngImport: i0, template: "<div class=\"feeding-root\">\n <div class=\"feeding-page\" #feedingPage>\n <div class=\"backdrop\"></div>\n\n <header class=\"hero\" [class.hero--profile-merged]=\"profile() && !editing() && ageBreakdown()\">\n @if (profile() && !editing() && ageBreakdown(); as age) {\n <!-- \u2550\u2550 REDESIGNED HERO \u2550\u2550 -->\n <app-hero-header\n [profile]=\"profile()!\"\n [age]=\"age\"\n [user]=\"user()\"\n [weightLabel]=\"profileHeroWeightLabel()\"\n [isAnyLoading]=\"isAnyLoading()\"\n [showRefresh]=\"bottomTab() !== 'schedule'\"\n (openMenu)=\"openSettingsMenu()\"\n (openChat)=\"openChatRoute()\"\n (refresh)=\"refreshAll()\"\n >\n <app-activity-log slot=\"activity-log\" (activityChanged)=\"onActivityChanged()\"></app-activity-log>\n </app-hero-header>\n\n <app-hero-stats-strip\n [currentTime]=\"currentTimeStr\"\n [dateLabel]=\"heroDateLabel\"\n [nextFeedTime]=\"prediction()?.nextTime ?? null\"\n [nextFeedCountdown]=\"heroNextFeedCountdown()\"\n [weightLabel]=\"profileHeroWeightLabel()\"\n [whoStatus]=\"nutritionTarget()?.ageLabel ?? null\"\n ></app-hero-stats-strip>\n\n <div class=\"hero-notif-wrap\">\n <app-notification-banner\n [notifications]=\"visibleNotifications()\"\n [saving]=\"notificationSaving()\"\n [currentUser]=\"user()\"\n [dialogOpen]=\"notifDialogOpen()\"\n (openDialog)=\"openNotificationRoute()\"\n (closeDialog)=\"notifDialogOpen.set(false)\"\n (acknowledge)=\"acknowledgeNotification($event)\"\n (acknowledgeAll)=\"notifDialogOpen.set(false); openAcknowledgeAllConfirmDialog()\"\n (delete)=\"deleteNotification($event)\"\n (openComposer)=\"notifDialogOpen.set(false); openNotificationComposerDialog()\"\n ></app-notification-banner>\n </div>\n\n } @else {\n <!-- \u2500\u2500 Fallback: no profile / editing \u2500\u2500 -->\n <div class=\"hero-inner\">\n <div class=\"hero-brand\">\n <div class=\"hero-title-row\">\n <div class=\"hero-title\">\n <div class=\"emoji\" aria-hidden=\"true\">\uD83D\uDC76</div>\n <div class=\"hero-text\">\n <h1>B\u00E9 y\u00EAu c\u1EE7a b\u1EA1n</h1>\n <p class=\"hero-userline\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <strong>{{ user() }}</strong>\n </p>\n </div>\n </div>\n @if (profile() && !editing()) {\n <div class=\"hero-actions\">\n <app-activity-log (activityChanged)=\"onActivityChanged()\"></app-activity-log>\n <button\n class=\"btn icon-btn\"\n type=\"button\"\n (click)=\"feedingDialogs.openFeedingSettingsDialog()\"\n title=\"C\u00E0i \u0111\u1EB7t\"\n aria-label=\"C\u00E0i \u0111\u1EB7t c\u1EEF b\u00FA\"\n >\n <i class=\"pi pi-sliders-h\"></i>\n </button>\n @if (bottomTab() !== 'schedule') {\n <button\n class=\"btn icon-btn\"\n type=\"button\"\n (click)=\"refreshAll()\"\n [disabled]=\"isAnyLoading()\"\n [title]=\"\n isAnyLoading() ? '\u0110ang t\u1EA3i\u2026' : 'T\u1EA3i l\u1EA1i C\u1EEF b\u00FA, C\u00E2n, L\u1ECBch, Y t\u1EBF, T\u00E0i li\u1EC7u'\n \"\n aria-label=\"T\u1EA3i l\u1EA1i C\u1EEF b\u00FA, Th\u1EC3 tr\u1EA1ng, L\u1ECBch, Ti\u1EC1n s\u1EED y t\u1EBF v\u00E0 T\u00E0i li\u1EC7u\"\n >\n <i class=\"pi pi-refresh\" [class.spin]=\"isAnyLoading()\"></i>\n </button>\n }\n </div>\n }\n </div>\n </div>\n\n <div class=\"hero-datetime\" aria-live=\"polite\">\n <div class=\"hero-datetime-strip\">\n <div class=\"hero-datetime-strip__block hero-datetime-strip__block--date\">\n <i class=\"pi pi-calendar\" aria-hidden=\"true\"></i>\n <span class=\"hero-datetime-strip__wd\">{{ heroWeekday }}</span>\n <time class=\"hero-datetime-strip__date\" [attr.datetime]=\"todayDateStr()\">{{\n heroDateNumeric\n }}</time>\n </div>\n <span class=\"hero-datetime-strip__divider\" aria-hidden=\"true\"></span>\n <div class=\"hero-datetime-strip__block hero-datetime-strip__block--time\">\n <i class=\"pi pi-clock\" aria-hidden=\"true\"></i>\n <span class=\"hero-datetime-strip__clock\">{{ currentTimeStr }}</span>\n </div>\n </div>\n </div>\n\n <section class=\"hero-notification\" aria-label=\"Th\u00F4ng b\u00E1o n\u1ED9i b\u1ED9\">\n <!-- watermark background icons -->\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-bell\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-megaphone\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-comments\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--send\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-send\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--star\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-star\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--bolt\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-bolt\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--heart\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-heart\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--info\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-info-circle\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--check\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-check-circle\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--eye\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-eye\"></i>\n </span>\n\n <div class=\"hero-notification__head\">\n <label class=\"hero-notification__composer-label\" for=\"hero-notification-input\">\n <i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i>\n <span>Th\u00F4ng b\u00E1o</span>\n @if (visibleNotifications().length > 0) {\n <span class=\"hero-notification__unread-badge\">{{\n visibleNotifications().length\n }}</span>\n }\n </label>\n <div class=\"hero-notification__head-actions\">\n <button\n type=\"button\"\n class=\"hero-notification__mark-all\"\n (click)=\"openAcknowledgeAllConfirmDialog()\"\n [disabled]=\"notificationSaving() || visibleNotifications().length === 0\"\n title=\"\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc\"\n >\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n \u0110\u00E3 \u0111\u1ECDc t\u1EA5t c\u1EA3\n </button>\n <button\n type=\"button\"\n class=\"hero-notification__add\"\n (click)=\"openNotificationComposerDialog()\"\n aria-label=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n title=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n @if (displayedNotifications().length > 0) {\n <ul class=\"hero-notification__list\">\n @for (notice of displayedNotifications(); track notice) {\n <li class=\"hero-notification__item\">\n <div class=\"hero-notification__avatar\" aria-hidden=\"true\">\n {{ notice.user | slice: 0 : 2 | uppercase }}\n </div>\n <div class=\"hero-notification__body\">\n <div class=\"hero-notification__body-head\">\n <span class=\"hero-notification__author\">{{ notice.user }}</span>\n </div>\n <p class=\"hero-notification__content\">{{ notice.content }}</p>\n @if (notice.createdAt) {\n <span class=\"hero-notification__created\">{{\n formatNotificationCreatedAt(notice.createdAt)\n }}</span>\n }\n </div>\n <div class=\"hero-notification__item-actions\">\n <button\n type=\"button\"\n class=\"hero-notification__ack-top\"\n (click)=\"acknowledgeNotification(notice)\"\n [disabled]=\"notificationSaving()\"\n aria-label=\"\u0110\u00E3 \u0111\u1ECDc th\u00F4ng b\u00E1o\"\n title=\"\u0110\u00E3 \u0111\u1ECDc\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n @if (canDeleteNotification(notice)) {\n <button\n type=\"button\"\n class=\"hero-notification__delete\"\n (click)=\"deleteNotification(notice)\"\n [disabled]=\"notificationSaving()\"\n aria-label=\"X\u00F3a th\u00F4ng b\u00E1o\"\n title=\"X\u00F3a th\u00F4ng b\u00E1o\"\n >\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </li>\n }\n </ul>\n } @else {\n <div class=\"hero-notification__empty\">\n <i class=\"pi pi-bell hero-notification__empty-icon\" aria-hidden=\"true\"></i>\n <span class=\"hero-notification__empty-title\">Kh\u00F4ng c\u00F3 th\u00F4ng b\u00E1o m\u1EDBi</span>\n <span class=\"hero-notification__empty-sub\"\n >M\u1ECDi th\u1EE9 \u0111\u1EC1u \u1ED5n. Th\u00F4ng b\u00E1o m\u1EDBi s\u1EBD xu\u1EA5t hi\u1EC7n \u1EDF \u0111\u00E2y.</span\n >\n </div>\n }\n\n @if (hiddenNotificationCount() > 0) {\n <button\n type=\"button\"\n class=\"hero-notification__more\"\n (click)=\"openNotificationListDialog()\"\n >\n Xem th\u00EAm {{ hiddenNotificationCount() }} th\u00F4ng b\u00E1o \u2192\n </button>\n }\n </section>\n\n </div>\n } <!-- end @else no-profile -->\n </header>\n\n <main\n class=\"content\"\n [class.is-documents]=\"bottomTab() === 'documents'\"\n [class.is-weight]=\"bottomTab() === 'weight'\"\n [class.is-schedule]=\"bottomTab() === 'schedule'\"\n [class.is-mom]=\"bottomTab() === 'mom'\"\n [class.is-medical]=\"bottomTab() === 'medical'\"\n >\n <!--\n ============ TAB PANES ============\n D\u00F9ng `[hidden]` thay v\u00EC `*ngIf` \u0111\u1EC3 c\u00E1c tab c\u00F9ng gi\u1EEF tr\u1EA1ng th\u00E1i khi\n user qua l\u1EA1i: scroll position, search query \u0111ang g\u00F5, viewMode, folder\n \u0111ang \u0111\u1EE9ng, file \u0111ang ch\u1ECDn, draft \u0111ang nh\u1EADp\u2026 \u0111\u1EC1u kh\u00F4ng b\u1ECB reset. H\u1EC7\n qu\u1EA3: `<app-documents>` \u0111\u01B0\u1EE3c mount 1 l\u1EA7n \u1EDF app load \u2014 `loadEntries()`\n ch\u1EA1y 1 l\u1EA7n, c\u00E1c l\u1EA7n switch tab k\u1EBF ti\u1EBFp kh\u00F4ng g\u1ECDi API th\u00EAm.\n -->\n <!-- ============ TAB: DOCUMENTS \u2014 \u0111\u00E3 chuy\u1EC3n sang subroute (m\u1EDF t\u1EEB Settings menu) ============ -->\n\n <!-- ============ TAB: WEIGHT ============ -->\n <div class=\"tab-pane tab-pane--weight\" [hidden]=\"bottomTab() !== 'weight'\">\n <app-weight\n [user]=\"user()\"\n [birthDate]=\"profile()?.birthDate\"\n [gender]=\"profile()?.gender\"\n [babyName]=\"profile()?.babyName\"\n ></app-weight>\n </div>\n\n <!-- ============ TAB: L\u1ECACH \u2014 Google Sheet tab \"Event\" ============ -->\n <div class=\"tab-pane tab-pane--schedule\" [hidden]=\"bottomTab() !== 'schedule'\">\n <app-feeding-schedule [user]=\"user()\"></app-feeding-schedule>\n </div>\n\n <!-- ============ TAB: TI\u1EC0N S\u1EEC Y T\u1EBE \u2014 Medical history V2 ============ -->\n <div class=\"tab-pane tab-pane--medical\" [hidden]=\"bottomTab() !== 'medical'\">\n <app-medical-history\n [user]=\"user()\"\n (openExplorerFile)=\"openMedicalAttachmentInDocuments($event)\"\n ></app-medical-history>\n </div>\n\n <!-- ============ TAB: M\u1EB8 \u2014 \u0111\u00E3 chuy\u1EC3n sang subroute (m\u1EDF t\u1EEB Settings menu) ============ -->\n\n <!-- ============ TAB: FEEDING ============ -->\n <div class=\"tab-pane tab-pane--feeding\" [hidden]=\"bottomTab() !== 'feeding'\">\n <app-feeding-profile\n [user]=\"user()\"\n [profile]=\"profile()\"\n [draft]=\"draft()\"\n [editing]=\"editing()\"\n [maxBirthDate]=\"maxBirthDate\"\n (save)=\"save()\"\n (cancelEdit)=\"cancelEdit()\"\n (startEdit)=\"startEdit()\"\n (clearProfile)=\"clearProfile()\"\n (draftNameChange)=\"updateDraftName($event)\"\n (draftBirthChange)=\"updateDraftBirth($event)\"\n (draftGenderChange)=\"setDraftGender($event)\"\n />\n\n @if (profile() && !editing() && ageBreakdown()) {\n <app-feeding-daily\n [logs]=\"logs()\"\n [feedingSettings]=\"feedingSettings()\"\n [now]=\"now()\"\n [nutritionTarget]=\"nutritionTarget()\"\n [user]=\"user()\"\n [syncMessage]=\"syncMessage()\"\n [syncError]=\"syncError()\"\n [logDialogOpen]=\"logDialogOpen()\"\n [loadingLogs]=\"loadingLogs()\"\n [refreshToken]=\"dailyRefreshToken()\"\n (logsChanged)=\"onFeedingLogsChanged()\"\n (bottlePrepChange)=\"bottlePrep.set($event)\"\n (editLog)=\"feedingDialogs.openEditDialog($event)\"\n (historyOpen)=\"feedingDialogs.openHistoryDialog($event.filter, $event.dateStr)\"\n (feedRowClick)=\"feedingDialogs.onFeedRowClick($event)\"\n >\n <app-feeding-charts\n data-feeding-charts\n [logs]=\"logs()\"\n [now]=\"now()\"\n [nutritionTarget]=\"nutritionTarget()\"\n />\n </app-feeding-daily>\n <app-feeding-nutrition\n [nutritionTarget]=\"nutritionTarget()\"\n [todayStats]=\"todayStats()\"\n [now]=\"now()\"\n [latestWeightKg]=\"latestWeightKgFromSheet()\"\n [editing]=\"editing()\"\n (goToWeight)=\"setBottomTab('weight')\"\n />\n }\n\n <!-- ============ FAB \u00AB Ghi c\u1EEF b\u00FA \u00BB c\u0169 \u0111\u00E3 \u0111\u01B0\u1EE3c thay b\u1EB1ng FAB gi\u1EEFa bottom-nav ============ -->\n </div>\n <!-- /.tab-pane--feeding -->\n </main>\n </div>\n <!-- /.feeding-page -->\n\n <!-- ============ BOTTOM NAVIGATION (C\u1EEF b\u00FA \u00B7 Th\u1EC3 tr\u1EA1ng \u00B7 + \u00B7 L\u1ECBch \u00B7 Y t\u1EBF) ============ -->\n <nav\n class=\"bottom-nav\"\n role=\"tablist\"\n aria-label=\"\u0110i\u1EC1u h\u01B0\u1EDBng ch\u00EDnh\"\n >\n <div class=\"bn-side bn-side--left\">\n @for (tab of navLeftTabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"bn-item\"\n role=\"tab\"\n [attr.aria-selected]=\"bottomTab() === tab.id\"\n [class.active]=\"bottomTab() === tab.id\"\n (click)=\"setBottomTab(tab.id)\"\n >\n <span class=\"bn-icon-wrap\">\n <i class=\"pi {{ tab.icon }} bn-icon\" aria-hidden=\"true\"></i>\n </span>\n <span class=\"bn-label\">{{ tab.label }}</span>\n </button>\n }\n </div>\n\n <button\n type=\"button\"\n class=\"bn-fab\"\n (click)=\"feedingDialogs.openLogDialog()\"\n [disabled]=\"!profile() || editing()\"\n [title]=\"(!profile() || editing()) ? 'Ch\u1ECDn b\u00E9 tr\u01B0\u1EDBc khi ghi c\u1EEF b\u00FA' : 'Ghi nh\u1EADn c\u1EEF b\u00FA m\u1EDBi'\"\n aria-label=\"Ghi nh\u1EADn c\u1EEF b\u00FA\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n\n <div class=\"bn-side bn-side--right\">\n @for (tab of navRightTabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"bn-item\"\n role=\"tab\"\n [attr.aria-selected]=\"bottomTab() === tab.id\"\n [class.active]=\"bottomTab() === tab.id\"\n (click)=\"setBottomTab(tab.id)\"\n >\n <span class=\"bn-icon-wrap\">\n <i class=\"pi {{ tab.icon }} bn-icon\" aria-hidden=\"true\"></i>\n </span>\n <span class=\"bn-label\">{{ tab.label }}</span>\n </button>\n }\n </div>\n </nav>\n\n <!-- ============ NOTIFICATION SUBROUTE (full-screen) ============ -->\n @if (notifRouteOpen()) {\n <app-notification-list\n [notifications]=\"allNotifications()\"\n [currentUser]=\"user()\"\n [saving]=\"notificationSaving()\"\n (back)=\"closeNotificationRoute()\"\n (acknowledge)=\"acknowledgeNotification($event)\"\n (acknowledgeAll)=\"openAcknowledgeAllConfirmDialog()\"\n (delete)=\"deleteNotification($event)\"\n (openComposer)=\"openNotificationComposerDialog()\"\n />\n }\n\n <!-- \u2550\u2550 NOTIFICATION DIALOGS \u2014 rendered as siblings of .feeding-page (outside the\n overflow/stacking-context scroll zone) so they always overlay the\n full-screen notification subroute. See .feeding-page overflow-y:auto +\n -webkit-overflow-scrolling:touch in feeding.component.scss. \u2550\u2550 -->\n @if (notificationComposerDialogOpen()) {\n <div\n class=\"dialog-overlay dialog-overlay--front\"\n (click)=\"closeNotificationComposerDialog()\"\n >\n <div\n class=\"dialog hero-notification-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\" aria-hidden=\"true\"><i class=\"pi pi-bell\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\" aria-hidden=\"true\"><i class=\"pi pi-megaphone\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--send\" aria-hidden=\"true\"><i class=\"pi pi-send\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--star\" aria-hidden=\"true\"><i class=\"pi pi-star\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\" aria-hidden=\"true\"><i class=\"pi pi-comments\"></i></span>\n\n <div class=\"dialog-head hero-notification-dialog__head\">\n <div class=\"hero-notification-dialog__title-group\">\n <div class=\"hero-notification-dialog__icon-wrap\">\n <i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i>\n </div>\n <div>\n <h2 class=\"hero-notification-dialog__title\">T\u1EA1o th\u00F4ng b\u00E1o</h2>\n <p class=\"hero-notification-dialog__subtitle\">Th\u00F4ng b\u00E1o s\u1EBD hi\u1EC3n th\u1ECB cho to\u00E0n b\u1ED9 th\u00E0nh vi\u00EAn</p>\n </div>\n </div>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeNotificationComposerDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <div class=\"hero-notification__composer-panel\">\n <div class=\"hero-notification__composer-row\">\n <div class=\"hero-notification__input-wrap\">\n <textarea\n id=\"hero-notification-input\"\n class=\"hero-notification__input\"\n [value]=\"notificationDraft()\"\n (input)=\"updateNotificationDraft($any($event.target).value)\"\n [disabled]=\"notificationSaving()\"\n maxlength=\"300\"\n placeholder=\"Nh\u1EADp n\u1ED9i dung th\u00F4ng b\u00E1o cho m\u1ECDi ng\u01B0\u1EDDi...\"\n aria-label=\"N\u1ED9i dung th\u00F4ng b\u00E1o\"\n ></textarea>\n <div class=\"hero-notification__char-ring\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 36 36\">\n <circle class=\"hero-notification__char-ring-track\" cx=\"18\" cy=\"18\" r=\"15\" />\n <circle class=\"hero-notification__char-ring-fill\" cx=\"18\" cy=\"18\" r=\"15\"\n [style.stroke-dashoffset]=\"94 - (notificationDraft().trim().length / 300) * 94\" />\n </svg>\n <span class=\"hero-notification__char-count\">{{ notificationDraft().trim().length }}</span>\n </div>\n </div>\n </div>\n <div class=\"hero-notification__composer-actions\">\n <button type=\"button\" class=\"btn ghost hero-notification__cancel\"\n (click)=\"closeNotificationComposerDialog()\" [disabled]=\"notificationSaving()\">H\u1EE7y</button>\n <button type=\"button\" class=\"btn hero-notification__send\"\n (click)=\"createNotification()\"\n [disabled]=\"notificationSaving() || !notificationDraft().trim()\">\n <i class=\"pi pi-send\"></i>\n <span>G\u1EEDi th\u00F4ng b\u00E1o</span>\n </button>\n </div>\n </div>\n @if (notificationError()) {\n <p class=\"hero-notification__error\">{{ notificationError() }}</p>\n }\n </div>\n </div>\n }\n\n @if (notificationListDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeNotificationListDialog()\">\n <div class=\"dialog hero-notification-list-dialog\" role=\"dialog\" aria-modal=\"true\"\n aria-label=\"Danh s\u00E1ch th\u00F4ng b\u00E1o\" (click)=\"$event.stopPropagation()\">\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\" aria-hidden=\"true\"><i class=\"pi pi-bell\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\" aria-hidden=\"true\"><i class=\"pi pi-megaphone\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\" aria-hidden=\"true\"><i class=\"pi pi-comments\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--star\" aria-hidden=\"true\"><i class=\"pi pi-star\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--check\" aria-hidden=\"true\"><i class=\"pi pi-check-circle\"></i></span>\n\n <div class=\"dialog-head hero-notification-list-dialog__head\">\n <div class=\"hero-notification-dialog__title-group\">\n <div class=\"hero-notification-dialog__icon-wrap\"><i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i></div>\n <div>\n <h2 class=\"hero-notification-list-dialog__title\">To\u00E0n b\u1ED9 th\u00F4ng b\u00E1o</h2>\n <p class=\"hero-notification-dialog__subtitle\">{{ visibleNotifications().length }} th\u00F4ng b\u00E1o</p>\n </div>\n </div>\n <div class=\"hero-notification-list-dialog__head-actions\">\n <button type=\"button\" class=\"hero-notification__mark-all\"\n (click)=\"openAcknowledgeAllConfirmDialog()\"\n [disabled]=\"notificationSaving() || visibleNotifications().length === 0\"\n title=\"\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc\">\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i> \u0110\u00E3 \u0111\u1ECDc t\u1EA5t c\u1EA3\n </button>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeNotificationListDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"hero-notification-list-dialog__body\">\n @if (visibleNotifications().length > 0) {\n <ul class=\"hero-notification__list\">\n @for (notice of visibleNotifications(); track notice) {\n <li class=\"hero-notification__item\">\n <div class=\"hero-notification__avatar\" aria-hidden=\"true\">{{ notice.user | slice: 0 : 2 | uppercase }}</div>\n <div class=\"hero-notification__body\">\n <div class=\"hero-notification__body-head\">\n <span class=\"hero-notification__author\">{{ notice.user }}</span>\n </div>\n <p class=\"hero-notification__content\">{{ notice.content }}</p>\n @if (notice.createdAt) {\n <span class=\"hero-notification__created\">{{ formatNotificationCreatedAt(notice.createdAt) }}</span>\n }\n </div>\n <div class=\"hero-notification__item-actions\">\n <button type=\"button\" class=\"hero-notification__ack-top\"\n (click)=\"acknowledgeNotification(notice)\" [disabled]=\"notificationSaving()\"\n aria-label=\"\u0110\u00E3 \u0111\u1ECDc th\u00F4ng b\u00E1o\" title=\"\u0110\u00E3 \u0111\u1ECDc\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n @if (canDeleteNotification(notice)) {\n <button type=\"button\" class=\"hero-notification__delete\"\n (click)=\"deleteNotification(notice)\" [disabled]=\"notificationSaving()\"\n aria-label=\"X\u00F3a th\u00F4ng b\u00E1o\" title=\"X\u00F3a th\u00F4ng b\u00E1o\">\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </li>\n }\n </ul>\n } @else {\n <div class=\"hero-notification__empty\">\n <i class=\"pi pi-bell hero-notification__empty-icon\" aria-hidden=\"true\"></i>\n <span class=\"hero-notification__empty-title\">Kh\u00F4ng c\u00F3 th\u00F4ng b\u00E1o m\u1EDBi</span>\n <span class=\"hero-notification__empty-sub\">M\u1ECDi th\u1EE9 \u0111\u1EC1u \u1ED5n. Th\u00F4ng b\u00E1o m\u1EDBi s\u1EBD xu\u1EA5t hi\u1EC7n \u1EDF \u0111\u00E2y.</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n @if (acknowledgeAllConfirmDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeAcknowledgeAllConfirmDialog()\">\n <div class=\"dialog ack-all-confirm-dialog\" role=\"alertdialog\" aria-modal=\"true\"\n aria-labelledby=\"ack-all-confirm-title\" (click)=\"$event.stopPropagation()\">\n <div class=\"ack-all-confirm-dialog__icon-wrap\" aria-hidden=\"true\"><i class=\"pi pi-check-circle\"></i></div>\n <h2 id=\"ack-all-confirm-title\" class=\"ack-all-confirm-dialog__title\">\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc?</h2>\n <p class=\"ack-all-confirm-dialog__desc\">\n T\u1EA5t c\u1EA3 {{ visibleNotifications().length }} th\u00F4ng b\u00E1o s\u1EBD \u0111\u01B0\u1EE3c \u0111\u00E1nh d\u1EA5u \u0111\u00E3 \u0111\u1ECDc v\u00E0 \u1EA9n kh\u1ECFi danh s\u00E1ch.\n </p>\n <div class=\"ack-all-confirm-dialog__actions\">\n <button type=\"button\" class=\"btn ghost\" (click)=\"closeAcknowledgeAllConfirmDialog()\" [disabled]=\"notificationSaving()\">H\u1EE7y</button>\n <button type=\"button\" class=\"btn ack-all-confirm-dialog__confirm-btn\"\n (click)=\"confirmAcknowledgeAll()\" [disabled]=\"notificationSaving()\">\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i> X\u00E1c nh\u1EADn\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- ============ SETTINGS FLOAT MENU (full-screen) ============ -->\n @if (settingsMenuOpen()) {\n <app-settings-menu\n [appName]=\"appInfo.name\"\n [appVersion]=\"appInfo.version\"\n [showDocuments]=\"explorerEnabled\"\n [unreadCount]=\"visibleNotifications().length\"\n (close)=\"closeSettingsMenu()\"\n (select)=\"onSettingsMenuSelect($event)\"\n />\n }\n\n <!-- ============ M\u1EB8 SUBROUTE (full-screen) ============ -->\n @if (momRouteOpen()) {\n <app-subroute-shell\n title=\"M\u1EB9\"\n (back)=\"closeMomRoute()\"\n >\n <app-feeding-mom\n [profile]=\"profile()\"\n [editing]=\"editing()\"\n (goToFeeding)=\"closeMomRoute(); setBottomTab('feeding')\"\n ></app-feeding-mom>\n </app-subroute-shell>\n }\n\n <!-- ============ T\u00C0I LI\u1EC6U SUBROUTE (full-screen) ============ -->\n @if (documentsRouteOpen()) {\n <app-subroute-shell\n title=\"T\u00E0i li\u1EC7u\"\n (back)=\"closeDocumentsRoute()\"\n >\n <app-documents></app-documents>\n </app-subroute-shell>\n }\n\n <!-- ============ TR\u1EE2 L\u00DD AI SUBROUTE (full-screen, m\u1EDF t\u1EEB n\u00FAt chat tr\u00EAn hero) ============ -->\n @if (chatRouteOpen()) {\n <app-subroute-shell\n title=\"Tr\u1EE3 l\u00FD AI\"\n (back)=\"closeChatRoute()\"\n >\n <app-chat-shell\n [context]=\"chatContext()\"\n [disabled]=\"chatDisabled()\"\n ></app-chat-shell>\n </app-subroute-shell>\n }\n\n <!-- About -->\n @if (aboutDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeAboutDialog()\">\n <div\n class=\"dialog about-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"feeding-about-title\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"dialog-head about-dialog__head\">\n <h2 id=\"feeding-about-title\" class=\"about-dialog__title\">\n <i class=\"pi pi-info-circle\" aria-hidden=\"true\"></i>\n About\n </h2>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeAboutDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <dl class=\"about-dialog__meta\">\n <div class=\"about-dialog__row\">\n <dt>\u1EE8ng d\u1EE5ng</dt>\n <dd>{{ appInfo.name }}</dd>\n </div>\n <div class=\"about-dialog__row\">\n <dt>Phi\u00EAn b\u1EA3n</dt>\n <dd>\n <code>{{ appInfo.version }}</code>\n </dd>\n </div>\n </dl>\n <div class=\"dialog-actions\">\n <button type=\"button\" class=\"btn primary\" (click)=\"closeAboutDialog()\">\u0110\u00F3ng</button>\n </div>\n </div>\n </div>\n }\n\n <!-- Nh\u1EAFc s\u1EF1 ki\u1EC7n l\u1ECBch (sheet Event + Settings) -->\n @if (eventReminderDialogOpen() && scheduleReminderEvents().length > 0) {\n <div\n class=\"dialog-overlay dialog-overlay--front dialog-overlay--event-reminder\"\n (click)=\"closeEventReminderDialog()\"\n >\n <div\n class=\"dialog event-reminder-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"dialog-head event-reminder-dialog__head\">\n <h2 class=\"event-reminder-dialog__title\">\n <i class=\"pi pi-bell\" aria-hidden=\"true\"></i>\n B\u1EA1n c\u00F3 l\u1ECBch s\u1EAFp t\u1EDBi\n </h2>\n <button\n type=\"button\"\n class=\"dialog-close\"\n (click)=\"closeEventReminderDialog()\"\n aria-label=\"\u0110\u00F3ng\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <ul class=\"event-reminder-list\">\n @for (ev of scheduleReminderEvents(); track ev) {\n <li>\n <article class=\"event-reminder-card\">\n <h3 class=\"event-reminder-card__title\">{{ ev.title }}</h3>\n <p class=\"event-reminder-card__datetime\">\n <span class=\"event-reminder-card__date\">{{ formatReminderEventWhen(ev) }}</span>\n <span class=\"event-reminder-card__sep\" aria-hidden=\"true\"> \u2013 </span>\n <span class=\"event-reminder-card__hour\">{{\n formatReminderEventTime(ev.time)\n }}</span>\n </p>\n @if (ev.place) {\n <p class=\"event-reminder-card__place\">\n <i class=\"pi pi-map-marker\" aria-hidden=\"true\"></i>\n <span>{{ ev.place }}</span>\n </p>\n }\n @if (ev.note) {\n <div class=\"event-reminder-card__content-wrap\">\n <span class=\"event-reminder-card__content-label\">N\u1ED9i dung</span>\n <p class=\"event-reminder-card__content\">{{ ev.note }}</p>\n </div>\n }\n </article>\n </li>\n }\n </ul>\n <div class=\"dialog-actions event-reminder-actions\">\n <button\n type=\"button\"\n class=\"event-reminder-actions__link\"\n (click)=\"acknowledgeAllEventReminders()\"\n >\n Kh\u00F4ng nh\u1EAFc l\u1EA1i\n </button>\n <button\n type=\"button\"\n class=\"btn primary event-reminder-actions__primary\"\n (click)=\"skipEventReminderSession()\"\n >\n \u0110\u00E3 hi\u1EC3u\n </button>\n </div>\n </div>\n </div>\n }\n\n <app-feeding-dialogs\n #feedingDialogs\n [logs]=\"logs()\"\n [user]=\"user()\"\n [now]=\"now()\"\n [bottlePrep]=\"bottlePrep()\"\n [feedingSettings]=\"feedingSettings()\"\n [prediction]=\"prediction()\"\n [todayStats]=\"todayStats()\"\n [yesterdayStats]=\"yesterdayStats()\"\n [todayLogs]=\"todayLogs()\"\n [yesterdayLogs]=\"yesterdayLogs()\"\n [maxBirthDate]=\"maxBirthDate\"\n [syncError]=\"syncError()\"\n [syncMessage]=\"syncMessage()\"\n (logsChanged)=\"onFeedingLogsChanged()\"\n (settingsChanged)=\"onFeedingSettingsChanged($event)\"\n (syncErrorChange)=\"syncError.set($event)\"\n (syncMessageChange)=\"syncMessage.set($event)\"\n (logDialogOpenChange)=\"logDialogOpen.set($event)\"\n (bottlePrepClearRequested)=\"clearBottlePrep()\"\n />\n</div>\n<!-- /.feeding-root -->\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;position:absolute;inset:0;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;--bg: #f6f7fb;--surface: #ffffff;--border: #e6e8ef;--border-strong: #d1d5db;--primary: #5b6cff;--primary-2: #4c5cf0;--primary-soft: #eef0ff;--accent: #ff5c8a;--accent-soft: #ffe7ef;--mint: #10b981;--mint-soft: #d1fae5;--amber: #f59e0b;--amber-soft: #fef3c7;--rose: #ef4444;--rose-soft: #fee2e2;--text: #0f172a;--muted: #64748b;--muted-2: #94a3b8}.feeding-root{flex:1;min-height:0;width:100%;display:flex;flex-direction:column;position:relative}.feeding-root .bp-prep-user{font-weight:800;color:#0369a1;background:#0ea5e933;padding:0 5px;margin-right:2px;border-radius:5px;white-space:nowrap;transition:color .2s,background .2s}.feeding-root .bp-prep-time{font-weight:800;font-variant-numeric:tabular-nums;color:#0284c7;background:linear-gradient(180deg,#f0f9ff,#e0f2fe);border:1px solid rgba(14,165,233,.35);padding:1px 7px;margin-left:2px;border-radius:6px;white-space:nowrap;box-shadow:0 1px #ffffffa6 inset;transition:color .2s,background .2s,border-color .2s}.feeding-page{position:relative;flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;color:var(--text);padding-bottom:calc(170px + env(safe-area-inset-bottom,0px))}.backdrop{position:fixed;inset:0;background:var(--bg);z-index:-1}.hero-notif-wrap{padding:0 16px 8px}.hero{padding:0;background:#fffffff5;border-bottom:1px solid rgba(226,232,240,.9)}@media(max-width:640px){.hero{padding-top:calc(26px + env(safe-area-inset-top,0px));padding-bottom:10px}}.hero-inner{max-width:1100px;margin:0 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:14px 18px}.hero-brand{min-width:0}.hero-title-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0;width:100%}.hero-title{display:flex;align-items:center;gap:12px;min-width:0;flex:1}.hero-title .emoji{font-size:36px;line-height:1;flex-shrink:0;filter:drop-shadow(0 2px 4px rgba(15,23,42,.08))}@media(max-width:640px){.hero-title .emoji{font-size:32px}}.hero-title .hero-text{min-width:0}.hero-title h1{margin:0;font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.02em;line-height:1.2}@media(max-width:640px){.hero-title h1{font-size:17px}}.hero-title .hero-userline{margin:5px 0 0;display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px 6px;font-size:12.5px;color:var(--muted)}.hero-title .hero-userline i{font-size:12px;color:var(--primary);opacity:.9}.hero-title .hero-userline strong{color:var(--primary);font-weight:700;letter-spacing:.01em}.hero-title .hero-userline .hero-last-update{font-size:11px;color:#94a3b8;font-weight:400}.hero--profile-merged{background:var(--primary-soft);padding-bottom:10px;margin-bottom:8px}.hero-title--merged{align-items:flex-start}.hero-title--merged .emoji{font-size:30px}.hero-title--merged h1{font-size:18px;line-height:1.15}.hero-merged-head{display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px;min-width:0;row-gap:6px}.hero-age-chip{font-size:10.5px;font-weight:800;letter-spacing:.04em;text-transform:lowercase;color:var(--primary);background:var(--primary-soft);padding:3px 9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--primary) 18%,transparent);white-space:nowrap}.hero-merged-stat{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:700;color:var(--muted);background:#94a3b824;border:1px solid rgba(148,163,184,.28);white-space:nowrap;line-height:1.25}.hero-merged-stat>i{font-size:10px;opacity:.88;color:var(--muted-2)}.hero-merged-stat--weight>i{color:var(--accent);opacity:1}.hero-merged-meta{margin:5px 0 0;display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;font-size:11.5px;line-height:1.45;color:var(--muted)}.hero-merged-meta .dot{color:var(--muted-2);font-weight:700;-webkit-user-select:none;user-select:none}.hero-merged-meta i{font-size:10px;margin-right:3px;color:var(--muted-2);opacity:.95}.hero-merged-meta strong{color:var(--primary);font-weight:700}.hero-merged-sync{color:#94a3b8;font-weight:400;font-size:11px}.hero-actions--merged{flex-shrink:0}.hero-profile-menu{position:relative;flex:0 0 auto;list-style:none}.hero-profile-menu__trigger{list-style:none}.hero-profile-menu__trigger::-webkit-details-marker{display:none}.hero-profile-menu__trigger::marker{content:\"\"}.hero-profile-menu__panel{position:absolute;top:calc(100% + 6px);right:0;z-index:30;min-width:180px;padding:6px;border-radius:12px;border:1px solid var(--border);background:#fff;box-shadow:0 8px 24px -8px #0f172a2e}.hero-profile-menu__item{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border:0;border-radius:8px;background:transparent;font:inherit;font-size:13px;font-weight:600;color:var(--text);text-align:left;cursor:pointer;transition:background .12s ease,color .12s ease}.hero-profile-menu__item i{font-size:14px;color:var(--muted-2);width:1.1em;text-align:center}.hero-profile-menu__item:hover:not(:disabled){background:var(--primary-soft, #eef0ff);color:var(--primary)}.hero-profile-menu__item:hover:not(:disabled) i{color:var(--primary)}.hero-profile-menu__item--danger:hover:not(:disabled){color:var(--rose);background:var(--rose-soft)}.hero-profile-menu__item--danger:hover:not(:disabled) i{color:var(--rose)}.about-dialog{max-width:360px}.about-dialog__head{margin-bottom:8px}.about-dialog__title{display:flex;align-items:center;gap:8px;margin:0;font-size:18px;font-weight:700}.about-dialog__title i{color:var(--primary)}.about-dialog__meta{margin:0 0 16px;padding:0}.about-dialog__row{display:grid;grid-template-columns:96px 1fr;gap:8px 12px;padding:10px 0;border-bottom:1px solid var(--border)}.about-dialog__row:last-child{border-bottom:0}.about-dialog__row dt{margin:0;font-size:13px;font-weight:600;color:var(--muted-2)}.about-dialog__row dd{margin:0;font-size:14px;font-weight:600;color:var(--text)}.about-dialog__row dd code{font-size:13px;font-weight:600;padding:2px 8px;border-radius:6px;background:var(--primary-soft, #eef0ff);color:var(--primary)}@media(max-width:640px){.hero-title--merged .emoji{font-size:26px}.hero-merged-meta{font-size:11px}.hero-merged-stat{font-size:10.5px;padding:2px 7px}}.hero-datetime{display:flex;flex-wrap:wrap;align-items:center;flex-shrink:0}.hero-datetime-strip{display:inline-flex;align-items:stretch;flex-wrap:nowrap;max-width:100%;min-height:34px;border:1px solid var(--border);border-radius:8px;background:linear-gradient(180deg,#fff,#f1f5f9);box-shadow:0 1px 1px #0f172a0d}.hero-datetime-strip__block{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;min-width:0}.hero-datetime-strip__block>.pi{font-size:12px;color:var(--primary);opacity:.82;flex-shrink:0}.hero-datetime-strip__block--date{flex-wrap:wrap;row-gap:0}.hero-datetime-strip__wd{font-size:10px;font-weight:700;color:var(--muted);text-transform:capitalize;letter-spacing:.02em;line-height:1.15;max-width:88px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hero-datetime-strip__date{font-size:12px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--text);letter-spacing:.02em;white-space:nowrap}.hero-datetime-strip__divider{align-self:stretch;width:1px;margin:5px 0;background:#94a3b866;flex-shrink:0}.hero-datetime-strip__clock{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:.04em;color:var(--primary);line-height:1;white-space:nowrap}.hero-datetime-strip__block--time{padding-right:10px}.hero-datetime-strip__block--time>.pi{font-size:11px}@media(max-width:520px){.hero-inner{flex-direction:column;align-items:stretch}.hero-datetime{width:100%;justify-content:flex-start}.hero-datetime-strip{flex:1 1 auto;width:100%;justify-content:space-between}.hero-notification__composer-row{flex-direction:column;align-items:stretch}.hero-notification__send,.hero-notification__cancel{width:100%;justify-content:center}}.hero-notification__bg-icon{position:absolute;pointer-events:none;color:var(--primary);opacity:.13;line-height:1}.hero-notification__bg-icon i{display:block}.hero-notification__bg-icon--bell{top:8%;left:6%;font-size:28px;transform:rotate(-18deg)}.hero-notification__bg-icon--megaphone{top:10%;right:8%;font-size:24px;transform:rotate(12deg)}.hero-notification__bg-icon--comments{bottom:14%;right:10%;font-size:22px;transform:rotate(-8deg)}.hero-notification__bg-icon--send{bottom:10%;left:50%;font-size:20px;transform:rotate(-22deg)}.hero-notification__bg-icon--star{bottom:16%;left:4%;font-size:18px;transform:rotate(20deg)}.hero-notification__bg-icon--bolt{top:46%;right:2%;font-size:20px;transform:rotate(-5deg)}.hero-notification__bg-icon--heart{top:38%;left:14%;font-size:17px;transform:rotate(15deg)}.hero-notification__bg-icon--info{top:4%;left:50%;font-size:18px;transform:rotate(0)}.hero-notification__bg-icon--check{bottom:24%;left:35%;font-size:17px;transform:rotate(8deg)}.hero-notification__bg-icon--eye{top:14%;left:28%;font-size:18px;transform:rotate(-10deg)}.hero-notification{flex:1 1 100%;display:flex;flex-direction:column;gap:10px;margin-top:2px;padding:10px 12px;border:1px solid rgba(148,163,184,.28);border-radius:14px;background:#fff;position:relative;overflow:hidden}.hero-notification__head{display:flex;align-items:center;justify-content:space-between;gap:10px;position:relative}.hero-notification__head-actions{display:inline-flex;align-items:center;gap:6px}.hero-notification__composer-label{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--muted)}.hero-notification__composer-label i{color:var(--primary);font-size:12px}.hero-notification__unread-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:var(--primary);color:#fff;font-size:10px;font-weight:700;line-height:1}.hero-notification__add{width:28px;height:28px;border:1px solid rgba(var(--primary-rgb, 76, 92, 240),.25);border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.1);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0}.hero-notification__add i{font-size:11px}.hero-notification__add:hover:not(:disabled){background:var(--primary);border-color:var(--primary);color:#fff}.hero-notification__mark-all{height:26px;border:none;border-radius:0;background:transparent;color:var(--primary);font-size:11px;font-weight:600;padding:0;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:4px}.hero-notification__mark-all i{font-size:10px}.hero-notification__mark-all:hover:not(:disabled){opacity:.75}.hero-notification__mark-all:disabled{color:var(--muted-2);cursor:default}.hero-notification__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px;position:relative}.hero-notification__item{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:10px;background:#f8fafc;border:1px solid #e2e8f0;position:relative;transition:border-color .18s ease,transform .18s ease}@media(hover:hover){.hero-notification__item:hover{border-color:#c7d2fe;transform:translateY(-1px)}}.hero-notification__avatar{width:34px;height:34px;border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.12);border:1.5px solid rgba(var(--primary-rgb, 76, 92, 240),.22);color:var(--primary);font-size:11px;font-weight:700;letter-spacing:.5px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.hero-notification__body{flex:1;min-width:0;padding-right:52px}.hero-notification__body-head{display:flex;align-items:center;gap:6px;margin-bottom:3px}.hero-notification__author{font-size:12px;font-weight:700;color:var(--text)}.hero-notification__content{margin:0;font-size:13.5px;line-height:1.5;color:var(--text);white-space:pre-wrap;word-break:break-word}.hero-notification__created{display:block;margin-top:4px;font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums}.hero-notification__item-actions{position:absolute;top:7px;right:8px;display:inline-flex;align-items:center;gap:4px}.hero-notification__ack-top{width:24px;height:24px;border:none;border-radius:50%;background:#eff6ff;color:#1d4ed8;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s ease,color .15s ease,transform .15s ease}.hero-notification__ack-top i{font-size:10px}.hero-notification__ack-top:active:not(:disabled){transform:scale(.96)}.hero-notification__ack-top:hover:not(:disabled){background:#dbeafe;color:#1e40af}.hero-notification__delete{width:24px;height:24px;border:none;border-radius:50%;background:transparent;color:#94a3b8;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.hero-notification__delete i{font-size:10px}.hero-notification__delete:hover:not(:disabled){background:#fee2e2;color:#b91c1c}.hero-notification__empty{display:flex;flex-direction:column;align-items:center;gap:4px;padding:16px 8px;position:relative}.hero-notification__empty-icon{font-size:28px;color:var(--primary);opacity:.45;margin-bottom:4px}.hero-notification__empty-title{font-size:13px;font-weight:600;color:var(--muted)}.hero-notification__empty-sub{font-size:11px;color:var(--muted-2);text-align:center}.hero-notification__more{align-self:flex-start;border:none;background:transparent;color:var(--primary);font-size:12px;font-weight:700;cursor:pointer;padding:0;font-family:inherit;position:relative}.hero-notification__more:hover{opacity:.75}.hero-notification__composer-row{display:flex;align-items:stretch;gap:8px;min-width:0}.hero-notification__composer-panel{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid #dbe4f3;border-radius:12px;background:#f8fbff}.hero-notification__input-wrap{flex:1;min-width:0;border-radius:11px;border:1.5px solid #cfd8e6;background:#fff;transition:border-color .15s ease;position:relative}.hero-notification__composer-row:focus-within .hero-notification__input-wrap{border-color:var(--primary)}.hero-notification__input{width:100%;min-width:0;min-height:100px;border:0;border-radius:11px;padding:10px 12px 32px;font-size:13px;line-height:1.45;color:var(--text);background:transparent;font-family:inherit;resize:vertical}.hero-notification__input:focus{outline:none}.hero-notification__char-ring{position:absolute;bottom:8px;right:10px;display:flex;align-items:center;gap:4px;pointer-events:none}.hero-notification__char-ring svg{width:22px;height:22px;transform:rotate(-90deg)}.hero-notification__char-ring-track{fill:none;stroke:#e2e8f0;stroke-width:3}.hero-notification__char-ring-fill{fill:none;stroke:var(--primary);stroke-width:3;stroke-dasharray:94 94;stroke-linecap:round;transition:stroke-dashoffset .2s ease}.hero-notification__char-count{font-size:10px;color:var(--muted-2);font-variant-numeric:tabular-nums}.hero-notification__composer-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px}.hero-notification__send,.hero-notification__cancel{height:36px;border-radius:10px;min-width:86px;padding:0 14px;font-size:12px;font-weight:700}.hero-notification__send{background:var(--primary);color:#fff}.hero-notification__send:not(:disabled):hover{background:var(--primary-2)}.hero-notification__cancel{min-width:72px}.hero-notification__error{margin:0;font-size:12px;color:#b91c1c;position:relative}.hero-notification-dialog{max-width:min(520px,100vw - 24px);overflow:hidden}.hero-notification-dialog .hero-notification__composer-row{align-items:stretch;gap:10px}.hero-notification-dialog .hero-notification__input-wrap{min-height:110px}.hero-notification-dialog__head{margin-bottom:14px}.hero-notification-dialog__title-group{display:flex;align-items:flex-start;gap:10px}.hero-notification-dialog__icon-wrap{width:34px;height:34px;border-radius:10px;background:rgba(var(--primary-rgb, 76, 92, 240),.12);border:1px solid rgba(var(--primary-rgb, 76, 92, 240),.22);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.hero-notification-dialog__icon-wrap i{font-size:14px}.hero-notification-dialog__title{margin:0;font-size:15px;font-weight:800;color:var(--text);line-height:1.3}.hero-notification-dialog__subtitle{margin:2px 0 0;font-size:11px;color:var(--muted-2)}.hero-notification-list-dialog{max-width:min(620px,100vw - 24px)}.hero-notification-list-dialog__head{margin-bottom:10px;align-items:flex-start}.hero-notification-list-dialog__head-actions{display:inline-flex;align-items:center;gap:8px;flex-shrink:0}.hero-notification-list-dialog__title{margin:0;font-size:15px;font-weight:800;color:var(--text);line-height:1.3}.hero-notification-list-dialog__body{max-height:min(60vh,480px);overflow-y:auto;padding-right:2px}.ack-all-confirm-dialog{max-width:min(380px,100vw - 24px);text-align:center;padding:28px 24px 24px;display:flex;flex-direction:column;align-items:center;gap:10px;overflow:hidden}.ack-all-confirm-dialog__icon-wrap{width:52px;height:52px;border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.1);border:1.5px solid rgba(var(--primary-rgb, 76, 92, 240),.2);color:var(--primary);display:flex;align-items:center;justify-content:center;margin-bottom:2px}.ack-all-confirm-dialog__icon-wrap i{font-size:22px}.ack-all-confirm-dialog__title{margin:0;font-size:16px;font-weight:800;color:var(--text)}.ack-all-confirm-dialog__desc{margin:0;font-size:13px;color:var(--muted);line-height:1.55;max-width:280px}.ack-all-confirm-dialog__actions{display:flex;gap:10px;margin-top:6px;width:100%;justify-content:center}.ack-all-confirm-dialog__actions .btn{min-width:96px;height:38px;border-radius:10px;font-size:13px;font-weight:700}.ack-all-confirm-dialog__confirm-btn{background:var(--primary);color:#fff;display:inline-flex;align-items:center;gap:6px}.ack-all-confirm-dialog__confirm-btn i{font-size:12px}.ack-all-confirm-dialog__confirm-btn:not(:disabled):hover{background:var(--primary-2)}.hero-actions{display:flex;gap:8px;align-items:center;flex-shrink:0;align-self:center}.content{width:100%}.content .tab-pane[hidden]{display:none!important}.content .tab-pane--feeding{max-width:1100px;margin:0 auto;padding:0 20px}.content .tab-pane--documents{max-width:none;padding:0}.content .tab-pane--weight{max-width:none;padding:0;background:linear-gradient(180deg,color-mix(in srgb,var(--primary, #5b6cff) 5%,var(--surface, #fff)) 0%,var(--surface, #fff) min(36vh,280px),var(--surface, #fff) 100%)}.content .tab-pane--mom{max-width:1100px;margin:0 auto;padding:0 20px calc(24px + env(safe-area-inset-bottom,0px))}.content .tab-pane--medical{max-width:none;padding:0;background:linear-gradient(180deg,color-mix(in srgb,var(--primary, #5b6cff) 7%,var(--surface, #fff)) 0%,var(--surface, #fff) min(42vh,320px),var(--surface, #fff) 100%)}.bottom-nav{--bn-primary: #5b6cff;--bn-primary-rgb: 91, 108, 255;--bn-inactive: #b0b7c3;--bn-height: 62px;position:fixed;left:0;right:0;bottom:0;width:100%;box-sizing:border-box;z-index:90;display:flex;align-items:center;justify-content:space-between;gap:4px;min-height:var(--bn-height);padding:0 4px env(safe-area-inset-bottom,0px);background:#fffffff5;backdrop-filter:blur(24px) saturate(200%);-webkit-backdrop-filter:blur(24px) saturate(200%);border-top:1px solid rgba(0,0,0,.055);box-shadow:0 -4px 24px -4px #0f172a14}.bottom-nav .bn-side{flex:1;display:flex;align-items:center;justify-content:space-around;min-width:0}.bottom-nav .bn-fab{flex-shrink:0;width:56px;height:56px;margin-top:-20px;border-radius:999px;border:3px solid rgba(255,255,255,.96);background:var(--bn-primary);color:#fff;font-size:22px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:transform .15s ease,background .15s ease,opacity .15s ease}.bottom-nav .bn-fab:hover:not(:disabled){background:var(--primary-2, #4c5cf0);transform:translateY(-2px)}.bottom-nav .bn-fab:active:not(:disabled){transform:translateY(0) scale(.94)}.bottom-nav .bn-fab:disabled{background:var(--bn-inactive);cursor:not-allowed;opacity:.7}.bottom-nav .bn-item{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;height:var(--bn-height);padding:0 2px;background:transparent;border:none;color:var(--bn-inactive);cursor:pointer;font-family:inherit;-webkit-tap-highlight-color:transparent;transition:color .22s ease}.bottom-nav .bn-item .bn-icon-wrap{display:flex;align-items:center;justify-content:center;width:32px;height:30px;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}.bottom-nav .bn-item .bn-icon{font-size:21px;line-height:1;transition:filter .22s ease;display:block}.bottom-nav .bn-item .bn-label{font-size:10px;font-weight:500;letter-spacing:.025em;line-height:1;transition:font-weight .22s ease}.bottom-nav .bn-item:not(.active):hover{color:rgba(var(--bn-primary-rgb),.7)}.bottom-nav .bn-item:active .bn-icon-wrap{transform:scale(.88)}.bottom-nav .bn-item.active{color:var(--bn-primary)}.bottom-nav .bn-item.active .bn-icon-wrap{transform:translateY(-3px) scale(1.15)}.bottom-nav .bn-item.active .bn-icon{filter:drop-shadow(0 2px 8px rgba(var(--bn-primary-rgb),.4))}.bottom-nav .bn-item.active .bn-label{font-weight:700}.card{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:20px;margin-bottom:16px}.card-header{margin-bottom:16px}.card-header h2{margin:0;font-size:18px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:8px}.card-header h2 i{color:var(--primary)}.card-header p{margin:6px 0 0;color:var(--muted);font-size:13px}.eyebrow{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--muted-2);letter-spacing:.06em}.eyebrow i{margin-right:4px}.form{display:flex;flex-direction:column;gap:14px}.field{display:flex;flex-direction:column;gap:6px}.field .label{font-size:12px;font-weight:600;color:var(--muted);letter-spacing:.02em;display:flex;align-items:center;gap:6px;flex-wrap:wrap}.field .label .label-hint{font-size:11px;font-weight:500;color:var(--muted-2);font-style:italic;text-transform:none;letter-spacing:0}.field input[type=text],.field input[type=date],.field input[type=time],.field input[type=number]{padding:12px 14px;border:1.5px solid var(--border);border-radius:10px;font-size:14px;font-family:inherit;color:var(--text);background:#fafbfc;width:100%;min-width:0;box-sizing:border-box;appearance:none;-webkit-appearance:none;transition:border-color .15s,background .15s;min-height:46px;font-variant-numeric:tabular-nums}.field input[type=text]:focus,.field input[type=date]:focus,.field input[type=time]:focus,.field input[type=number]:focus{outline:none;border-color:var(--primary);background:#fff}.field input[type=text]::placeholder,.field input[type=date]::placeholder,.field input[type=time]::placeholder,.field input[type=number]::placeholder{color:var(--muted-2)}.field input[type=number]{-moz-appearance:textfield}.field input[type=number]::-webkit-outer-spin-button,.field input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.radio-group{display:flex;gap:8px;flex-wrap:wrap}.chip{padding:9px 16px;border:1.5px solid var(--border);background:#fff;border-radius:999px;font-size:13px;cursor:pointer;color:var(--text);transition:all .15s;font-family:inherit}.chip:hover{border-color:var(--primary);color:var(--primary)}.chip.active{background:var(--primary);border-color:var(--primary);color:#fff}.form-actions{display:flex;gap:10px;margin-top:4px;flex-wrap:wrap}.btn{display:inline-flex;align-items:center;gap:6px;padding:10px 18px;border:none;border-radius:10px;font-size:14px;font-weight:600;font-family:inherit;cursor:pointer;transition:background .15s,color .15s,border-color .15s}.btn:disabled{opacity:.5;cursor:not-allowed}.btn.small{padding:6px 12px;font-size:12px}.btn.primary{background:var(--primary);color:#fff}.btn.primary:not(:disabled):hover{background:var(--primary-2)}.btn.ghost{background:transparent;color:var(--muted);border:1.5px solid var(--border)}.btn.ghost:hover{color:var(--text);border-color:var(--border-strong)}.btn.danger-ghost{background:transparent;color:var(--rose);border:1.5px solid var(--rose-soft)}.btn.danger-ghost:hover{background:var(--rose-soft)}.btn.icon-btn{padding:0;width:36px;height:36px;justify-content:center;background:transparent;color:var(--muted);border:1.5px solid var(--border);border-radius:10px}.btn.icon-btn i{font-size:14px}.btn.icon-btn:not(:disabled):hover{color:var(--primary);border-color:var(--primary);background:var(--primary-soft)}.btn.icon-btn .spin{animation:spin-refresh .9s linear infinite}@keyframes spin-refresh{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.age-stats{display:flex;align-items:baseline;justify-content:flex-start;gap:16px;padding:14px 16px;background:var(--primary-soft);border-radius:12px}.age-stats .stat{text-align:center}.age-stats .stat .num{font-size:26px;font-weight:700;color:var(--primary);line-height:1;font-variant-numeric:tabular-nums}.age-stats .stat .unit{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-top:3px}.age-stats .dot{color:var(--muted-2);font-size:20px}.period-card{margin-bottom:0}.period-card h2{margin:6px 0 8px;font-size:20px;font-weight:700}.period-card .period-summary{color:var(--muted);font-size:14px;margin:0 0 14px;line-height:1.55}.schedule-grid{display:grid;grid-template-columns:1fr;gap:10px}.schedule{display:flex;gap:12px;padding:12px;background:#fafbfc;border:1px solid var(--border);border-radius:12px}.schedule i{color:var(--primary);font-size:18px;margin-top:2px}.schedule .schedule-title{font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-bottom:2px}.schedule .schedule-text{font-size:14px;color:var(--text);line-height:1.5}.compare-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}@media(max-width:768px){.compare-grid{grid-template-columns:1fr}}.day-card{margin-bottom:0;min-width:0;overflow:hidden}.day-card.today{border-color:#3b82f6;background:linear-gradient(180deg,#dbeafe,#fff 50%)}.day-card.yesterday{background:#fafbfc}.day-date-nav-wrap{position:relative;margin-bottom:12px}.day-date-nav-reset{position:absolute;top:-8px;right:-8px;z-index:1;width:24px;height:24px;border:1px solid var(--border);border-radius:50%;background:#fff;color:var(--muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;box-shadow:0 1px 3px #0f172a14}.day-date-nav-reset i{font-size:10px}.day-date-nav-reset:hover{background:#fee2e2;border-color:#fecaca;color:#dc2626}.day-date-nav-reset:active{background:#fee2e2;color:#dc2626}.day-date-strip{display:grid;grid-template-columns:32px 1fr 32px;gap:6px;align-items:stretch;padding:6px 8px;border-radius:10px;background:#fff;border:1px solid var(--border);touch-action:manipulation}.day-date-strip-scroller{display:flex;gap:4px;min-width:0;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;scrollbar-width:thin;padding:1px 2px}.day-date-strip-scroller::-webkit-scrollbar{height:4px}.day-date-strip-scroller::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:999px}.day-date-strip-day{flex:0 0 64px;scroll-snap-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-width:0;padding:6px 4px;border:1px solid transparent;border-radius:8px;background:#f8fafc;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.day-date-strip-day:hover{background:#eef2ff;border-color:#c7d2fe}.day-date-strip-day.active{background:#dbeafe;border-color:#3b82f6;box-shadow:inset 0 0 0 1px #3b82f626}.day-date-strip-date{font-size:12px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.2}.day-date-strip-ml{font-size:11px;font-weight:600;color:#1d4ed8;font-variant-numeric:tabular-nums;line-height:1.2}.day-date-strip-ml.empty{color:var(--muted);font-weight:500}.day-date-strip-arrow{width:32px;min-height:52px;flex-shrink:0;border:none;border-radius:8px;background:#f1f5f9;color:var(--text);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.day-date-strip-arrow i{font-size:12px}.day-date-strip-arrow:hover:not(:disabled){background:var(--primary);color:#fff}.day-date-strip-arrow:active:not(:disabled){background:var(--primary);color:#fff}.day-date-strip-arrow:disabled{opacity:.35;cursor:not-allowed}.day-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:12px}.day-head h3{margin:4px 0 0;font-size:16px;color:var(--text);font-variant-numeric:tabular-nums}.big-total{display:flex;align-items:baseline;gap:3px}.big-total .num{font-size:32px;font-weight:800;color:var(--text);line-height:1;font-variant-numeric:tabular-nums}.big-total .unit{font-size:14px;color:var(--muted);font-weight:500}.day-stats{display:flex;flex-wrap:wrap;gap:10px 16px;padding:10px 0 0;border-top:1px solid var(--border)}.day-stats>div{font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:5px}.day-stats>div i{color:var(--primary);font-size:12px}.compare-banner{margin-top:12px;padding:12px;background:var(--primary-soft);border-radius:12px;font-size:12px;color:var(--text);display:flex;flex-direction:column;gap:8px}.compare-banner strong{color:var(--primary);font-variant-numeric:tabular-nums;font-weight:700}.compare-banner .compare-row{display:flex;align-items:center;justify-content:space-between;gap:12px}.compare-banner .compare-row:not(:last-child){padding-bottom:8px;border-bottom:1px dashed rgba(15,23,42,.1)}.compare-banner .compare-stats{display:flex;align-items:center;gap:6px;flex:1}.compare-banner .compare-stats .label{color:var(--muted);font-weight:500;font-size:11px}.compare-banner .compare-stats .count{color:var(--muted-2);font-size:11px}.compare-banner .compare-change{display:flex;align-items:center;gap:4px;font-size:11px;font-weight:600;flex-shrink:0}.compare-banner .compare-change i{font-size:10px}.compare-banner .compare-change i.up{color:var(--mint)}.compare-banner .compare-change i.down{color:var(--amber)}.compare-banner .compare-change strong{font-size:12px}.compare-banner .compare-change span{color:var(--muted-2);font-weight:500}.today-logs{margin-top:12px;padding:12px;background:#fafbfc;border:1px solid var(--border);border-radius:12px}.logs-header{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px}.logs-header span{display:flex;align-items:center;gap:6px}.logs-header span:before{content:\"\\1f37c\";font-size:14px}.logs-header .logs-more{text-transform:none;letter-spacing:0;background:transparent;border:none;color:var(--primary);font-size:12px;font-weight:600;padding:4px 8px;border-radius:6px;cursor:pointer;display:inline-flex;align-items:center;gap:3px;transition:background .2s ease}.logs-header .logs-more i{font-size:10px}.logs-header .logs-more:hover{background:var(--primary-soft)}.log-list{display:flex;flex-direction:column;gap:6px;min-width:0}.log-row{display:flex;align-items:center;gap:10px;padding:8px 10px;background:#fafbfc;border-radius:8px;font-size:13px;min-width:0;max-width:100%;transition:all .2s ease;position:relative}.log-row.low-volume .log-volume{color:#f59e0b;font-weight:900}.log-row.high-volume .log-volume{color:#10b981;font-weight:900}.log-row:hover{background:#f1f5f9;transform:translateY(-1px);box-shadow:0 2px 8px #0000000d}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}.log-time{font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;min-width:42px}.log-volume{font-weight:800;color:var(--primary);font-size:16px;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.log-gap{display:inline-flex;align-items:center;gap:3px;padding:2px 7px;background:#f3f4f6;color:#6b7280;border-radius:999px;font-size:10.5px;font-weight:600;white-space:nowrap;flex-shrink:0;font-variant-numeric:tabular-nums;transition:all .2s ease}.log-gap i{font-size:9px;opacity:.7}.log-gap.feed-gap-warn{background:linear-gradient(135deg,#f59e0b,#ea580c);color:#fff;font-weight:700;border:1px solid rgba(234,88,12,.45);box-shadow:0 0 0 1px #fff3 inset,0 2px 8px #ea580c59}.log-gap.feed-gap-warn i{opacity:.95;color:inherit}.log-note{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.log-actions{margin-left:auto;display:inline-flex;align-items:center;gap:2px}.log-edit,.log-del{background:transparent;border:none;color:var(--muted-2);cursor:pointer;padding:4px 6px;border-radius:6px;font-size:12px;transition:all .2s ease}.log-edit:hover{color:var(--primary);background:var(--primary-soft)}.log-del:hover{color:var(--rose);background:var(--rose-soft)}.empty-mini{padding:12px;text-align:center;color:var(--muted-2);font-size:13px;font-style:italic}.countdown-hero{display:flex;flex-direction:column;gap:16px;padding:18px 20px;background:#fff;border-radius:16px;border:1px solid #e6e9ff;transition:all .3s ease;margin-bottom:20px}.countdown-hero .hero-main{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:20px}.countdown-hero .feeding-time-card{flex:1;min-width:0;text-align:center}.countdown-hero .feeding-time-card .time-header{margin-bottom:12px;display:flex;justify-content:center}.countdown-hero .feeding-time-card .time-header .status-badge{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;padding:6px 12px;border-radius:14px;white-space:nowrap}.countdown-hero .feeding-time-card .time-header .status-badge i{font-size:11px}.countdown-hero .feeding-time-card .time-header .status-badge.status-waiting{background:var(--primary-soft);color:var(--primary)}.countdown-hero .feeding-time-card .time-header .status-badge.status-now{background:#fee2e2;color:#dc2626;animation:pulse-gentle 2s ease-in-out infinite;font-size:11px;text-transform:none;font-weight:700}.countdown-hero .feeding-time-card .time-header .status-badge.status-late{background:var(--rose-soft);color:var(--rose)}.countdown-hero .feeding-time-card .time-display .predicted-time{font-size:42px;font-weight:800;line-height:1;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.02em;margin-bottom:4px}.countdown-hero .feeding-time-card .time-display .time-remaining{font-size:15px;font-weight:500;color:var(--muted);font-variant-numeric:tabular-nums}.countdown-hero .countdown-next{display:flex;flex-direction:column;gap:8px;padding-left:16px;border-left:1px dashed #d8dcff;flex-shrink:0;min-width:0}.countdown-hero .next-item{display:flex;align-items:center;gap:6px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.countdown-hero .next-item i{color:var(--primary);font-size:13px}.countdown-hero .next-item strong{font-weight:700}.countdown-hero .next-item .predict-label,.countdown-hero .next-item .recommend-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-2);margin-left:4px}.countdown-hero .next-item .recommend-label{color:var(--mint)}.countdown-hero .volume-info{display:flex;flex-direction:column;gap:8px;padding-left:20px;border-left:1px dashed #d8dcff;flex-shrink:0;min-width:160px;transition:all .3s ease}.countdown-hero .volume-info .volume-row{display:flex;align-items:center;justify-content:space-between;gap:12px}.countdown-hero .volume-info .volume-row .volume-prefix{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-2);flex-shrink:0}.countdown-hero .volume-info .volume-row .volume-amount{font-size:22px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1;text-align:right}.countdown-hero .volume-info .volume-row.predicted-row .volume-prefix,.countdown-hero .volume-info .volume-row.predicted-row .volume-amount{color:var(--primary)}.countdown-hero .volume-info .volume-row.recommended-row .volume-prefix,.countdown-hero .volume-info .volume-row.recommended-row .volume-amount{color:var(--mint)}.countdown-hero[data-status=waiting]{border-color:#bbf7d0;background:linear-gradient(135deg,#f7fef8,#f0fdf4)}.countdown-hero[data-status=waiting] .feeding-time-card .time-display .predicted-time{color:#16a34a}.countdown-hero[data-status=waiting] .feeding-time-card .time-display .time-remaining{color:#15803d}.countdown-hero[data-status=waiting] .feeding-time-card .status-badge.status-waiting{background:#dcfce7!important;color:#15803d!important;border:1px solid #86efac}.countdown-hero[data-status=waiting] .volume-info .volume-amount{color:#16a34a}.countdown-hero[data-status=waiting] .volume-info .volume-prefix{color:#15803d}.countdown-hero[data-status=late]{border-color:#fca5a5;background:linear-gradient(135deg,#fef2f2,#fee2e2)}.countdown-hero[data-status=late] .feeding-time-card .time-display .predicted-time{color:#dc2626}.countdown-hero[data-status=late] .feeding-time-card .time-display .time-remaining{color:#b91c1c}.countdown-hero[data-status=late] .feeding-time-card .status-badge.status-late{background:#fee2e2;color:#dc2626;border:1px solid #fca5a5}.countdown-hero[data-status=late] .volume-info .volume-amount{color:#dc2626}.countdown-hero[data-status=late] .volume-info .volume-prefix{color:#b91c1c}.countdown-hero[data-status=now]{border-color:#fbbf24;background:linear-gradient(135deg,#fefce8,#fef3c7);animation:pulse-card 2s ease-in-out infinite}.countdown-hero[data-status=now] .feeding-time-card .time-display .predicted-time{color:#92400e}.countdown-hero[data-status=now] .feeding-time-card .time-display .time-remaining{color:#a16207}.countdown-hero[data-status=now] .feeding-time-card .status-badge.status-now{background:#fef3c7!important;color:#b45309!important;border:1px solid #f59e0b!important}.countdown-hero[data-status=now] .volume-info .volume-amount{color:#92400e}.countdown-hero[data-status=now] .volume-info .volume-prefix{color:#a16207}@media(max-width:540px){.countdown-hero .hero-main{flex-direction:column;align-items:stretch;gap:12px}.countdown-hero .hero-main .volume-info{border-left:none;border-top:1px dashed #d8dcff;padding-left:0;padding-top:12px;min-width:auto}.countdown-hero .hero-main .volume-info .volume-row{justify-content:space-between;padding:0 4px}.countdown-hero .hero-main .feeding-time-card .time-display .predicted-time{font-size:36px}.countdown-hero .hero-main .feeding-time-card .volume-info .volume-amount{font-size:20px}}@media(max-width:400px){.countdown-hero .feeding-time-card .status-badge{font-size:10px;padding:4px 10px}.countdown-hero .feeding-time-card .time-display .predicted-time{font-size:32px}.countdown-hero .volume-info .volume-amount{font-size:18px}}@keyframes pulse-soft{0%,to{opacity:1}50%{opacity:.65}}@keyframes pulse-gentle{0%,to{opacity:1}50%{opacity:.75}}@keyframes pulse-urgent{0%,to{opacity:1;text-shadow:0 0 0 rgba(239,68,68,0)}50%{opacity:.8;text-shadow:0 0 8px rgba(239,68,68,.25)}}@keyframes pulse-card{0%,to{transform:scale(1);box-shadow:0 1px 3px #0000001a,0 0 #f8717100}50%{transform:scale(1.02);box-shadow:0 4px 12px #00000026,0 0 0 2px #f871714d}}.burp-warning{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;margin:0 0 16px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:1px solid #f59e0b;border-radius:14px;box-shadow:0 2px 8px #f59e0b33;animation:burp-pulse 2s ease-in-out infinite}.burp-warning__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:40px;height:40px;background:#f59e0b;border-radius:50%;color:#fff;font-size:18px;animation:burp-icon-bounce 1.5s ease-in-out infinite}.burp-warning__content{flex:1;min-width:0}.burp-warning__title{font-size:15px;font-weight:700;color:#92400e;margin-bottom:4px}.burp-warning__text{font-size:13px;color:#78350f;line-height:1.5;margin-bottom:8px}.burp-warning__text strong{font-weight:600;color:#92400e}.burp-warning__countdown{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:#ffffffb3;border-radius:8px;font-size:13px;color:#92400e;font-weight:500}.burp-warning__countdown i{font-size:14px;color:#f59e0b}.burp-warning__countdown strong{font-size:16px;font-weight:700;color:#d97706}@keyframes burp-pulse{0%,to{box-shadow:0 2px 8px #f59e0b33}50%{box-shadow:0 4px 16px #f59e0b59}}@keyframes burp-icon-bounce{0%,to{transform:scale(1)}50%{transform:scale(1.1)}}.countdown-progress{margin-top:10px}.countdown-progress .cp-track{position:relative;height:6px;background:#ffffffbf;border-radius:999px;overflow:hidden}.countdown-progress .cp-fill{height:100%;background:linear-gradient(90deg,var(--primary),var(--accent));border-radius:999px;transition:width .4s ease}.countdown-progress .cp-fill[data-status=waiting]{background:linear-gradient(90deg,#22c55e,#16a34a)}.countdown-progress .cp-fill[data-status=late]{background:linear-gradient(90deg,#f87171,#dc2626)}.countdown-progress .cp-fill[data-status=now]{background:linear-gradient(90deg,#fbbf24,#d97706)}.countdown-progress .cp-labels{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:6px;font-size:11.5px;color:var(--muted)}.countdown-progress .cp-labels i{font-size:10px;margin-right:2px;color:var(--muted-2)}.countdown-progress .cp-labels .muted{color:var(--muted-2)}.countdown-progress .cp-labels .cp-right{font-weight:600;color:var(--muted);white-space:nowrap}.predict-head{display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:12px;margin-bottom:16px}.predict-head .eyebrow{color:var(--primary);display:flex;align-items:center;gap:4px}.predict-head .eyebrow.sparkle i{animation:sparkle 2s ease-in-out infinite}.predict-head h2{margin:4px 0 0;font-size:20px;font-weight:700}.last-feed{display:flex;align-items:center;gap:12px;padding:12px 14px;background:#fff;border-radius:12px;margin-bottom:14px;border:1px solid #e8e9ff}.last-feed .last-feed-icon{width:38px;height:38px;border-radius:50%;background:var(--primary-soft);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.last-feed .last-feed-icon i{color:var(--primary);font-size:16px}.last-feed .last-feed-body{flex:1;min-width:0}.last-feed .last-feed-label{font-size:10px;font-weight:700;text-transform:uppercase;color:var(--muted-2);letter-spacing:.06em;margin-bottom:2px}.last-feed .last-feed-value{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.last-feed .last-feed-value strong{color:var(--primary);font-size:18px;font-weight:800}.last-feed .last-feed-value .sep{color:var(--muted-2)}.last-feed .last-feed-value .ago{color:var(--accent);font-weight:600;font-size:13px}.last-feed .last-feed-note{margin-top:4px;font-size:12px;color:var(--muted);font-style:italic;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.predict-empty{padding:14px 16px;background:#fff;border-radius:12px;color:var(--muted);font-size:13px;display:flex;align-items:center;gap:8px}.predict-empty i{color:var(--primary)}.predict-body{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:14px}@media(max-width:640px){.predict-body{grid-template-columns:1fr}}.predict-metric{background:#fff;border-radius:12px;padding:14px;text-align:center}.predict-metric .metric-label{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px;display:flex;align-items:center;justify-content:center;gap:5px}.predict-metric .metric-label i{color:var(--primary);font-size:12px}.predict-metric .metric-value{font-size:28px;font-weight:800;line-height:1;color:var(--primary);font-variant-numeric:tabular-nums}.predict-metric .metric-value .ml-unit{font-size:14px;color:var(--muted);font-weight:500;margin-left:2px}.predict-metric .metric-sub{margin-top:6px;font-size:12px;color:var(--muted)}.reasoning{background:#fff;border-radius:12px;padding:12px 14px;margin-bottom:12px}.reasoning .reasoning-head{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--muted);letter-spacing:.05em;margin-bottom:6px}.reasoning .reasoning-head i{color:var(--primary);margin-right:4px}.reasoning ul{margin:0;padding-left:18px;list-style:disc}.reasoning li{font-size:13px;color:var(--text);line-height:1.55;margin:2px 0}.predict-actions{display:flex;justify-content:flex-end}.feed-list-card{margin-bottom:16px}.feed-list-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:12px}.feed-list-head h2{margin:4px 0 0;font-size:18px;font-weight:700}.feed-list-compact{display:flex;flex-direction:column;gap:6px}.feed-row{display:grid;grid-template-columns:68px 80px 1fr auto;gap:10px;align-items:center;padding:10px 12px;transition:all .2s ease;position:relative}.feed-row.low-volume .feed-row-volume strong{color:#f59e0b;font-weight:900}.feed-row.high-volume .feed-row-volume strong{color:#10b981;font-weight:900}.feed-row{background:#fafbfc;border-radius:10px;border:1px solid var(--border)}.feed-row .feed-row-time{display:flex;flex-direction:column;line-height:1.2;font-variant-numeric:tabular-nums;gap:3px}.feed-row .feed-row-time .time{font-weight:700;color:var(--text);font-size:14px}.feed-row .feed-row-time .date{font-size:11px;color:var(--muted-2)}.feed-row .feed-row-time .feed-row-gap{display:inline-flex;align-items:center;gap:3px;font-size:10.5px;font-weight:600;color:#6b7280;background:#f3f4f6;padding:1px 6px;border-radius:999px;width:fit-content;white-space:nowrap;font-variant-numeric:tabular-nums}.feed-row .feed-row-time .feed-row-gap i{font-size:8px;opacity:.7}.feed-row .feed-row-time .feed-row-gap.feed-gap-warn{background:linear-gradient(135deg,#f59e0b,#ea580c);color:#fff;font-weight:700;border:1px solid rgba(234,88,12,.45);box-shadow:0 0 0 1px #fff3 inset,0 2px 8px #ea580c59}.feed-row .feed-row-time .feed-row-gap.feed-gap-warn i{opacity:.95;color:inherit}.feed-row .feed-row-volume{font-variant-numeric:tabular-nums}.feed-row .feed-row-volume strong{color:var(--primary);font-size:19px;font-weight:800;letter-spacing:-.01em}.feed-row .feed-row-volume .u{font-size:11px;color:var(--muted);margin-left:2px}.feed-row .feed-row-note{font-size:13px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.feed-row .feed-row-note.muted{color:var(--muted-2);font-style:italic}.feed-row .feed-row-actions{display:inline-flex;align-items:center;gap:2px;margin-left:auto}.feed-row .feed-row-edit,.feed-row .feed-row-del{background:transparent;border:none;color:var(--muted-2);cursor:pointer;padding:6px 8px;border-radius:6px;font-size:13px}.feed-row .feed-row-edit:hover{color:var(--primary, #5b6cff);background:#5b6cff1a}.feed-row .feed-row-del:hover{color:var(--rose);background:var(--rose-soft)}@media(max-width:480px){.feed-row{grid-template-columns:58px 70px 1fr auto;gap:8px;padding:8px 10px}.feed-row .feed-row-time .time{font-size:13px}}.dialog-wide{max-width:720px;display:flex;flex-direction:column;padding:0;overflow:hidden}@media(max-width:640px){.dialog-wide{max-height:calc(100dvh - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px) - 72px);border-radius:14px}}.dialog-wide .dialog-head{position:sticky;top:0;z-index:5;background:var(--surface);padding:16px 20px;margin:0;border-bottom:1px solid var(--border);-webkit-backdrop-filter:saturate(1.2) blur(6px);backdrop-filter:saturate(1.2) blur(6px)}@media(max-width:640px){.dialog-wide .dialog-head{padding:12px 14px}}.dialog-wide .dialog-close{width:40px;height:40px;font-size:16px;background:#f1f3f7;color:var(--text)}.dialog-wide .dialog-close:hover{background:var(--rose-soft);color:var(--rose)}.dialog-wide .history-body,.dialog-wide .tips-dialog-body{padding:18px 20px 24px;overflow-y:auto;flex:1;min-height:0}@media(max-width:640px){.dialog-wide .history-body,.dialog-wide .tips-dialog-body{padding:14px 14px 20px}}.history-body{display:flex;flex-direction:column;gap:18px}.history-paging-hint{margin:0;font-size:12px;line-height:1.45}.history-load-more{display:grid;justify-items:center;width:100%;box-sizing:border-box;padding:8px 0 12px}.history-load-more .btn{width:auto;max-width:min(320px,100%);min-width:0;margin-inline:auto;justify-content:center}.tips-nav{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px;background:#f1f3f7;border-radius:12px;margin-bottom:16px}.nav-arrow{width:40px;height:40px;border-radius:50%;border:none;background:#fff;color:var(--primary);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:16px;transition:all .15s;flex-shrink:0}.nav-arrow:hover:not(:disabled){background:var(--primary);color:#fff;transform:scale(1.05)}.nav-arrow:active:not(:disabled){transform:scale(.95)}.nav-arrow:disabled{opacity:.35;cursor:not-allowed}.tips-now-btn{flex:1;padding:9px 16px;border:none;background:transparent;border-radius:999px;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;justify-content:center;gap:6px;transition:all .15s}.tips-now-btn i{font-size:12px}.tips-now-btn:hover{color:var(--primary);background:#fff}.tips-now-btn.active{background:var(--primary);color:#fff;pointer-events:none}.tips-dialog-body .period-summary{font-size:14px;color:var(--muted);line-height:1.6;margin:0 0 14px}.tips-dialog-body .schedule-grid{grid-template-columns:repeat(2,1fr);margin-bottom:16px}@media(max-width:560px){.tips-dialog-body .schedule-grid{grid-template-columns:1fr}}.dialog-tips-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.history-group .history-group-head{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;background:var(--primary-soft);border-radius:10px;margin-bottom:8px}.history-group .history-group-head .h-date{font-size:14px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums}.history-group .history-group-head .h-day{font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.05em}.history-group .history-group-head .h-total{font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.history-group .history-group-head .h-total strong{color:var(--primary);font-size:20px;font-weight:800}.history-group .history-group-head .h-total .h-count{color:var(--muted);font-size:12px;font-weight:500;margin-left:4px}.history-group .history-group-head .h-total .h-avg{color:var(--primary);font-size:12px;font-weight:600;margin-left:4px;font-variant-numeric:tabular-nums}.history-group .history-group-rows{display:flex;flex-direction:column;gap:4px}.tips-section-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px;padding:4px 4px 0}.tips-section-head .eyebrow i{margin-right:4px}.tips-section-head h2{margin:4px 0 0;font-size:20px;font-weight:700;color:var(--text)}.filter-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}.filter-chip{padding:7px 14px;border:1.5px solid var(--border);background:#fff;border-radius:999px;font-size:13px;font-weight:500;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;gap:5px;transition:all .15s;font-family:inherit}.filter-chip i{font-size:12px}.filter-chip:hover{border-color:var(--cat-color, var(--primary));color:var(--cat-color, var(--primary))}.filter-chip.active{background:var(--cat-color, var(--primary));border-color:var(--cat-color, var(--primary));color:#fff}.tips-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;margin-bottom:20px}.tip-card{background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--cat-color, var(--primary));border-radius:12px;padding:16px;transition:transform .15s}.tip-card:hover{transform:translateY(-2px)}.tip-card .tip-head{margin-bottom:8px}.tip-card .tip-pill{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;background:var(--cat-color, var(--primary));color:#fff;font-size:11px;font-weight:600;border-radius:999px;text-transform:uppercase;letter-spacing:.04em}.tip-card .tip-pill i{font-size:10px}.tip-card .tip-title{margin:6px 0 8px;font-size:15px;font-weight:700;line-height:1.35;color:var(--text)}.tip-card .tip-body{margin:0;font-size:13px;line-height:1.55;color:var(--muted)}.empty{grid-column:1/-1;padding:40px 20px;text-align:center;color:var(--muted-2)}.empty i{font-size:32px;margin-bottom:8px;display:block}.upcoming{margin-bottom:24px}.upcoming h3{margin:0 0 12px;font-size:16px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:6px}.upcoming h3 i{color:var(--primary)}.upcoming-grid{display:flex;gap:8px;flex-wrap:wrap}.upcoming-item{padding:10px 14px;background:var(--surface);border:1px solid var(--border);border-radius:10px;font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:6px}.upcoming-item i{color:var(--primary);font-size:12px}.disclaimer{padding:16px;background:var(--amber-soft);border-radius:12px;color:#78350f;font-size:13px;line-height:1.5;margin-bottom:24px;display:flex;gap:8px;align-items:flex-start}.disclaimer i{color:var(--amber);margin-top:2px}.toast{position:fixed;bottom:100px;left:50%;transform:translate(-50%);z-index:90;padding:12px 18px;border-radius:12px;font-size:14px;font-weight:500;box-shadow:0 6px 24px #0f172a1f;display:flex;align-items:center;gap:8px;animation:toastIn .3s cubic-bezier(.4,0,.2,1)}.toast.success{background:var(--mint);color:#fff}.toast.error{background:var(--rose);color:#fff}@keyframes toastIn{0%{transform:translate(-50%,20px);opacity:0}to{transform:translate(-50%);opacity:1}}.fab{position:fixed;bottom:calc(80px + env(safe-area-inset-bottom,0px));right:20px;z-index:96;display:inline-flex;align-items:center;gap:10px;padding:14px 22px 14px 18px;background:var(--primary);color:#fff;border:none;border-radius:999px;font-size:15px;font-weight:700;font-family:inherit;cursor:pointer;box-shadow:0 8px 24px #5b6cff73;transition:transform .15s,box-shadow .15s,background .15s}.fab i{font-size:18px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;background:#ffffff2e}.fab .fab-label{white-space:nowrap}.fab:hover{background:var(--primary-2);transform:translateY(-2px);box-shadow:0 12px 28px #5b6cff8c}.fab:active{transform:translateY(0)}@media(max-width:480px){.fab{padding:14px}.fab .fab-label{display:none}.fab i{font-size:22px;width:28px;height:28px}}.dialog-overlay{position:fixed;inset:0;background:#0f172a8c;z-index:110;display:flex;align-items:center;justify-content:center;padding:20px;animation:overlayIn .2s ease-out}.dialog-overlay.dialog-overlay--front{z-index:400}.dialog-overlay.dialog-overlay--event-reminder{z-index:410}@media(max-width:640px){.dialog-overlay{padding:calc(env(safe-area-inset-top,0px) + 16px) 12px calc(env(safe-area-inset-bottom,0px) + 16px);align-items:flex-start}}@keyframes overlayIn{0%{opacity:0}to{opacity:1}}.dialog{background:var(--surface);border-radius:20px;width:100%;max-width:560px;max-height:min(100vh - 40px,100dvh - 40px);overflow-y:auto;padding:24px;animation:dialogIn .25s cubic-bezier(.4,0,.2,1);box-shadow:0 20px 60px #0f172a40}@media(max-width:640px){.dialog{max-height:calc(100dvh - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px) - 32px);border-radius:16px}}@keyframes dialogIn{0%{opacity:0;transform:translateY(20px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.dialog-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:18px}.dialog-head h2{margin:4px 0 0;font-size:20px;font-weight:700;color:var(--text);display:flex;align-items:center;gap:8px}.dialog-head h2 i{color:var(--primary)}.dialog-close{background:#f1f3f7;border:none;width:36px;height:36px;border-radius:50%;cursor:pointer;color:var(--muted);font-size:14px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;transition:background .15s,color .15s}.dialog-close:hover{background:var(--rose-soft);color:var(--rose)}.log-form{display:flex;flex-direction:column;gap:14px}.log-volume-field{margin:0}.log-volume-field .log-volume-input-row{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px 10px;min-width:0}.log-volume-field .log-volume-input-row>input[type=number]{flex:0 0 118px;width:118px;max-width:min(118px,100%);min-width:0}.log-volume-field .predict-hint--inline{flex:1 1 auto;min-width:0;margin:0;padding:6px 10px;gap:6px;font-size:12px;border-radius:8px}.log-volume-field .predict-hint--inline>i{font-size:13px;flex-shrink:0}.log-volume-field .predict-hint--inline .hint-text{flex:1 1 auto;min-width:0;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.log-volume-field .predict-hint--inline .btn.small{flex-shrink:0;padding:4px 8px;font-size:11px}@media(max-width:400px){.log-volume-field .log-volume-input-row>input[type=number]{flex:1 1 100px;width:100%;max-width:none}.log-volume-field .predict-hint--inline{flex:1 1 100%;white-space:normal}.log-volume-field .predict-hint--inline .hint-text{white-space:normal;overflow:visible;text-overflow:unset}}.edit-date-banner{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:10px 14px;background:linear-gradient(135deg,#eef2ff,#f5f3ff);border:1px solid #dbe1ff;border-radius:12px;font-size:13px;color:var(--text)}.edit-date-banner>i.pi-calendar{color:var(--primary, #5b6cff);font-size:15px}.edit-date-banner .edb-label{color:var(--muted, #6b7280);font-weight:500}.edit-date-banner .edb-value{font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.01em}.edit-date-banner .edb-lock{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;flex-shrink:0;border-radius:50%;background:#ffffffe0;border:1px solid #e2e8f0;color:var(--muted, #64748b)}.edit-date-banner .edb-lock i{font-size:14px;line-height:1}.log-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.log-grid .field.full{grid-column:1/-1}.log-grid.log-grid--date-time{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:560px){.log-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:380px){.log-grid{grid-template-columns:1fr}}.quick-volumes{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.quick-volumes .quick-label{font-size:12px;color:var(--muted);font-weight:600;margin-right:4px}.quick-chip{padding:7px 13px;background:#f1f3f7;border:none;border-radius:999px;font-size:12px;font-weight:600;cursor:pointer;color:var(--muted);transition:all .15s;font-family:inherit}.quick-chip:hover{background:var(--primary-soft);color:var(--primary)}.quick-chip.now-chip{background:var(--primary-soft);color:var(--primary);display:inline-flex;align-items:center;gap:4px}.quick-chip.now-chip:hover{background:var(--primary);color:#fff}.quick-chip.formula-chip{display:inline-flex;align-items:center;gap:5px;background:#fff7ed;color:#c2410c;border:1px solid #fed7aa}.quick-chip.formula-chip i{font-size:11px;opacity:.9}.quick-chip.formula-chip:hover{background:#ffedd5;color:#9a3412;border-color:#fdba74}.quick-chip.formula-chip.active{background:#c2410c;color:#fff;border-color:#c2410c;box-shadow:0 2px 8px #c2410c40}.quick-chip.formula-chip.active:hover{background:#9a3412;border-color:#9a3412;color:#fff}.bottle-prep{background:#f0f9ff;border:1px solid #bae6fd;border-radius:12px;padding:8px 12px;margin-bottom:16px;display:flex;flex-direction:column;gap:8px;transition:background .2s,border-color .2s}.bottle-prep:has(.bp-warning){background:#fffbeb;border-color:#fde68a}.bottle-prep:has(.bp-warning) .bp-info>i{color:#f59e0b}.bottle-prep:has(.bp-warning) .bp-info strong{color:#d97706}.bottle-prep:has(.bp-warning) .bp-prep-user{color:#92400e;background:#fbbf246b}.bottle-prep:has(.bp-warning) .bp-prep-time{color:#c2410c;background:linear-gradient(180deg,#fff7ed,#ffedd5);border-color:#fb923c73}.bottle-prep:has(.bp-form){align-items:stretch;padding:10px 12px 12px}.bottle-prep .bp-warning{display:flex;align-items:center;justify-content:space-between;gap:10px;animation:slideDown .2s ease;flex-wrap:wrap}.bottle-prep .bp-warning__content{display:flex;align-items:center;gap:8px;font-size:13px;flex:1;min-width:0}.bottle-prep .bp-warning__content i{font-size:16px;flex-shrink:0}.bottle-prep .bp-warning__content strong{font-weight:700}.bottle-prep .bp-warning--expired{background:#fef2f2;border:1px solid #fecaca;border-radius:8px;padding:8px 10px;color:#991b1b}.bottle-prep .bp-warning--expired i{color:#dc2626}.bottle-prep .bp-warning--soon{background:#fefce8;border:1px solid #fde68a;border-radius:8px;padding:8px 10px;color:#92400e}.bottle-prep .bp-warning--soon i{color:#f59e0b}.bottle-prep .bp-warning__btn{flex-shrink:0;display:inline-flex;align-items:center;gap:5px;padding:7px 12px;font-size:12px;font-weight:700;font-family:inherit;color:#fff;background:linear-gradient(180deg,#f59e0b,#d97706);border:none;border-radius:8px;cursor:pointer;box-shadow:0 2px 4px #f59e0b40;transition:all .15s ease}.bottle-prep .bp-warning__btn i{font-size:12px}.bottle-prep .bp-warning__btn:hover{background:linear-gradient(180deg,#fbbf24,#f59e0b);transform:translateY(-1px);box-shadow:0 4px 8px #f59e0b59}.bottle-prep .bp-warning__btn:active{transform:translateY(0)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.bottle-prep .bp-info-row{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%}.bottle-prep:not(:has(.bp-warning)):not(:has(.bp-form)){flex-direction:row;align-items:center;justify-content:space-between;flex-wrap:wrap}.bottle-prep .bp-info{display:flex;align-items:flex-start;gap:8px;font-size:14px;color:var(--text);flex:1;min-width:0}.bottle-prep .bp-info>i{color:#0ea5e9;font-size:16px;margin-top:2px;flex-shrink:0}.bottle-prep .bp-info .bp-text{line-height:1.45;min-width:0}.bottle-prep .bp-info .bp-useby{display:inline-block;margin-top:2px;font-size:13px}.bottle-prep .bp-info strong{color:#0284c7;font-weight:800;font-variant-numeric:tabular-nums}.bottle-prep .bp-info .muted{color:var(--muted);font-size:13px}.bottle-prep .bp-actions{display:flex;gap:4px}.bottle-prep .bp-add{flex:1;background:transparent;border:none;padding:6px 4px;font-size:13px;font-weight:600;color:#0284c7;cursor:pointer;display:flex;align-items:center;gap:8px;font-family:inherit;text-align:left}.bottle-prep .bp-add>i{font-size:15px}.bottle-prep .bp-add:hover{color:#0369a1}.bottle-prep .bp-form{display:flex;flex-direction:column;gap:8px;width:100%}.bottle-prep .bp-form-head{display:flex;align-items:center;gap:6px}.bottle-prep .bp-form-head>i{color:#0ea5e9;font-size:15px}.bottle-prep .bp-form-head .bp-label{font-size:13px;color:var(--muted);font-weight:600;white-space:nowrap}.bottle-prep .bp-input-wrap{display:flex;align-items:center;gap:6px;background:#fff;border:1px solid #7dd3fc;border-radius:10px;padding:3px;transition:border-color .15s,box-shadow .15s}.bottle-prep .bp-input-wrap:focus-within{border-color:#0ea5e9;box-shadow:0 0 0 3px #0ea5e926}.bottle-prep .bp-input-wrap .bp-step{width:30px;height:30px;flex-shrink:0;border-radius:8px;border:none;background:#e0f2fe;color:#0369a1;font-size:12px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-family:inherit;transition:all .12s}.bottle-prep .bp-input-wrap .bp-step:hover{background:#bae6fd;color:#0284c7}.bottle-prep .bp-input-wrap .bp-step:active{transform:scale(.94)}.bottle-prep .bp-input-wrap .bp-step:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.bottle-prep .bp-input-wrap .bp-input{flex:1;min-width:60px;padding:4px 6px;font-size:18px;font-weight:800;border:none;background:transparent;font-variant-numeric:tabular-nums;font-family:inherit;color:#d97706;text-align:center;letter-spacing:-.01em}.bottle-prep .bp-input-wrap .bp-input:focus{outline:none}.bottle-prep .bp-input-wrap .bp-input:disabled{opacity:.55;cursor:not-allowed}.bottle-prep .bp-input-wrap .bp-unit{font-size:12px;color:var(--muted);font-weight:600;padding-right:4px}.bottle-prep .bp-quick{display:flex;flex-wrap:wrap;align-items:center;gap:5px}.bottle-prep .bp-quick .bp-quick-label{font-size:11px;color:var(--muted);font-weight:600;margin-right:2px}.bottle-prep .bp-quick .bp-quick-chip{padding:4px 9px;background:#f0f9ff;border:1px solid #7dd3fc;border-radius:999px;font-size:11.5px;font-weight:700;color:#0369a1;cursor:pointer;font-family:inherit;font-variant-numeric:tabular-nums;transition:all .12s}.bottle-prep .bp-quick .bp-quick-chip:hover{background:#e0f2fe;border-color:#38bdf8;color:#0284c7}.bottle-prep .bp-quick .bp-quick-chip:active{transform:scale(.95)}.bottle-prep .bp-quick .bp-quick-chip:disabled{opacity:.45;cursor:not-allowed}.bottle-prep .bp-form-actions{display:flex;gap:6px;justify-content:flex-end}.bottle-prep .bp-btn{width:32px;height:32px;border-radius:8px;border:none;background:#fff;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:12px;transition:all .15s;flex-shrink:0}.bottle-prep .bp-btn:hover:not(:disabled){background:#e0f2fe;color:#0284c7}.bottle-prep .bp-btn:disabled{opacity:.45;cursor:not-allowed}.bottle-prep .bp-btn.primary{background:#0ea5e9;color:#fff}.bottle-prep .bp-btn.primary:hover:not(:disabled){background:#0284c7}.bottle-prep .bp-btn.danger:hover{background:var(--rose-soft);color:var(--rose)}.calc-block{border:1px solid #fde7c2;background:#fffaf0;border-radius:12px;overflow:hidden}.calc-block .calc-head{padding:10px 14px 0}.calc-block .prep-info{display:flex;align-items:flex-start;gap:6px;font-size:13px;color:var(--text)}.calc-block .prep-info>i{color:#f59e0b;font-size:14px;margin-top:2px;flex-shrink:0}.calc-block .prep-info .prep-info-text{line-height:1.45;min-width:0}.calc-block .prep-info strong{color:#d97706;font-weight:800;font-variant-numeric:tabular-nums}.calc-block .prep-info .muted{color:var(--muted-2);font-size:12px;display:inline-block;margin-top:2px}.calc-block .calc-body{padding:8px 14px 14px;display:flex;flex-direction:column;gap:10px}.calc-block .field.mini.remaining-input{position:relative;margin:0;display:flex;flex-direction:column}.calc-block .field.mini.remaining-input .label{font-size:11px;font-weight:600;color:var(--muted);margin-bottom:4px}.calc-block .field.mini.remaining-input input{width:100%;padding:10px 36px 10px 12px;font-size:16px;font-weight:700;border:1px solid #fadf9e;border-radius:8px;background:#fff;font-variant-numeric:tabular-nums;font-family:inherit;color:#d97706}.calc-block .field.mini.remaining-input input:focus{outline:none;border-color:#f59e0b;box-shadow:0 0 0 3px #f59e0b26}.calc-block .field.mini.remaining-input .suffix{position:absolute;right:12px;top:50%;transform:translateY(4px);font-size:12px;color:var(--muted-2);pointer-events:none}.calc-block .calc-result-row{display:flex;align-items:center;justify-content:space-between;gap:10px}.calc-block .calc-result{display:flex;align-items:baseline;gap:4px;font-variant-numeric:tabular-nums}.calc-block .calc-result .calc-label{font-size:13px;color:var(--muted);font-weight:600}.calc-block .calc-result strong{font-size:22px;font-weight:800;color:var(--primary)}.calc-block .calc-result .u{font-size:12px;color:var(--primary);margin-left:2px}.calc-block .calc-result .muted{color:var(--muted-2);font-size:18px}.calc-block .calc-apply{flex-shrink:0}.calc-block .calc-apply:disabled{background:#e5e7eb;color:var(--muted-2);cursor:not-allowed;box-shadow:none}.predict-hint{display:flex;align-items:center;gap:10px;padding:10px 14px;background:linear-gradient(135deg,var(--primary-soft) 0%,var(--accent-soft) 100%);border-radius:10px;font-size:13px}.predict-hint>i{color:var(--primary);font-size:16px}.predict-hint .hint-text{flex:1;color:var(--text)}.predict-hint .hint-text strong{color:var(--primary);font-weight:700}.predict-hint.predict-hint--inline .hint-text strong{font-weight:800;font-variant-numeric:tabular-nums}.sync-error{padding:10px 14px;background:var(--rose-soft);color:#991b1b;border-radius:10px;font-size:13px;display:flex;align-items:center;gap:6px}.sync-success{padding:10px 14px;background:var(--mint-soft);color:#166534;border-radius:10px;font-size:13px;display:flex;align-items:center;gap:6px;animation:fadeIn .2s ease}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:4px}.feeding-settings-dialog .feeding-settings-hint{margin:0 0 14px;font-size:13px;line-height:1.45}.feeding-settings-dialog .feeding-settings-hint code{font-size:11px;padding:1px 5px;border-radius:4px;background:#f1f5f9}.feeding-settings-dialog .feeding-settings-grid{grid-template-columns:1fr;gap:16px}.feeding-settings-dialog .field-hint{display:block;margin-top:8px;font-size:12px;line-height:1.4;padding:8px 12px;background:#f8fafc;border-radius:8px;border-left:3px solid #e2e8f0}.feeding-settings-dialog .label{position:relative}.feeding-settings-dialog .label code{font-size:11px;font-weight:600;color:var(--primary);background:var(--primary-soft);padding:2px 6px;border-radius:4px}.feeding-settings-dialog .label .notification-badge{display:inline-flex;align-items:center;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:#fff;background:linear-gradient(135deg,#10b981,#059669);padding:2px 6px;border-radius:10px;margin-left:6px;box-shadow:0 1px 2px #10b98133;animation:gentle-pulse 2s ease-in-out infinite}.feeding-settings-dialog .notification-setting-field{position:relative}.feeding-settings-dialog .notification-setting-field input{border:1.5px solid #10b981;background:linear-gradient(to right,#fff,#f0fdf4)}.feeding-settings-dialog .notification-setting-field input:focus{border-color:#059669;box-shadow:0 0 0 3px #10b9811a;background:#fff}.feeding-settings-dialog .notification-setting-field input::placeholder{color:#6b7280;opacity:.7}.feeding-settings-dialog .notification-setting-field .field-hint{border-left-color:#10b981;background:linear-gradient(to right,#f0fdf4,#f8fafc)}@keyframes gentle-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.85;transform:scale(1.02)}}.log-time--with-badge,.feed-row-time .time--with-badge{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}.log-merge-badge,.feed-merge-badge{font:inherit;font-size:10px;font-weight:700;padding:2px 7px;border-radius:999px;border:1px solid rgba(99,102,241,.35);background:linear-gradient(135deg,#e0e7ff,#c7d2fe);color:#312e81;cursor:pointer;line-height:1.2;white-space:nowrap}.log-merge-badge:hover,.feed-merge-badge:hover{filter:brightness(1.03)}.log-row--clickable,.feed-row--clickable{cursor:pointer}.log-row--clickable:hover,.feed-row--clickable:hover{background:#6366f10f}.log-row--clickable:focus-visible,.feed-row--clickable:focus-visible{outline:2px solid rgba(99,102,241,.45);outline-offset:2px}.dialog-overlay.dialog-overlay--front.feed-group-detail-overlay{z-index:125}.dialog-overlay.dialog-overlay--front.feed-detail-overlay{z-index:140;animation:overlayIn .12s ease-out}.dialog-overlay.dialog-overlay--front.feed-detail-overlay .feed-detail-dialog{animation:feedDetailIn .14s ease-out}@keyframes feedDetailIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.feed-detail-dialog{--fd-accent: 99, 102, 241;--fd-soft: #eef2ff;--fd-strong: #4338ca;max-width:min(400px,96vw);padding:0;overflow:hidden;display:flex;flex-direction:column}.feed-detail-dialog[data-status=low]{--fd-accent: 245, 158, 11;--fd-soft: #fffbeb;--fd-strong: #b45309}.feed-detail-dialog[data-status=high]{--fd-accent: 244, 63, 94;--fd-soft: #fff1f2;--fd-strong: #e11d48}.feed-detail-dialog[data-status=ok]{--fd-accent: 16, 185, 129;--fd-soft: #ecfdf5;--fd-strong: #059669}.feed-detail-top{position:relative;padding:20px 20px 16px;text-align:center;background:radial-gradient(120% 80% at 50% -20%,rgba(var(--fd-accent),.22),transparent 55%),linear-gradient(180deg,var(--fd-soft) 0%,#ffffff 72%);border-bottom:1px solid rgba(var(--fd-accent),.12)}.feed-detail-close{position:absolute;top:12px;right:12px;width:36px;height:36px;border:none;border-radius:50%;background:#ffffffd9;color:#64748b;cursor:pointer;display:grid;place-items:center;box-shadow:0 2px 8px #0f172a14;transition:background .15s ease,color .15s ease}.feed-detail-close:hover{background:#fff;color:#0f172a}.feed-detail-eyebrow{margin:0 0 6px;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#64748b}.feed-detail-metric{display:flex;align-items:flex-end;justify-content:center;gap:4px;line-height:1;margin-bottom:10px}.feed-detail-metric__value{font-size:clamp(48px,14vw,56px);font-weight:800;letter-spacing:-.04em;color:var(--fd-strong);font-variant-numeric:tabular-nums}.feed-detail-metric__unit{font-size:18px;font-weight:700;color:rgba(var(--fd-accent),.85);padding-bottom:8px}.feed-detail-status{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:999px;font-size:12px;font-weight:700;background:#fff;border:1px solid rgba(var(--fd-accent),.28);color:var(--fd-strong);box-shadow:0 2px 6px rgba(var(--fd-accent),.1)}.feed-detail-status .pi{font-size:13px}.feed-detail-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:14px}.feed-detail-chip{display:inline-flex;align-items:center;gap:6px;padding:7px 11px;border-radius:12px;background:#ffffffeb;border:1px solid #e2e8f0;font-size:12px;font-weight:600;color:#334155;line-height:1.3;box-shadow:0 1px 4px #0f172a0a}.feed-detail-chip .pi{font-size:13px;color:#6366f1;flex-shrink:0}.feed-detail-chip em{font-style:normal;font-weight:500;color:#94a3b8;margin-left:4px}.feed-detail-chip--time .pi{color:#dc2626}.feed-detail-chip--time span{font-variant-numeric:tabular-nums;font-weight:700;color:#dc2626}.feed-detail-chip--muted{background:#f8fafc;border-color:#e2e8f0;color:#64748b;font-weight:500}.feed-detail-chip--muted .pi{color:#94a3b8}.feed-detail-body{padding:16px 18px 8px;overflow-y:auto;flex:1;min-height:0}.feed-detail-section{margin-bottom:14px}.feed-detail-section:last-child{margin-bottom:0}.feed-detail-section__title{margin:0 0 10px;font-size:12px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#64748b;display:flex;align-items:center;gap:7px}.feed-detail-section__title .pi{font-size:13px;color:#6366f1}.feed-detail-cards{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.feed-detail-card{display:flex;align-items:flex-start;gap:12px;padding:12px 13px;border-radius:14px;background:linear-gradient(180deg,#fafbff,#fff);border:1px solid #e2e8f0;box-shadow:0 2px 8px #0f172a0a}.feed-detail-card--warn,.feed-detail-card--gap.feed-detail-card--warn{border-color:#f59e0b66;background:linear-gradient(180deg,#fffbeb,#fff)}.feed-detail-card--warn .feed-detail-card__icon,.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__icon{background:#fef3c7;color:#b45309}.feed-detail-card--warn .feed-detail-card__text,.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__text{color:#92400e}.feed-detail-card--position{border-color:#8b5cf659;background:linear-gradient(180deg,#f5f3ff,#fff)}.feed-detail-card--average{border-color:#0ea5e959;background:linear-gradient(180deg,#f0f9ff,#fff)}.feed-detail-card--next{border-color:#10b98159;background:linear-gradient(180deg,#ecfdf5,#fff)}.feed-detail-card--gap:not(.feed-detail-card--warn){border-color:#64748b59;background:linear-gradient(180deg,#f8fafc,#fff)}.feed-detail-card__icon{flex-shrink:0;width:36px;height:36px;border-radius:10px;display:grid;place-items:center;background:#eef2ff;color:#4f46e5;font-size:15px}.feed-detail-card__icon[data-kind=position]{background:#ede9fe;color:#7c3aed}.feed-detail-card__icon[data-kind=average]{background:#e0f2fe;color:#0284c7}.feed-detail-card__icon[data-kind=next]{background:#d1fae5;color:#059669}.feed-detail-card__icon[data-kind=gap]{background:#e2e8f0;color:#475569}.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__icon{background:#fef3c7;color:#b45309}.feed-detail-card__body{min-width:0;flex:1}.feed-detail-card__label{display:block;font-size:11px;font-weight:800;color:#64748b;margin-bottom:3px;letter-spacing:.02em}.feed-detail-card__text{margin:0;font-size:13px;line-height:1.5;color:#0f172a}.fdc-position__head{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin-bottom:8px}.fdc-position__idx{font-size:18px;font-weight:800;color:#6d28d9;letter-spacing:-.02em}.fdc-position__of{font-size:14px;font-weight:700;color:#a78bfa}.fdc-position__tag{font-size:11px;font-weight:600;color:#64748b;padding:2px 8px;border-radius:999px;background:#8b5cf61a}.fdc-progress{height:8px;border-radius:999px;background:#ede9fe;overflow:hidden;margin-bottom:10px}.fdc-progress__fill{height:100%;border-radius:inherit;background:linear-gradient(90deg,#8b5cf6,#6366f1);transition:width .2s ease}.fdc-position__stats{display:flex;flex-wrap:wrap;gap:8px}.fdc-stat{display:inline-flex;align-items:baseline;gap:4px;padding:6px 10px;border-radius:10px;font-size:12px}.fdc-stat strong{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums}.fdc-stat small{font-size:11px;font-weight:600;opacity:.85}.fdc-stat--violet{background:#f5f3ff;color:#5b21b6}.fdc-stat--violet strong{color:#6d28d9}.fdc-stat--indigo{background:#eef2ff;color:#4338ca}.fdc-stat--indigo strong{color:#4f46e5}.fdc-avg,.fdc-next{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}.fdc-pill{display:inline-flex;padding:4px 10px;border-radius:999px;font-size:13px;font-weight:800;font-variant-numeric:tabular-nums}.fdc-pill--up{background:#dcfce7;color:#15803d}.fdc-pill--down{background:#fee2e2;color:#b91c1c}.fdc-pill--neutral{background:#f1f5f9;color:#475569}.fdc-avg__meta{font-size:12px;color:#64748b;line-height:1.4}.fdc-avg__meta strong{color:#0f172a;font-weight:700}.fdc-next__time{font-size:16px;font-weight:800;color:#dc2626;font-variant-numeric:tabular-nums}.fdc-next__vol{font-size:14px;font-weight:800;color:#059669;padding:4px 10px;border-radius:8px;background:#d1fae5}.fdc-next__gap{font-size:12px;font-weight:600;color:#64748b;display:inline-flex;align-items:center;gap:4px}.fdc-gap{display:flex;flex-direction:column;gap:10px}.fdc-gap__prev{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px;padding:10px 12px;border-radius:10px;background:#ffffffe6;border:1px solid #e2e8f0}.fdc-gap__prev-label{font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#64748b;width:100%}.fdc-gap__prev-time{font-size:17px;font-weight:800;color:#0f172a;font-variant-numeric:tabular-nums}.fdc-gap__prev-vol{font-size:14px;font-weight:800;color:#475569;padding:3px 8px;border-radius:8px;background:#f1f5f9}.fdc-gap__prev-date{font-size:11px;font-weight:600;color:#94a3b8}.fdc-gap__row{display:flex;flex-wrap:nowrap;align-items:center;gap:8px;min-width:0}.fdc-gap__interval{display:inline-flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;padding:6px 10px;border-radius:999px;font-size:12px;font-weight:700;color:#475569;background:#e2e8f0;white-space:nowrap}.fdc-gap__interval .pi{font-size:13px;flex-shrink:0}.fdc-gap__interval span{overflow:hidden;text-overflow:ellipsis}.fdc-gap__interval--warn{color:#b45309;background:#fde68a;border:1px solid rgba(245,158,11,.35)}.fdc-gap__vol-diff{flex:0 0 auto;white-space:nowrap;font-size:12px;padding:5px 10px}.feed-detail-quote{margin:0;padding:12px 14px 12px 16px;border-radius:0;border-left:3px solid #c7d2fe;background:#f8fafc;font-size:14px;line-height:1.55;color:#334155;font-style:normal}.feed-detail-footer{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#fafbff}.feed-detail-cta{display:flex;gap:8px;justify-content:stretch}.feed-detail-cta .btn{flex:1;justify-content:center}.feed-detail-cta .btn.primary{flex:1.2}.feed-group-detail-dialog .feed-group-detail-summary{margin:0 0 8px;padding:0 2px;font-size:13px;line-height:1.45}.feed-group-detail-dialog .feed-group-detail-hint{margin:0 0 12px;font-size:12px;line-height:1.4;display:flex;align-items:center;gap:6px}.feed-group-detail-dialog .feed-group-detail-history{margin-bottom:4px}.feed-group-detail-dialog .feed-group-detail-rows{max-height:min(58vh,420px);overflow-y:auto;padding-right:2px}.mom-food-card{--mf-tone: 244, 114, 182;--mf-soft: #fdf2f8;--mf-ring: #fbcfe8;--mf-strong: #db2777;position:relative;overflow:hidden;background:radial-gradient(900px 260px at 0% 0%,rgba(var(--mf-tone),.14),transparent 60%),#fff;border-color:rgba(var(--mf-tone),.22);padding:18px;margin-top:16px}.mom-food-card[data-accent=rose]{--mf-tone: 244, 63, 94;--mf-soft: #fff1f2;--mf-ring: #fecdd3;--mf-strong: #e11d48}.mom-food-card[data-accent=peach]{--mf-tone: 251, 146, 60;--mf-soft: #fff7ed;--mf-ring: #fed7aa;--mf-strong: #ea580c}.mom-food-card[data-accent=mint]{--mf-tone: 16, 185, 129;--mf-soft: #ecfdf5;--mf-ring: #a7f3d0;--mf-strong: #059669}.mom-food-card[data-accent=lavender]{--mf-tone: 139, 92, 246;--mf-soft: #f5f3ff;--mf-ring: #ddd6fe;--mf-strong: #7c3aed}.mom-food-card[data-accent=amber]{--mf-tone: 245, 158, 11;--mf-soft: #fffbeb;--mf-ring: #fde68a;--mf-strong: #d97706}.mf-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:12px}.mf-head__lead{min-width:0;flex:1}.mf-head .eyebrow{display:inline-flex;align-items:center;gap:6px;color:var(--mf-strong);font-weight:700}.mf-head .eyebrow i{font-size:13px}.mf-head h2{margin:4px 0 0;font-size:18px;font-weight:800;color:var(--text);line-height:1.25}.mf-headline{margin:4px 0 0;font-size:13px;color:var(--mf-strong);font-weight:600}.mf-nav{display:inline-flex;align-items:center;gap:6px;background:var(--mf-soft);border-radius:999px;padding:4px;border:1px solid rgba(var(--mf-tone),.25);flex-shrink:0}.mf-arrow{width:30px;height:30px;border-radius:50%;border:none;background:#fff;color:var(--mf-strong);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .15s ease,background .15s ease}.mf-arrow i{font-size:12px}.mf-arrow:hover:not(:disabled){transform:scale(1.08);background:var(--mf-strong);color:#fff}.mf-arrow:disabled{opacity:.35;cursor:not-allowed}.mf-step{font-variant-numeric:tabular-nums;font-size:12px;color:var(--muted);padding:0 4px}.mf-step strong{color:var(--mf-strong);font-weight:800;font-size:13px}.mf-reset{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--mf-strong);background:transparent;border:1px dashed rgba(var(--mf-tone),.5);border-radius:999px;padding:4px 12px;cursor:pointer;margin-bottom:10px;transition:background .15s ease}.mf-reset:hover{background:var(--mf-soft)}.mf-reset i{font-size:11px}.mf-desc{margin:0 0 14px;font-size:13px;color:var(--muted);line-height:1.55}.mf-columns{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px}@media(max-width:640px){.mf-columns{grid-template-columns:1fr}}.mf-col{padding:12px 14px;border-radius:14px;background:#fff;border:1px solid #eef0f3}.mf-col--good{background:linear-gradient(180deg,#f0fdf4,#fff 80%);border-color:#bbf7d0}.mf-col--bad{background:linear-gradient(180deg,#fef2f2,#fff 80%);border-color:#fecaca}.mf-col-title{display:flex;align-items:center;gap:8px;margin:0 0 10px;font-size:14px;font-weight:800;color:var(--text);letter-spacing:.01em}.mf-dot{width:22px;height:22px;border-radius:50%;display:inline-grid;place-items:center;color:#fff;flex-shrink:0;font-size:11px}.mf-dot i{font-size:10px}.mf-dot.good{background:#10b981;box-shadow:0 2px 6px #10b9814d}.mf-dot.bad{background:#ef4444;box-shadow:0 2px 6px #ef44444d}.mf-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.mf-item{display:flex;align-items:flex-start;gap:10px;padding:8px 10px;border-radius:10px;background:#ffffffb3;transition:background .15s ease,transform .15s ease}.mf-item:hover{background:#fff;transform:translate(2px)}.mf-item--bad .mf-name{color:#7f1d1d}.mf-item--good .mf-name{color:#064e3b}.mf-emoji{width:28px;height:28px;border-radius:8px;background:#fff;display:inline-grid;place-items:center;font-size:16px;flex-shrink:0;box-shadow:0 1px 2px #0f172a0f}.mf-emoji--x{background:#fef2f2;color:#ef4444}.mf-emoji--x i{font-size:12px}.mf-item-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.mf-name{font-size:13px;font-weight:700;color:var(--text);line-height:1.3}.mf-note{font-size:11.5px;color:var(--muted);line-height:1.35}.mf-tip{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;border-radius:12px;background:var(--mf-soft);border:1px solid rgba(var(--mf-tone),.22);font-size:12.5px;color:var(--text);line-height:1.5}.mf-tip i{color:var(--mf-strong);font-size:15px;margin-top:1px;flex-shrink:0}.mom-tab .card{padding:12px 14px;margin-bottom:10px;border-radius:14px}.mom-tab .mom-wellness-section,.mom-tab .mom-tips-week{margin-bottom:10px}.mom-tab .mom-food-card{padding:12px 14px;margin-top:10px}.mom-tab .mf-head{margin-bottom:8px}.mom-tab .mf-head h2{font-size:16px}.mom-tab .mf-desc{margin-bottom:10px;font-size:12px;line-height:1.45;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.mom-tab .mf-columns{gap:8px;margin-bottom:8px}.mom-tab .mf-col{padding:8px 10px}.mom-tab .mf-list{gap:6px}.mom-tab .mf-item{padding:6px 8px}.mom-tab .mf-tip{padding:8px 10px;font-size:12px}.mom-hero{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;margin-bottom:14px;background:linear-gradient(135deg,#fdf2f8,#faf5ff,#eef2ff);border:1px solid #f9a8d4;border-radius:16px}.mom-hero .mom-hero__icon{font-size:36px;line-height:1;flex-shrink:0}.mom-hero h2{margin:0 0 6px;font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.02em}.mom-hero .mom-hero__sub{margin:0;font-size:13px;line-height:1.5;color:var(--muted)}.mom-hero .mom-hero__sub strong{color:var(--text)}.mom-hero .mom-hero__sub .muted-inline{display:block;margin-top:4px;font-size:12.5px;opacity:.92}.mom-hero--compact{align-items:center;padding:10px 12px;margin-bottom:10px;border-radius:14px;gap:10px}.mom-hero--compact .mom-hero__icon{font-size:26px}.mom-hero--compact h2{margin:0;font-size:16px;letter-spacing:-.01em}.mom-hero--compact .mom-hero__title-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px}.mom-hero--compact .mom-hero__baby{font-size:12px;font-weight:700;color:#be185d;padding:2px 8px;border-radius:999px;background:#ffffffbf;border:1px solid rgba(244,114,182,.35)}.mom-hero--compact .mom-hero__sub{margin:4px 0 0;font-size:11.5px;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.mom-hero--compact .mom-hero__sub .muted-inline{display:inline;margin-top:0;font-size:11.5px}.section-head--tight{margin-bottom:8px}.section-head--tight h3{margin:0}.mom-disclaimer--compact{font-size:11px;line-height:1.4;padding:8px 10px;margin-top:4px;margin-bottom:6px}.section-head{margin-bottom:14px}.section-head h3{margin:0 0 6px;font-size:16px;font-weight:800;display:flex;align-items:center;gap:8px;color:var(--text)}.section-head h3 i{color:#db2777;font-size:15px}.section-head .section-sub{margin:0;font-size:12.5px;color:var(--muted);line-height:1.45}.mom-wellness-section{margin-bottom:16px}.mom-tab .mom-wellness-grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:8px}.mom-wellness-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.mom-w-card{padding:14px 14px 12px;border-radius:14px;border:1px solid var(--border);background:#fafafa;transition:border-color .15s,box-shadow .15s}.mom-w-card:hover{border-color:#f472b6;box-shadow:0 6px 18px -12px #db277759}.mom-w-card .mom-w-card__icon{width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,#fce7f3,#ede9fe);display:flex;align-items:center;justify-content:center;margin-bottom:10px}.mom-w-card .mom-w-card__icon i{font-size:16px;color:#be185d}.mom-w-card h4{margin:0 0 8px;font-size:13.5px;font-weight:800;color:var(--text);line-height:1.3}.mom-w-card p{margin:0;font-size:12.5px;line-height:1.5;color:var(--muted)}.mom-tips-week{margin-bottom:16px}.mom-tab .mom-tips-list{gap:6px}.mom-tab .mom-tips-list li{padding:8px 10px;border-radius:10px}.mom-tab .mom-tips-list li strong{margin-bottom:2px;font-size:12px}.mom-tab .mom-tips-list li span{font-size:11.5px;line-height:1.4}.mom-tips-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px}.mom-tips-list li{display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border-radius:12px;background:#fefce8;border:1px solid #fde047}.mom-tips-list li>i{color:#ca8a04;margin-top:2px;flex-shrink:0}.mom-tips-list li strong{display:block;font-size:13px;font-weight:800;color:var(--text);margin-bottom:4px}.mom-tips-list li span{font-size:12.5px;line-height:1.5;color:var(--muted)}.mom-disclaimer{margin-top:8px;margin-bottom:8px}.mom-empty-profile{max-width:520px;margin:24px auto 40px;text-align:center}.mom-empty-profile__inner{padding:28px 22px}.mom-empty-profile__inner .mom-empty-emoji{font-size:48px;display:block;margin-bottom:12px}.mom-empty-profile__inner h2{margin:0 0 10px;font-size:17px;font-weight:800;color:var(--text)}.mom-empty-profile__inner p{margin:0 0 18px;font-size:14px;line-height:1.55;color:var(--muted)}.event-reminder-dialog{max-width:min(520px,100vw - 28px);padding-bottom:8px}.event-reminder-dialog__head{align-items:flex-start;margin-bottom:4px}.event-reminder-dialog__title{margin:0;padding-right:40px;font-size:20px;font-weight:800;line-height:1.3;color:var(--text, #0f172a);display:flex;align-items:center;gap:10px;letter-spacing:-.02em}.event-reminder-dialog__title .pi-bell{color:#f59e0b;font-size:18px;flex-shrink:0}.event-reminder-list{list-style:none;margin:12px 0 0;padding:0;max-height:min(52vh,400px);overflow:auto;display:flex;flex-direction:column;gap:10px}.event-reminder-card{padding:14px 16px;background:linear-gradient(180deg,#fafbff,#fff);border:1px solid #e2e8f0;border-radius:14px;box-shadow:0 2px 8px #0f172a0d}.event-reminder-card__title{margin:0;font-size:16px;font-weight:800;color:var(--text, #0f172a);line-height:1.35}.event-reminder-card__datetime{margin:5px 0 0;font-size:12.5px;font-weight:500;color:#64748b;line-height:1.4}.event-reminder-card__date{color:#475569;font-weight:600}.event-reminder-card__sep{color:#94a3b8}.event-reminder-card__hour{color:#dc2626;font-weight:700;font-variant-numeric:tabular-nums}.event-reminder-card__place{margin:6px 0 0;display:flex;align-items:flex-start;gap:6px;font-size:13px;color:#475569;line-height:1.4}.event-reminder-card__place .pi-map-marker{margin-top:2px;flex-shrink:0;font-size:13px;color:var(--primary, #5b6cff)}.event-reminder-card__content-wrap{margin-top:10px;padding-top:10px;border-top:1px solid #eef1f6}.event-reminder-card__content-label{display:block;margin-bottom:4px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:#94a3b8}.event-reminder-card__content{margin:0;font-size:13.5px;color:#334155;line-height:1.5;white-space:pre-wrap}.event-reminder-actions{display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding-top:14px;border-top:1px solid var(--border, #e5e7eb)}.event-reminder-actions__link{flex:0 1 auto;min-width:0;padding:6px 4px;border:none;background:transparent;color:#64748b;font-size:13px;font-weight:600;font-family:inherit;text-decoration:underline;text-underline-offset:3px;cursor:pointer}.event-reminder-actions__link:hover:not(:disabled){color:#334155}.event-reminder-actions__link:disabled{opacity:.5;cursor:not-allowed}.event-reminder-actions__primary{flex:1 1 auto;display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:10px 18px;font-size:15px;font-weight:700;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DocumentsComponent, selector: "app-documents" }, { kind: "component", type: MedicalHistoryComponent, selector: "app-medical-history", inputs: ["user"], outputs: ["openExplorerFile"] }, { kind: "component", type: WeightComponent, selector: "app-weight", inputs: ["user", "birthDate", "gender", "babyName"] }, { kind: "component", type: ActivityLogComponent, selector: "app-activity-log", outputs: ["activityChanged"] }, { kind: "component", type: FeedingScheduleComponent, selector: "app-feeding-schedule", inputs: ["user"] }, { kind: "component", type: FeedingMomComponent, selector: "app-feeding-mom", inputs: ["profile", "editing"], outputs: ["goToFeeding"] }, { kind: "component", type: FeedingChartsComponent, selector: "app-feeding-charts", inputs: ["logs", "now", "nutritionTarget"] }, { kind: "component", type: FeedingNutritionComponent, selector: "app-feeding-nutrition", inputs: ["nutritionTarget", "todayStats", "now", "latestWeightKg", "editing"], outputs: ["goToWeight"] }, { kind: "component", type: FeedingProfileComponent, selector: "app-feeding-profile", inputs: ["user", "profile", "draft", "editing", "maxBirthDate"], outputs: ["save", "cancelEdit", "startEdit", "clearProfile", "draftNameChange", "draftBirthChange", "draftGenderChange"] }, { kind: "component", type: FeedingDialogsComponent, selector: "app-feeding-dialogs", inputs: ["logs", "user", "now", "bottlePrep", "feedingSettings", "prediction", "todayStats", "yesterdayStats", "todayLogs", "yesterdayLogs", "maxBirthDate", "syncError", "syncMessage"], outputs: ["logsChanged", "settingsChanged", "syncErrorChange", "syncMessageChange", "logDialogOpenChange", "bottlePrepClearRequested"] }, { kind: "component", type: FeedingDailyComponent, selector: "app-feeding-daily", inputs: ["logs", "feedingSettings", "now", "nutritionTarget", "user", "syncMessage", "syncError", "logDialogOpen", "loadingLogs", "refreshToken"], outputs: ["logsChanged", "bottlePrepChange", "editLog", "historyOpen", "feedRowClick"] }, { kind: "component", type: HeroHeaderComponent, selector: "app-hero-header", inputs: ["profile", "age", "user", "weightLabel", "isAnyLoading", "showRefresh", "showChat"], outputs: ["refresh", "openMenu", "openChat"] }, { kind: "component", type: HeroStatsStripComponent, selector: "app-hero-stats-strip", inputs: ["currentTime", "dateLabel", "nextFeedTime", "nextFeedCountdown", "weightLabel", "whoStatus"] }, { kind: "component", type: NotificationBannerComponent, selector: "app-notification-banner", inputs: ["notifications", "saving", "currentUser", "dialogOpen"], outputs: ["openDialog", "closeDialog", "acknowledge", "acknowledgeAll", "delete", "openComposer"] }, { kind: "component", type: NotificationListComponent, selector: "app-notification-list", inputs: ["notifications", "currentUser", "saving"], outputs: ["back", "acknowledge", "acknowledgeAll", "delete", "openComposer"] }, { kind: "component", type: SubrouteShellComponent, selector: "app-subroute-shell", inputs: ["title"], outputs: ["back"] }, { kind: "component", type: SettingsMenuComponent, selector: "app-settings-menu", inputs: ["appName", "appVersion", "showDocuments", "unreadCount"], outputs: ["close", "select"] }, { kind: "component", type: ChatShellComponent, selector: "app-chat-shell", inputs: ["context", "disabled"] }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1$1.SlicePipe, name: "slice" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15825
17113
  }
15826
17114
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: FeedingComponent, decorators: [{
15827
17115
  type: Component,
@@ -15844,7 +17132,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
15844
17132
  NotificationListComponent,
15845
17133
  SubrouteShellComponent,
15846
17134
  SettingsMenuComponent,
15847
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"feeding-root\">\n <div class=\"feeding-page\" #feedingPage>\n <div class=\"backdrop\"></div>\n\n <header class=\"hero\" [class.hero--profile-merged]=\"profile() && !editing() && ageBreakdown()\">\n @if (profile() && !editing() && ageBreakdown(); as age) {\n <!-- \u2550\u2550 REDESIGNED HERO \u2550\u2550 -->\n <app-hero-header\n [profile]=\"profile()!\"\n [age]=\"age\"\n [user]=\"user()\"\n [weightLabel]=\"profileHeroWeightLabel()\"\n [isAnyLoading]=\"isAnyLoading()\"\n [showRefresh]=\"bottomTab() !== 'schedule'\"\n (openMenu)=\"openSettingsMenu()\"\n (refresh)=\"refreshAll()\"\n >\n <app-activity-log slot=\"activity-log\" (activityChanged)=\"onActivityChanged()\"></app-activity-log>\n </app-hero-header>\n\n <app-hero-stats-strip\n [currentTime]=\"currentTimeStr\"\n [dateLabel]=\"heroDateLabel\"\n [nextFeedTime]=\"prediction()?.nextTime ?? null\"\n [nextFeedCountdown]=\"heroNextFeedCountdown()\"\n [weightLabel]=\"profileHeroWeightLabel()\"\n [whoStatus]=\"nutritionTarget()?.ageLabel ?? null\"\n ></app-hero-stats-strip>\n\n <div class=\"hero-notif-wrap\">\n <app-notification-banner\n [notifications]=\"visibleNotifications()\"\n [saving]=\"notificationSaving()\"\n [currentUser]=\"user()\"\n [dialogOpen]=\"notifDialogOpen()\"\n (openDialog)=\"openNotificationRoute()\"\n (closeDialog)=\"notifDialogOpen.set(false)\"\n (acknowledge)=\"acknowledgeNotification($event)\"\n (acknowledgeAll)=\"notifDialogOpen.set(false); openAcknowledgeAllConfirmDialog()\"\n (delete)=\"deleteNotification($event)\"\n (openComposer)=\"notifDialogOpen.set(false); openNotificationComposerDialog()\"\n ></app-notification-banner>\n </div>\n\n } @else {\n <!-- \u2500\u2500 Fallback: no profile / editing \u2500\u2500 -->\n <div class=\"hero-inner\">\n <div class=\"hero-brand\">\n <div class=\"hero-title-row\">\n <div class=\"hero-title\">\n <div class=\"emoji\" aria-hidden=\"true\">\uD83D\uDC76</div>\n <div class=\"hero-text\">\n <h1>B\u00E9 y\u00EAu c\u1EE7a b\u1EA1n</h1>\n <p class=\"hero-userline\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <strong>{{ user() }}</strong>\n </p>\n </div>\n </div>\n @if (profile() && !editing()) {\n <div class=\"hero-actions\">\n <app-activity-log (activityChanged)=\"onActivityChanged()\"></app-activity-log>\n <button\n class=\"btn icon-btn\"\n type=\"button\"\n (click)=\"feedingDialogs.openFeedingSettingsDialog()\"\n title=\"C\u00E0i \u0111\u1EB7t\"\n aria-label=\"C\u00E0i \u0111\u1EB7t c\u1EEF b\u00FA\"\n >\n <i class=\"pi pi-sliders-h\"></i>\n </button>\n @if (bottomTab() !== 'schedule') {\n <button\n class=\"btn icon-btn\"\n type=\"button\"\n (click)=\"refreshAll()\"\n [disabled]=\"isAnyLoading()\"\n [title]=\"\n isAnyLoading() ? '\u0110ang t\u1EA3i\u2026' : 'T\u1EA3i l\u1EA1i C\u1EEF b\u00FA, C\u00E2n, L\u1ECBch, Y t\u1EBF, T\u00E0i li\u1EC7u'\n \"\n aria-label=\"T\u1EA3i l\u1EA1i C\u1EEF b\u00FA, Th\u1EC3 tr\u1EA1ng, L\u1ECBch, Ti\u1EC1n s\u1EED y t\u1EBF v\u00E0 T\u00E0i li\u1EC7u\"\n >\n <i class=\"pi pi-refresh\" [class.spin]=\"isAnyLoading()\"></i>\n </button>\n }\n </div>\n }\n </div>\n </div>\n\n <div class=\"hero-datetime\" aria-live=\"polite\">\n <div class=\"hero-datetime-strip\">\n <div class=\"hero-datetime-strip__block hero-datetime-strip__block--date\">\n <i class=\"pi pi-calendar\" aria-hidden=\"true\"></i>\n <span class=\"hero-datetime-strip__wd\">{{ heroWeekday }}</span>\n <time class=\"hero-datetime-strip__date\" [attr.datetime]=\"todayDateStr()\">{{\n heroDateNumeric\n }}</time>\n </div>\n <span class=\"hero-datetime-strip__divider\" aria-hidden=\"true\"></span>\n <div class=\"hero-datetime-strip__block hero-datetime-strip__block--time\">\n <i class=\"pi pi-clock\" aria-hidden=\"true\"></i>\n <span class=\"hero-datetime-strip__clock\">{{ currentTimeStr }}</span>\n </div>\n </div>\n </div>\n\n <section class=\"hero-notification\" aria-label=\"Th\u00F4ng b\u00E1o n\u1ED9i b\u1ED9\">\n <!-- watermark background icons -->\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-bell\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-megaphone\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-comments\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--send\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-send\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--star\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-star\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--bolt\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-bolt\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--heart\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-heart\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--info\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-info-circle\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--check\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-check-circle\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--eye\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-eye\"></i>\n </span>\n\n <div class=\"hero-notification__head\">\n <label class=\"hero-notification__composer-label\" for=\"hero-notification-input\">\n <i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i>\n <span>Th\u00F4ng b\u00E1o</span>\n @if (visibleNotifications().length > 0) {\n <span class=\"hero-notification__unread-badge\">{{\n visibleNotifications().length\n }}</span>\n }\n </label>\n <div class=\"hero-notification__head-actions\">\n <button\n type=\"button\"\n class=\"hero-notification__mark-all\"\n (click)=\"openAcknowledgeAllConfirmDialog()\"\n [disabled]=\"notificationSaving() || visibleNotifications().length === 0\"\n title=\"\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc\"\n >\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n \u0110\u00E3 \u0111\u1ECDc t\u1EA5t c\u1EA3\n </button>\n <button\n type=\"button\"\n class=\"hero-notification__add\"\n (click)=\"openNotificationComposerDialog()\"\n aria-label=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n title=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n @if (displayedNotifications().length > 0) {\n <ul class=\"hero-notification__list\">\n @for (notice of displayedNotifications(); track notice) {\n <li class=\"hero-notification__item\">\n <div class=\"hero-notification__avatar\" aria-hidden=\"true\">\n {{ notice.user | slice: 0 : 2 | uppercase }}\n </div>\n <div class=\"hero-notification__body\">\n <div class=\"hero-notification__body-head\">\n <span class=\"hero-notification__author\">{{ notice.user }}</span>\n </div>\n <p class=\"hero-notification__content\">{{ notice.content }}</p>\n @if (notice.createdAt) {\n <span class=\"hero-notification__created\">{{\n formatNotificationCreatedAt(notice.createdAt)\n }}</span>\n }\n </div>\n <div class=\"hero-notification__item-actions\">\n <button\n type=\"button\"\n class=\"hero-notification__ack-top\"\n (click)=\"acknowledgeNotification(notice)\"\n [disabled]=\"notificationSaving()\"\n aria-label=\"\u0110\u00E3 \u0111\u1ECDc th\u00F4ng b\u00E1o\"\n title=\"\u0110\u00E3 \u0111\u1ECDc\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n @if (canDeleteNotification(notice)) {\n <button\n type=\"button\"\n class=\"hero-notification__delete\"\n (click)=\"deleteNotification(notice)\"\n [disabled]=\"notificationSaving()\"\n aria-label=\"X\u00F3a th\u00F4ng b\u00E1o\"\n title=\"X\u00F3a th\u00F4ng b\u00E1o\"\n >\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </li>\n }\n </ul>\n } @else {\n <div class=\"hero-notification__empty\">\n <i class=\"pi pi-bell hero-notification__empty-icon\" aria-hidden=\"true\"></i>\n <span class=\"hero-notification__empty-title\">Kh\u00F4ng c\u00F3 th\u00F4ng b\u00E1o m\u1EDBi</span>\n <span class=\"hero-notification__empty-sub\"\n >M\u1ECDi th\u1EE9 \u0111\u1EC1u \u1ED5n. Th\u00F4ng b\u00E1o m\u1EDBi s\u1EBD xu\u1EA5t hi\u1EC7n \u1EDF \u0111\u00E2y.</span\n >\n </div>\n }\n\n @if (hiddenNotificationCount() > 0) {\n <button\n type=\"button\"\n class=\"hero-notification__more\"\n (click)=\"openNotificationListDialog()\"\n >\n Xem th\u00EAm {{ hiddenNotificationCount() }} th\u00F4ng b\u00E1o \u2192\n </button>\n }\n </section>\n\n </div>\n } <!-- end @else no-profile -->\n </header>\n\n <!-- \u2550\u2550 NOTIFICATION DIALOGS \u2014 rendered outside <header> to avoid overflow/stacking-context clipping \u2550\u2550 -->\n @if (notificationComposerDialogOpen()) {\n <div\n class=\"dialog-overlay dialog-overlay--front\"\n (click)=\"closeNotificationComposerDialog()\"\n >\n <div\n class=\"dialog hero-notification-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\" aria-hidden=\"true\"><i class=\"pi pi-bell\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\" aria-hidden=\"true\"><i class=\"pi pi-megaphone\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--send\" aria-hidden=\"true\"><i class=\"pi pi-send\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--star\" aria-hidden=\"true\"><i class=\"pi pi-star\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\" aria-hidden=\"true\"><i class=\"pi pi-comments\"></i></span>\n\n <div class=\"dialog-head hero-notification-dialog__head\">\n <div class=\"hero-notification-dialog__title-group\">\n <div class=\"hero-notification-dialog__icon-wrap\">\n <i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i>\n </div>\n <div>\n <h2 class=\"hero-notification-dialog__title\">T\u1EA1o th\u00F4ng b\u00E1o</h2>\n <p class=\"hero-notification-dialog__subtitle\">Th\u00F4ng b\u00E1o s\u1EBD hi\u1EC3n th\u1ECB cho to\u00E0n b\u1ED9 th\u00E0nh vi\u00EAn</p>\n </div>\n </div>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeNotificationComposerDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <div class=\"hero-notification__composer-panel\">\n <div class=\"hero-notification__composer-row\">\n <div class=\"hero-notification__input-wrap\">\n <textarea\n id=\"hero-notification-input\"\n class=\"hero-notification__input\"\n [value]=\"notificationDraft()\"\n (input)=\"updateNotificationDraft($any($event.target).value)\"\n [disabled]=\"notificationSaving()\"\n maxlength=\"300\"\n placeholder=\"Nh\u1EADp n\u1ED9i dung th\u00F4ng b\u00E1o cho m\u1ECDi ng\u01B0\u1EDDi...\"\n aria-label=\"N\u1ED9i dung th\u00F4ng b\u00E1o\"\n ></textarea>\n <div class=\"hero-notification__char-ring\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 36 36\">\n <circle class=\"hero-notification__char-ring-track\" cx=\"18\" cy=\"18\" r=\"15\" />\n <circle class=\"hero-notification__char-ring-fill\" cx=\"18\" cy=\"18\" r=\"15\"\n [style.stroke-dashoffset]=\"94 - (notificationDraft().trim().length / 300) * 94\" />\n </svg>\n <span class=\"hero-notification__char-count\">{{ notificationDraft().trim().length }}</span>\n </div>\n </div>\n </div>\n <div class=\"hero-notification__composer-actions\">\n <button type=\"button\" class=\"btn ghost hero-notification__cancel\"\n (click)=\"closeNotificationComposerDialog()\" [disabled]=\"notificationSaving()\">H\u1EE7y</button>\n <button type=\"button\" class=\"btn hero-notification__send\"\n (click)=\"createNotification()\"\n [disabled]=\"notificationSaving() || !notificationDraft().trim()\">\n <i class=\"pi pi-send\"></i>\n <span>G\u1EEDi th\u00F4ng b\u00E1o</span>\n </button>\n </div>\n </div>\n @if (notificationError()) {\n <p class=\"hero-notification__error\">{{ notificationError() }}</p>\n }\n </div>\n </div>\n }\n\n @if (notificationListDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeNotificationListDialog()\">\n <div class=\"dialog hero-notification-list-dialog\" role=\"dialog\" aria-modal=\"true\"\n aria-label=\"Danh s\u00E1ch th\u00F4ng b\u00E1o\" (click)=\"$event.stopPropagation()\">\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\" aria-hidden=\"true\"><i class=\"pi pi-bell\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\" aria-hidden=\"true\"><i class=\"pi pi-megaphone\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\" aria-hidden=\"true\"><i class=\"pi pi-comments\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--star\" aria-hidden=\"true\"><i class=\"pi pi-star\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--check\" aria-hidden=\"true\"><i class=\"pi pi-check-circle\"></i></span>\n\n <div class=\"dialog-head hero-notification-list-dialog__head\">\n <div class=\"hero-notification-dialog__title-group\">\n <div class=\"hero-notification-dialog__icon-wrap\"><i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i></div>\n <div>\n <h2 class=\"hero-notification-list-dialog__title\">To\u00E0n b\u1ED9 th\u00F4ng b\u00E1o</h2>\n <p class=\"hero-notification-dialog__subtitle\">{{ visibleNotifications().length }} th\u00F4ng b\u00E1o</p>\n </div>\n </div>\n <div class=\"hero-notification-list-dialog__head-actions\">\n <button type=\"button\" class=\"hero-notification__mark-all\"\n (click)=\"openAcknowledgeAllConfirmDialog()\"\n [disabled]=\"notificationSaving() || visibleNotifications().length === 0\"\n title=\"\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc\">\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i> \u0110\u00E3 \u0111\u1ECDc t\u1EA5t c\u1EA3\n </button>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeNotificationListDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"hero-notification-list-dialog__body\">\n @if (visibleNotifications().length > 0) {\n <ul class=\"hero-notification__list\">\n @for (notice of visibleNotifications(); track notice) {\n <li class=\"hero-notification__item\">\n <div class=\"hero-notification__avatar\" aria-hidden=\"true\">{{ notice.user | slice: 0 : 2 | uppercase }}</div>\n <div class=\"hero-notification__body\">\n <div class=\"hero-notification__body-head\">\n <span class=\"hero-notification__author\">{{ notice.user }}</span>\n </div>\n <p class=\"hero-notification__content\">{{ notice.content }}</p>\n @if (notice.createdAt) {\n <span class=\"hero-notification__created\">{{ formatNotificationCreatedAt(notice.createdAt) }}</span>\n }\n </div>\n <div class=\"hero-notification__item-actions\">\n <button type=\"button\" class=\"hero-notification__ack-top\"\n (click)=\"acknowledgeNotification(notice)\" [disabled]=\"notificationSaving()\"\n aria-label=\"\u0110\u00E3 \u0111\u1ECDc th\u00F4ng b\u00E1o\" title=\"\u0110\u00E3 \u0111\u1ECDc\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n @if (canDeleteNotification(notice)) {\n <button type=\"button\" class=\"hero-notification__delete\"\n (click)=\"deleteNotification(notice)\" [disabled]=\"notificationSaving()\"\n aria-label=\"X\u00F3a th\u00F4ng b\u00E1o\" title=\"X\u00F3a th\u00F4ng b\u00E1o\">\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </li>\n }\n </ul>\n } @else {\n <div class=\"hero-notification__empty\">\n <i class=\"pi pi-bell hero-notification__empty-icon\" aria-hidden=\"true\"></i>\n <span class=\"hero-notification__empty-title\">Kh\u00F4ng c\u00F3 th\u00F4ng b\u00E1o m\u1EDBi</span>\n <span class=\"hero-notification__empty-sub\">M\u1ECDi th\u1EE9 \u0111\u1EC1u \u1ED5n. Th\u00F4ng b\u00E1o m\u1EDBi s\u1EBD xu\u1EA5t hi\u1EC7n \u1EDF \u0111\u00E2y.</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n @if (acknowledgeAllConfirmDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeAcknowledgeAllConfirmDialog()\">\n <div class=\"dialog ack-all-confirm-dialog\" role=\"alertdialog\" aria-modal=\"true\"\n aria-labelledby=\"ack-all-confirm-title\" (click)=\"$event.stopPropagation()\">\n <div class=\"ack-all-confirm-dialog__icon-wrap\" aria-hidden=\"true\"><i class=\"pi pi-check-circle\"></i></div>\n <h2 id=\"ack-all-confirm-title\" class=\"ack-all-confirm-dialog__title\">\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc?</h2>\n <p class=\"ack-all-confirm-dialog__desc\">\n T\u1EA5t c\u1EA3 {{ visibleNotifications().length }} th\u00F4ng b\u00E1o s\u1EBD \u0111\u01B0\u1EE3c \u0111\u00E1nh d\u1EA5u \u0111\u00E3 \u0111\u1ECDc v\u00E0 \u1EA9n kh\u1ECFi danh s\u00E1ch.\n </p>\n <div class=\"ack-all-confirm-dialog__actions\">\n <button type=\"button\" class=\"btn ghost\" (click)=\"closeAcknowledgeAllConfirmDialog()\" [disabled]=\"notificationSaving()\">H\u1EE7y</button>\n <button type=\"button\" class=\"btn ack-all-confirm-dialog__confirm-btn\"\n (click)=\"confirmAcknowledgeAll()\" [disabled]=\"notificationSaving()\">\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i> X\u00E1c nh\u1EADn\n </button>\n </div>\n </div>\n </div>\n }\n\n <main\n class=\"content\"\n [class.is-documents]=\"bottomTab() === 'documents'\"\n [class.is-weight]=\"bottomTab() === 'weight'\"\n [class.is-schedule]=\"bottomTab() === 'schedule'\"\n [class.is-mom]=\"bottomTab() === 'mom'\"\n [class.is-medical]=\"bottomTab() === 'medical'\"\n >\n <!--\n ============ TAB PANES ============\n D\u00F9ng `[hidden]` thay v\u00EC `*ngIf` \u0111\u1EC3 c\u00E1c tab c\u00F9ng gi\u1EEF tr\u1EA1ng th\u00E1i khi\n user qua l\u1EA1i: scroll position, search query \u0111ang g\u00F5, viewMode, folder\n \u0111ang \u0111\u1EE9ng, file \u0111ang ch\u1ECDn, draft \u0111ang nh\u1EADp\u2026 \u0111\u1EC1u kh\u00F4ng b\u1ECB reset. H\u1EC7\n qu\u1EA3: `<app-documents>` \u0111\u01B0\u1EE3c mount 1 l\u1EA7n \u1EDF app load \u2014 `loadEntries()`\n ch\u1EA1y 1 l\u1EA7n, c\u00E1c l\u1EA7n switch tab k\u1EBF ti\u1EBFp kh\u00F4ng g\u1ECDi API th\u00EAm.\n -->\n <!-- ============ TAB: DOCUMENTS \u2014 \u0111\u00E3 chuy\u1EC3n sang subroute (m\u1EDF t\u1EEB Settings menu) ============ -->\n\n <!-- ============ TAB: WEIGHT ============ -->\n <div class=\"tab-pane tab-pane--weight\" [hidden]=\"bottomTab() !== 'weight'\">\n <app-weight\n [user]=\"user()\"\n [birthDate]=\"profile()?.birthDate\"\n [gender]=\"profile()?.gender\"\n [babyName]=\"profile()?.babyName\"\n ></app-weight>\n </div>\n\n <!-- ============ TAB: L\u1ECACH \u2014 Google Sheet tab \"Event\" ============ -->\n <div class=\"tab-pane tab-pane--schedule\" [hidden]=\"bottomTab() !== 'schedule'\">\n <app-feeding-schedule [user]=\"user()\"></app-feeding-schedule>\n </div>\n\n <!-- ============ TAB: TI\u1EC0N S\u1EEC Y T\u1EBE \u2014 Medical history V2 ============ -->\n <div class=\"tab-pane tab-pane--medical\" [hidden]=\"bottomTab() !== 'medical'\">\n <app-medical-history\n [user]=\"user()\"\n (openExplorerFile)=\"openMedicalAttachmentInDocuments($event)\"\n ></app-medical-history>\n </div>\n\n <!-- ============ TAB: M\u1EB8 \u2014 \u0111\u00E3 chuy\u1EC3n sang subroute (m\u1EDF t\u1EEB Settings menu) ============ -->\n\n <!-- ============ TAB: FEEDING ============ -->\n <div class=\"tab-pane tab-pane--feeding\" [hidden]=\"bottomTab() !== 'feeding'\">\n <app-feeding-profile\n [user]=\"user()\"\n [profile]=\"profile()\"\n [draft]=\"draft()\"\n [editing]=\"editing()\"\n [maxBirthDate]=\"maxBirthDate\"\n (save)=\"save()\"\n (cancelEdit)=\"cancelEdit()\"\n (startEdit)=\"startEdit()\"\n (clearProfile)=\"clearProfile()\"\n (draftNameChange)=\"updateDraftName($event)\"\n (draftBirthChange)=\"updateDraftBirth($event)\"\n (draftGenderChange)=\"setDraftGender($event)\"\n />\n\n @if (profile() && !editing() && ageBreakdown()) {\n <app-feeding-daily\n [logs]=\"logs()\"\n [feedingSettings]=\"feedingSettings()\"\n [now]=\"now()\"\n [nutritionTarget]=\"nutritionTarget()\"\n [user]=\"user()\"\n [syncMessage]=\"syncMessage()\"\n [syncError]=\"syncError()\"\n [logDialogOpen]=\"logDialogOpen()\"\n [loadingLogs]=\"loadingLogs()\"\n [refreshToken]=\"dailyRefreshToken()\"\n (logsChanged)=\"onFeedingLogsChanged()\"\n (bottlePrepChange)=\"bottlePrep.set($event)\"\n (editLog)=\"feedingDialogs.openEditDialog($event)\"\n (historyOpen)=\"feedingDialogs.openHistoryDialog($event.filter, $event.dateStr)\"\n (feedRowClick)=\"feedingDialogs.onFeedRowClick($event)\"\n >\n <app-feeding-charts\n data-feeding-charts\n [logs]=\"logs()\"\n [now]=\"now()\"\n [nutritionTarget]=\"nutritionTarget()\"\n />\n </app-feeding-daily>\n <app-feeding-nutrition\n [nutritionTarget]=\"nutritionTarget()\"\n [todayStats]=\"todayStats()\"\n [now]=\"now()\"\n [latestWeightKg]=\"latestWeightKgFromSheet()\"\n [editing]=\"editing()\"\n (goToWeight)=\"setBottomTab('weight')\"\n />\n }\n\n <!-- ============ FAB \u00AB Ghi c\u1EEF b\u00FA \u00BB c\u0169 \u0111\u00E3 \u0111\u01B0\u1EE3c thay b\u1EB1ng FAB gi\u1EEFa bottom-nav ============ -->\n </div>\n <!-- /.tab-pane--feeding -->\n </main>\n </div>\n <!-- /.feeding-page -->\n\n <!-- ============ BOTTOM NAVIGATION (C\u1EEF b\u00FA \u00B7 Th\u1EC3 tr\u1EA1ng \u00B7 + \u00B7 L\u1ECBch \u00B7 Y t\u1EBF) ============ -->\n <nav\n class=\"bottom-nav\"\n role=\"tablist\"\n aria-label=\"\u0110i\u1EC1u h\u01B0\u1EDBng ch\u00EDnh\"\n >\n <div class=\"bn-side bn-side--left\">\n @for (tab of navLeftTabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"bn-item\"\n role=\"tab\"\n [attr.aria-selected]=\"bottomTab() === tab.id\"\n [class.active]=\"bottomTab() === tab.id\"\n (click)=\"setBottomTab(tab.id)\"\n >\n <span class=\"bn-icon-wrap\">\n <i class=\"pi {{ tab.icon }} bn-icon\" aria-hidden=\"true\"></i>\n </span>\n <span class=\"bn-label\">{{ tab.label }}</span>\n </button>\n }\n </div>\n\n <button\n type=\"button\"\n class=\"bn-fab\"\n (click)=\"feedingDialogs.openLogDialog()\"\n [disabled]=\"!profile() || editing()\"\n [title]=\"(!profile() || editing()) ? 'Ch\u1ECDn b\u00E9 tr\u01B0\u1EDBc khi ghi c\u1EEF b\u00FA' : 'Ghi nh\u1EADn c\u1EEF b\u00FA m\u1EDBi'\"\n aria-label=\"Ghi nh\u1EADn c\u1EEF b\u00FA\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n\n <div class=\"bn-side bn-side--right\">\n @for (tab of navRightTabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"bn-item\"\n role=\"tab\"\n [attr.aria-selected]=\"bottomTab() === tab.id\"\n [class.active]=\"bottomTab() === tab.id\"\n (click)=\"setBottomTab(tab.id)\"\n >\n <span class=\"bn-icon-wrap\">\n <i class=\"pi {{ tab.icon }} bn-icon\" aria-hidden=\"true\"></i>\n </span>\n <span class=\"bn-label\">{{ tab.label }}</span>\n </button>\n }\n </div>\n </nav>\n\n <!-- ============ NOTIFICATION SUBROUTE (full-screen) ============ -->\n @if (notifRouteOpen()) {\n <app-notification-list\n [notifications]=\"allNotifications()\"\n [currentUser]=\"user()\"\n [saving]=\"notificationSaving()\"\n (back)=\"closeNotificationRoute()\"\n (acknowledge)=\"acknowledgeNotification($event)\"\n (acknowledgeAll)=\"openAcknowledgeAllConfirmDialog()\"\n (delete)=\"deleteNotification($event)\"\n (openComposer)=\"openNotificationComposerDialog()\"\n />\n }\n\n <!-- ============ SETTINGS FLOAT MENU (full-screen) ============ -->\n @if (settingsMenuOpen()) {\n <app-settings-menu\n [appName]=\"appInfo.name\"\n [appVersion]=\"appInfo.version\"\n [showDocuments]=\"explorerEnabled\"\n [unreadCount]=\"visibleNotifications().length\"\n (close)=\"closeSettingsMenu()\"\n (select)=\"onSettingsMenuSelect($event)\"\n />\n }\n\n <!-- ============ M\u1EB8 SUBROUTE (full-screen) ============ -->\n @if (momRouteOpen()) {\n <app-subroute-shell\n title=\"M\u1EB9\"\n (back)=\"closeMomRoute()\"\n >\n <app-feeding-mom\n [profile]=\"profile()\"\n [editing]=\"editing()\"\n (goToFeeding)=\"closeMomRoute(); setBottomTab('feeding')\"\n ></app-feeding-mom>\n </app-subroute-shell>\n }\n\n <!-- ============ T\u00C0I LI\u1EC6U SUBROUTE (full-screen) ============ -->\n @if (documentsRouteOpen()) {\n <app-subroute-shell\n title=\"T\u00E0i li\u1EC7u\"\n (back)=\"closeDocumentsRoute()\"\n >\n <app-documents></app-documents>\n </app-subroute-shell>\n }\n\n <!-- About -->\n @if (aboutDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeAboutDialog()\">\n <div\n class=\"dialog about-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"feeding-about-title\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"dialog-head about-dialog__head\">\n <h2 id=\"feeding-about-title\" class=\"about-dialog__title\">\n <i class=\"pi pi-info-circle\" aria-hidden=\"true\"></i>\n About\n </h2>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeAboutDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <dl class=\"about-dialog__meta\">\n <div class=\"about-dialog__row\">\n <dt>\u1EE8ng d\u1EE5ng</dt>\n <dd>{{ appInfo.name }}</dd>\n </div>\n <div class=\"about-dialog__row\">\n <dt>Phi\u00EAn b\u1EA3n</dt>\n <dd>\n <code>{{ appInfo.version }}</code>\n </dd>\n </div>\n </dl>\n <div class=\"dialog-actions\">\n <button type=\"button\" class=\"btn primary\" (click)=\"closeAboutDialog()\">\u0110\u00F3ng</button>\n </div>\n </div>\n </div>\n }\n\n <!-- Nh\u1EAFc s\u1EF1 ki\u1EC7n l\u1ECBch (sheet Event + Settings) -->\n @if (eventReminderDialogOpen() && scheduleReminderEvents().length > 0) {\n <div\n class=\"dialog-overlay dialog-overlay--front dialog-overlay--event-reminder\"\n (click)=\"closeEventReminderDialog()\"\n >\n <div\n class=\"dialog event-reminder-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"dialog-head event-reminder-dialog__head\">\n <h2 class=\"event-reminder-dialog__title\">\n <i class=\"pi pi-bell\" aria-hidden=\"true\"></i>\n B\u1EA1n c\u00F3 l\u1ECBch s\u1EAFp t\u1EDBi\n </h2>\n <button\n type=\"button\"\n class=\"dialog-close\"\n (click)=\"closeEventReminderDialog()\"\n aria-label=\"\u0110\u00F3ng\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <ul class=\"event-reminder-list\">\n @for (ev of scheduleReminderEvents(); track ev) {\n <li>\n <article class=\"event-reminder-card\">\n <h3 class=\"event-reminder-card__title\">{{ ev.title }}</h3>\n <p class=\"event-reminder-card__datetime\">\n <span class=\"event-reminder-card__date\">{{ formatReminderEventWhen(ev) }}</span>\n <span class=\"event-reminder-card__sep\" aria-hidden=\"true\"> \u2013 </span>\n <span class=\"event-reminder-card__hour\">{{\n formatReminderEventTime(ev.time)\n }}</span>\n </p>\n @if (ev.place) {\n <p class=\"event-reminder-card__place\">\n <i class=\"pi pi-map-marker\" aria-hidden=\"true\"></i>\n <span>{{ ev.place }}</span>\n </p>\n }\n @if (ev.note) {\n <div class=\"event-reminder-card__content-wrap\">\n <span class=\"event-reminder-card__content-label\">N\u1ED9i dung</span>\n <p class=\"event-reminder-card__content\">{{ ev.note }}</p>\n </div>\n }\n </article>\n </li>\n }\n </ul>\n <div class=\"dialog-actions event-reminder-actions\">\n <button\n type=\"button\"\n class=\"event-reminder-actions__link\"\n (click)=\"acknowledgeAllEventReminders()\"\n >\n Kh\u00F4ng nh\u1EAFc l\u1EA1i\n </button>\n <button\n type=\"button\"\n class=\"btn primary event-reminder-actions__primary\"\n (click)=\"skipEventReminderSession()\"\n >\n \u0110\u00E3 hi\u1EC3u\n </button>\n </div>\n </div>\n </div>\n }\n\n <app-feeding-dialogs\n #feedingDialogs\n [logs]=\"logs()\"\n [user]=\"user()\"\n [now]=\"now()\"\n [bottlePrep]=\"bottlePrep()\"\n [feedingSettings]=\"feedingSettings()\"\n [prediction]=\"prediction()\"\n [todayStats]=\"todayStats()\"\n [yesterdayStats]=\"yesterdayStats()\"\n [todayLogs]=\"todayLogs()\"\n [yesterdayLogs]=\"yesterdayLogs()\"\n [maxBirthDate]=\"maxBirthDate\"\n [syncError]=\"syncError()\"\n [syncMessage]=\"syncMessage()\"\n (logsChanged)=\"onFeedingLogsChanged()\"\n (settingsChanged)=\"onFeedingSettingsChanged($event)\"\n (syncErrorChange)=\"syncError.set($event)\"\n (syncMessageChange)=\"syncMessage.set($event)\"\n (logDialogOpenChange)=\"logDialogOpen.set($event)\"\n (bottlePrepClearRequested)=\"clearBottlePrep()\"\n />\n</div>\n<!-- /.feeding-root -->\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;position:absolute;inset:0;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;--bg: #f6f7fb;--surface: #ffffff;--border: #e6e8ef;--border-strong: #d1d5db;--primary: #5b6cff;--primary-2: #4c5cf0;--primary-soft: #eef0ff;--accent: #ff5c8a;--accent-soft: #ffe7ef;--mint: #10b981;--mint-soft: #d1fae5;--amber: #f59e0b;--amber-soft: #fef3c7;--rose: #ef4444;--rose-soft: #fee2e2;--text: #0f172a;--muted: #64748b;--muted-2: #94a3b8}.feeding-root{flex:1;min-height:0;width:100%;display:flex;flex-direction:column;position:relative}.feeding-root .bp-prep-user{font-weight:800;color:#0369a1;background:#0ea5e933;padding:0 5px;margin-right:2px;border-radius:5px;white-space:nowrap;transition:color .2s,background .2s}.feeding-root .bp-prep-time{font-weight:800;font-variant-numeric:tabular-nums;color:#0284c7;background:linear-gradient(180deg,#f0f9ff,#e0f2fe);border:1px solid rgba(14,165,233,.35);padding:1px 7px;margin-left:2px;border-radius:6px;white-space:nowrap;box-shadow:0 1px #ffffffa6 inset;transition:color .2s,background .2s,border-color .2s}.feeding-page{position:relative;flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;color:var(--text);padding-bottom:calc(170px + env(safe-area-inset-bottom,0px))}.backdrop{position:fixed;inset:0;background:var(--bg);z-index:-1}.hero-notif-wrap{padding:0 16px 8px}.hero{padding:0;background:#fffffff5;border-bottom:1px solid rgba(226,232,240,.9)}@media(max-width:640px){.hero{padding-top:calc(26px + env(safe-area-inset-top,0px));padding-bottom:10px}}.hero-inner{max-width:1100px;margin:0 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:14px 18px}.hero-brand{min-width:0}.hero-title-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0;width:100%}.hero-title{display:flex;align-items:center;gap:12px;min-width:0;flex:1}.hero-title .emoji{font-size:36px;line-height:1;flex-shrink:0;filter:drop-shadow(0 2px 4px rgba(15,23,42,.08))}@media(max-width:640px){.hero-title .emoji{font-size:32px}}.hero-title .hero-text{min-width:0}.hero-title h1{margin:0;font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.02em;line-height:1.2}@media(max-width:640px){.hero-title h1{font-size:17px}}.hero-title .hero-userline{margin:5px 0 0;display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px 6px;font-size:12.5px;color:var(--muted)}.hero-title .hero-userline i{font-size:12px;color:var(--primary);opacity:.9}.hero-title .hero-userline strong{color:var(--primary);font-weight:700;letter-spacing:.01em}.hero-title .hero-userline .hero-last-update{font-size:11px;color:#94a3b8;font-weight:400}.hero--profile-merged{background:var(--primary-soft);padding-bottom:10px;margin-bottom:8px}.hero-title--merged{align-items:flex-start}.hero-title--merged .emoji{font-size:30px}.hero-title--merged h1{font-size:18px;line-height:1.15}.hero-merged-head{display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px;min-width:0;row-gap:6px}.hero-age-chip{font-size:10.5px;font-weight:800;letter-spacing:.04em;text-transform:lowercase;color:var(--primary);background:var(--primary-soft);padding:3px 9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--primary) 18%,transparent);white-space:nowrap}.hero-merged-stat{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:700;color:var(--muted);background:#94a3b824;border:1px solid rgba(148,163,184,.28);white-space:nowrap;line-height:1.25}.hero-merged-stat>i{font-size:10px;opacity:.88;color:var(--muted-2)}.hero-merged-stat--weight>i{color:var(--accent);opacity:1}.hero-merged-meta{margin:5px 0 0;display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;font-size:11.5px;line-height:1.45;color:var(--muted)}.hero-merged-meta .dot{color:var(--muted-2);font-weight:700;-webkit-user-select:none;user-select:none}.hero-merged-meta i{font-size:10px;margin-right:3px;color:var(--muted-2);opacity:.95}.hero-merged-meta strong{color:var(--primary);font-weight:700}.hero-merged-sync{color:#94a3b8;font-weight:400;font-size:11px}.hero-actions--merged{flex-shrink:0}.hero-profile-menu{position:relative;flex:0 0 auto;list-style:none}.hero-profile-menu__trigger{list-style:none}.hero-profile-menu__trigger::-webkit-details-marker{display:none}.hero-profile-menu__trigger::marker{content:\"\"}.hero-profile-menu__panel{position:absolute;top:calc(100% + 6px);right:0;z-index:30;min-width:180px;padding:6px;border-radius:12px;border:1px solid var(--border);background:#fff;box-shadow:0 8px 24px -8px #0f172a2e}.hero-profile-menu__item{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border:0;border-radius:8px;background:transparent;font:inherit;font-size:13px;font-weight:600;color:var(--text);text-align:left;cursor:pointer;transition:background .12s ease,color .12s ease}.hero-profile-menu__item i{font-size:14px;color:var(--muted-2);width:1.1em;text-align:center}.hero-profile-menu__item:hover:not(:disabled){background:var(--primary-soft, #eef0ff);color:var(--primary)}.hero-profile-menu__item:hover:not(:disabled) i{color:var(--primary)}.hero-profile-menu__item--danger:hover:not(:disabled){color:var(--rose);background:var(--rose-soft)}.hero-profile-menu__item--danger:hover:not(:disabled) i{color:var(--rose)}.about-dialog{max-width:360px}.about-dialog__head{margin-bottom:8px}.about-dialog__title{display:flex;align-items:center;gap:8px;margin:0;font-size:18px;font-weight:700}.about-dialog__title i{color:var(--primary)}.about-dialog__meta{margin:0 0 16px;padding:0}.about-dialog__row{display:grid;grid-template-columns:96px 1fr;gap:8px 12px;padding:10px 0;border-bottom:1px solid var(--border)}.about-dialog__row:last-child{border-bottom:0}.about-dialog__row dt{margin:0;font-size:13px;font-weight:600;color:var(--muted-2)}.about-dialog__row dd{margin:0;font-size:14px;font-weight:600;color:var(--text)}.about-dialog__row dd code{font-size:13px;font-weight:600;padding:2px 8px;border-radius:6px;background:var(--primary-soft, #eef0ff);color:var(--primary)}@media(max-width:640px){.hero-title--merged .emoji{font-size:26px}.hero-merged-meta{font-size:11px}.hero-merged-stat{font-size:10.5px;padding:2px 7px}}.hero-datetime{display:flex;flex-wrap:wrap;align-items:center;flex-shrink:0}.hero-datetime-strip{display:inline-flex;align-items:stretch;flex-wrap:nowrap;max-width:100%;min-height:34px;border:1px solid var(--border);border-radius:8px;background:linear-gradient(180deg,#fff,#f1f5f9);box-shadow:0 1px 1px #0f172a0d}.hero-datetime-strip__block{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;min-width:0}.hero-datetime-strip__block>.pi{font-size:12px;color:var(--primary);opacity:.82;flex-shrink:0}.hero-datetime-strip__block--date{flex-wrap:wrap;row-gap:0}.hero-datetime-strip__wd{font-size:10px;font-weight:700;color:var(--muted);text-transform:capitalize;letter-spacing:.02em;line-height:1.15;max-width:88px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hero-datetime-strip__date{font-size:12px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--text);letter-spacing:.02em;white-space:nowrap}.hero-datetime-strip__divider{align-self:stretch;width:1px;margin:5px 0;background:#94a3b866;flex-shrink:0}.hero-datetime-strip__clock{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:.04em;color:var(--primary);line-height:1;white-space:nowrap}.hero-datetime-strip__block--time{padding-right:10px}.hero-datetime-strip__block--time>.pi{font-size:11px}@media(max-width:520px){.hero-inner{flex-direction:column;align-items:stretch}.hero-datetime{width:100%;justify-content:flex-start}.hero-datetime-strip{flex:1 1 auto;width:100%;justify-content:space-between}.hero-notification__composer-row{flex-direction:column;align-items:stretch}.hero-notification__send,.hero-notification__cancel{width:100%;justify-content:center}}.hero-notification__bg-icon{position:absolute;pointer-events:none;color:var(--primary);opacity:.13;line-height:1}.hero-notification__bg-icon i{display:block}.hero-notification__bg-icon--bell{top:8%;left:6%;font-size:28px;transform:rotate(-18deg)}.hero-notification__bg-icon--megaphone{top:10%;right:8%;font-size:24px;transform:rotate(12deg)}.hero-notification__bg-icon--comments{bottom:14%;right:10%;font-size:22px;transform:rotate(-8deg)}.hero-notification__bg-icon--send{bottom:10%;left:50%;font-size:20px;transform:rotate(-22deg)}.hero-notification__bg-icon--star{bottom:16%;left:4%;font-size:18px;transform:rotate(20deg)}.hero-notification__bg-icon--bolt{top:46%;right:2%;font-size:20px;transform:rotate(-5deg)}.hero-notification__bg-icon--heart{top:38%;left:14%;font-size:17px;transform:rotate(15deg)}.hero-notification__bg-icon--info{top:4%;left:50%;font-size:18px;transform:rotate(0)}.hero-notification__bg-icon--check{bottom:24%;left:35%;font-size:17px;transform:rotate(8deg)}.hero-notification__bg-icon--eye{top:14%;left:28%;font-size:18px;transform:rotate(-10deg)}.hero-notification{flex:1 1 100%;display:flex;flex-direction:column;gap:10px;margin-top:2px;padding:10px 12px;border:1px solid rgba(148,163,184,.28);border-radius:14px;background:#fff;position:relative;overflow:hidden}.hero-notification__head{display:flex;align-items:center;justify-content:space-between;gap:10px;position:relative}.hero-notification__head-actions{display:inline-flex;align-items:center;gap:6px}.hero-notification__composer-label{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--muted)}.hero-notification__composer-label i{color:var(--primary);font-size:12px}.hero-notification__unread-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:var(--primary);color:#fff;font-size:10px;font-weight:700;line-height:1}.hero-notification__add{width:28px;height:28px;border:1px solid rgba(var(--primary-rgb, 76, 92, 240),.25);border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.1);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0}.hero-notification__add i{font-size:11px}.hero-notification__add:hover:not(:disabled){background:var(--primary);border-color:var(--primary);color:#fff}.hero-notification__mark-all{height:26px;border:none;border-radius:0;background:transparent;color:var(--primary);font-size:11px;font-weight:600;padding:0;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:4px}.hero-notification__mark-all i{font-size:10px}.hero-notification__mark-all:hover:not(:disabled){opacity:.75}.hero-notification__mark-all:disabled{color:var(--muted-2);cursor:default}.hero-notification__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px;position:relative}.hero-notification__item{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:10px;background:#f8fafc;border:1px solid #e2e8f0;position:relative;transition:border-color .18s ease,transform .18s ease}@media(hover:hover){.hero-notification__item:hover{border-color:#c7d2fe;transform:translateY(-1px)}}.hero-notification__avatar{width:34px;height:34px;border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.12);border:1.5px solid rgba(var(--primary-rgb, 76, 92, 240),.22);color:var(--primary);font-size:11px;font-weight:700;letter-spacing:.5px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.hero-notification__body{flex:1;min-width:0;padding-right:52px}.hero-notification__body-head{display:flex;align-items:center;gap:6px;margin-bottom:3px}.hero-notification__author{font-size:12px;font-weight:700;color:var(--text)}.hero-notification__content{margin:0;font-size:13.5px;line-height:1.5;color:var(--text);white-space:pre-wrap;word-break:break-word}.hero-notification__created{display:block;margin-top:4px;font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums}.hero-notification__item-actions{position:absolute;top:7px;right:8px;display:inline-flex;align-items:center;gap:4px}.hero-notification__ack-top{width:24px;height:24px;border:none;border-radius:50%;background:#eff6ff;color:#1d4ed8;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s ease,color .15s ease,transform .15s ease}.hero-notification__ack-top i{font-size:10px}.hero-notification__ack-top:active:not(:disabled){transform:scale(.96)}.hero-notification__ack-top:hover:not(:disabled){background:#dbeafe;color:#1e40af}.hero-notification__delete{width:24px;height:24px;border:none;border-radius:50%;background:transparent;color:#94a3b8;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.hero-notification__delete i{font-size:10px}.hero-notification__delete:hover:not(:disabled){background:#fee2e2;color:#b91c1c}.hero-notification__empty{display:flex;flex-direction:column;align-items:center;gap:4px;padding:16px 8px;position:relative}.hero-notification__empty-icon{font-size:28px;color:var(--primary);opacity:.45;margin-bottom:4px}.hero-notification__empty-title{font-size:13px;font-weight:600;color:var(--muted)}.hero-notification__empty-sub{font-size:11px;color:var(--muted-2);text-align:center}.hero-notification__more{align-self:flex-start;border:none;background:transparent;color:var(--primary);font-size:12px;font-weight:700;cursor:pointer;padding:0;font-family:inherit;position:relative}.hero-notification__more:hover{opacity:.75}.hero-notification__composer-row{display:flex;align-items:stretch;gap:8px;min-width:0}.hero-notification__composer-panel{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid #dbe4f3;border-radius:12px;background:#f8fbff}.hero-notification__input-wrap{flex:1;min-width:0;border-radius:11px;border:1.5px solid #cfd8e6;background:#fff;transition:border-color .15s ease;position:relative}.hero-notification__composer-row:focus-within .hero-notification__input-wrap{border-color:var(--primary)}.hero-notification__input{width:100%;min-width:0;min-height:100px;border:0;border-radius:11px;padding:10px 12px 32px;font-size:13px;line-height:1.45;color:var(--text);background:transparent;font-family:inherit;resize:vertical}.hero-notification__input:focus{outline:none}.hero-notification__char-ring{position:absolute;bottom:8px;right:10px;display:flex;align-items:center;gap:4px;pointer-events:none}.hero-notification__char-ring svg{width:22px;height:22px;transform:rotate(-90deg)}.hero-notification__char-ring-track{fill:none;stroke:#e2e8f0;stroke-width:3}.hero-notification__char-ring-fill{fill:none;stroke:var(--primary);stroke-width:3;stroke-dasharray:94 94;stroke-linecap:round;transition:stroke-dashoffset .2s ease}.hero-notification__char-count{font-size:10px;color:var(--muted-2);font-variant-numeric:tabular-nums}.hero-notification__composer-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px}.hero-notification__send,.hero-notification__cancel{height:36px;border-radius:10px;min-width:86px;padding:0 14px;font-size:12px;font-weight:700}.hero-notification__send{background:var(--primary);color:#fff}.hero-notification__send:not(:disabled):hover{background:var(--primary-2)}.hero-notification__cancel{min-width:72px}.hero-notification__error{margin:0;font-size:12px;color:#b91c1c;position:relative}.hero-notification-dialog{max-width:min(520px,100vw - 24px);overflow:hidden}.hero-notification-dialog .hero-notification__composer-row{align-items:stretch;gap:10px}.hero-notification-dialog .hero-notification__input-wrap{min-height:110px}.hero-notification-dialog__head{margin-bottom:14px}.hero-notification-dialog__title-group{display:flex;align-items:flex-start;gap:10px}.hero-notification-dialog__icon-wrap{width:34px;height:34px;border-radius:10px;background:rgba(var(--primary-rgb, 76, 92, 240),.12);border:1px solid rgba(var(--primary-rgb, 76, 92, 240),.22);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.hero-notification-dialog__icon-wrap i{font-size:14px}.hero-notification-dialog__title{margin:0;font-size:15px;font-weight:800;color:var(--text);line-height:1.3}.hero-notification-dialog__subtitle{margin:2px 0 0;font-size:11px;color:var(--muted-2)}.hero-notification-list-dialog{max-width:min(620px,100vw - 24px)}.hero-notification-list-dialog__head{margin-bottom:10px;align-items:flex-start}.hero-notification-list-dialog__head-actions{display:inline-flex;align-items:center;gap:8px;flex-shrink:0}.hero-notification-list-dialog__title{margin:0;font-size:15px;font-weight:800;color:var(--text);line-height:1.3}.hero-notification-list-dialog__body{max-height:min(60vh,480px);overflow-y:auto;padding-right:2px}.ack-all-confirm-dialog{max-width:min(380px,100vw - 24px);text-align:center;padding:28px 24px 24px;display:flex;flex-direction:column;align-items:center;gap:10px;overflow:hidden}.ack-all-confirm-dialog__icon-wrap{width:52px;height:52px;border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.1);border:1.5px solid rgba(var(--primary-rgb, 76, 92, 240),.2);color:var(--primary);display:flex;align-items:center;justify-content:center;margin-bottom:2px}.ack-all-confirm-dialog__icon-wrap i{font-size:22px}.ack-all-confirm-dialog__title{margin:0;font-size:16px;font-weight:800;color:var(--text)}.ack-all-confirm-dialog__desc{margin:0;font-size:13px;color:var(--muted);line-height:1.55;max-width:280px}.ack-all-confirm-dialog__actions{display:flex;gap:10px;margin-top:6px;width:100%;justify-content:center}.ack-all-confirm-dialog__actions .btn{min-width:96px;height:38px;border-radius:10px;font-size:13px;font-weight:700}.ack-all-confirm-dialog__confirm-btn{background:var(--primary);color:#fff;display:inline-flex;align-items:center;gap:6px}.ack-all-confirm-dialog__confirm-btn i{font-size:12px}.ack-all-confirm-dialog__confirm-btn:not(:disabled):hover{background:var(--primary-2)}.hero-actions{display:flex;gap:8px;align-items:center;flex-shrink:0;align-self:center}.content{width:100%}.content .tab-pane[hidden]{display:none!important}.content .tab-pane--feeding{max-width:1100px;margin:0 auto;padding:0 20px}.content .tab-pane--documents{max-width:none;padding:0}.content .tab-pane--weight{max-width:none;padding:0;background:linear-gradient(180deg,color-mix(in srgb,var(--primary, #5b6cff) 5%,var(--surface, #fff)) 0%,var(--surface, #fff) min(36vh,280px),var(--surface, #fff) 100%)}.content .tab-pane--mom{max-width:1100px;margin:0 auto;padding:0 20px calc(24px + env(safe-area-inset-bottom,0px))}.content .tab-pane--medical{max-width:none;padding:0;background:linear-gradient(180deg,color-mix(in srgb,var(--primary, #5b6cff) 7%,var(--surface, #fff)) 0%,var(--surface, #fff) min(42vh,320px),var(--surface, #fff) 100%)}.bottom-nav{--bn-primary: #5b6cff;--bn-primary-rgb: 91, 108, 255;--bn-inactive: #b0b7c3;--bn-height: 62px;position:fixed;left:0;right:0;bottom:0;width:100%;box-sizing:border-box;z-index:90;display:flex;align-items:center;justify-content:space-between;gap:4px;min-height:var(--bn-height);padding:0 4px env(safe-area-inset-bottom,0px);background:#fffffff5;backdrop-filter:blur(24px) saturate(200%);-webkit-backdrop-filter:blur(24px) saturate(200%);border-top:1px solid rgba(0,0,0,.055);box-shadow:0 -4px 24px -4px #0f172a14}.bottom-nav .bn-side{flex:1;display:flex;align-items:center;justify-content:space-around;min-width:0}.bottom-nav .bn-fab{flex-shrink:0;width:56px;height:56px;margin-top:-20px;border-radius:999px;border:3px solid rgba(255,255,255,.96);background:var(--bn-primary);color:#fff;font-size:22px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:transform .15s ease,background .15s ease,opacity .15s ease}.bottom-nav .bn-fab:hover:not(:disabled){background:var(--primary-2, #4c5cf0);transform:translateY(-2px)}.bottom-nav .bn-fab:active:not(:disabled){transform:translateY(0) scale(.94)}.bottom-nav .bn-fab:disabled{background:var(--bn-inactive);cursor:not-allowed;opacity:.7}.bottom-nav .bn-item{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;height:var(--bn-height);padding:0 2px;background:transparent;border:none;color:var(--bn-inactive);cursor:pointer;font-family:inherit;-webkit-tap-highlight-color:transparent;transition:color .22s ease}.bottom-nav .bn-item .bn-icon-wrap{display:flex;align-items:center;justify-content:center;width:32px;height:30px;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}.bottom-nav .bn-item .bn-icon{font-size:21px;line-height:1;transition:filter .22s ease;display:block}.bottom-nav .bn-item .bn-label{font-size:10px;font-weight:500;letter-spacing:.025em;line-height:1;transition:font-weight .22s ease}.bottom-nav .bn-item:not(.active):hover{color:rgba(var(--bn-primary-rgb),.7)}.bottom-nav .bn-item:active .bn-icon-wrap{transform:scale(.88)}.bottom-nav .bn-item.active{color:var(--bn-primary)}.bottom-nav .bn-item.active .bn-icon-wrap{transform:translateY(-3px) scale(1.15)}.bottom-nav .bn-item.active .bn-icon{filter:drop-shadow(0 2px 8px rgba(var(--bn-primary-rgb),.4))}.bottom-nav .bn-item.active .bn-label{font-weight:700}.card{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:20px;margin-bottom:16px}.card-header{margin-bottom:16px}.card-header h2{margin:0;font-size:18px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:8px}.card-header h2 i{color:var(--primary)}.card-header p{margin:6px 0 0;color:var(--muted);font-size:13px}.eyebrow{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--muted-2);letter-spacing:.06em}.eyebrow i{margin-right:4px}.form{display:flex;flex-direction:column;gap:14px}.field{display:flex;flex-direction:column;gap:6px}.field .label{font-size:12px;font-weight:600;color:var(--muted);letter-spacing:.02em;display:flex;align-items:center;gap:6px;flex-wrap:wrap}.field .label .label-hint{font-size:11px;font-weight:500;color:var(--muted-2);font-style:italic;text-transform:none;letter-spacing:0}.field input[type=text],.field input[type=date],.field input[type=time],.field input[type=number]{padding:12px 14px;border:1.5px solid var(--border);border-radius:10px;font-size:14px;font-family:inherit;color:var(--text);background:#fafbfc;width:100%;min-width:0;box-sizing:border-box;appearance:none;-webkit-appearance:none;transition:border-color .15s,background .15s;min-height:46px;font-variant-numeric:tabular-nums}.field input[type=text]:focus,.field input[type=date]:focus,.field input[type=time]:focus,.field input[type=number]:focus{outline:none;border-color:var(--primary);background:#fff}.field input[type=text]::placeholder,.field input[type=date]::placeholder,.field input[type=time]::placeholder,.field input[type=number]::placeholder{color:var(--muted-2)}.field input[type=number]{-moz-appearance:textfield}.field input[type=number]::-webkit-outer-spin-button,.field input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.radio-group{display:flex;gap:8px;flex-wrap:wrap}.chip{padding:9px 16px;border:1.5px solid var(--border);background:#fff;border-radius:999px;font-size:13px;cursor:pointer;color:var(--text);transition:all .15s;font-family:inherit}.chip:hover{border-color:var(--primary);color:var(--primary)}.chip.active{background:var(--primary);border-color:var(--primary);color:#fff}.form-actions{display:flex;gap:10px;margin-top:4px;flex-wrap:wrap}.btn{display:inline-flex;align-items:center;gap:6px;padding:10px 18px;border:none;border-radius:10px;font-size:14px;font-weight:600;font-family:inherit;cursor:pointer;transition:background .15s,color .15s,border-color .15s}.btn:disabled{opacity:.5;cursor:not-allowed}.btn.small{padding:6px 12px;font-size:12px}.btn.primary{background:var(--primary);color:#fff}.btn.primary:not(:disabled):hover{background:var(--primary-2)}.btn.ghost{background:transparent;color:var(--muted);border:1.5px solid var(--border)}.btn.ghost:hover{color:var(--text);border-color:var(--border-strong)}.btn.danger-ghost{background:transparent;color:var(--rose);border:1.5px solid var(--rose-soft)}.btn.danger-ghost:hover{background:var(--rose-soft)}.btn.icon-btn{padding:0;width:36px;height:36px;justify-content:center;background:transparent;color:var(--muted);border:1.5px solid var(--border);border-radius:10px}.btn.icon-btn i{font-size:14px}.btn.icon-btn:not(:disabled):hover{color:var(--primary);border-color:var(--primary);background:var(--primary-soft)}.btn.icon-btn .spin{animation:spin-refresh .9s linear infinite}@keyframes spin-refresh{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.age-stats{display:flex;align-items:baseline;justify-content:flex-start;gap:16px;padding:14px 16px;background:var(--primary-soft);border-radius:12px}.age-stats .stat{text-align:center}.age-stats .stat .num{font-size:26px;font-weight:700;color:var(--primary);line-height:1;font-variant-numeric:tabular-nums}.age-stats .stat .unit{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-top:3px}.age-stats .dot{color:var(--muted-2);font-size:20px}.period-card{margin-bottom:0}.period-card h2{margin:6px 0 8px;font-size:20px;font-weight:700}.period-card .period-summary{color:var(--muted);font-size:14px;margin:0 0 14px;line-height:1.55}.schedule-grid{display:grid;grid-template-columns:1fr;gap:10px}.schedule{display:flex;gap:12px;padding:12px;background:#fafbfc;border:1px solid var(--border);border-radius:12px}.schedule i{color:var(--primary);font-size:18px;margin-top:2px}.schedule .schedule-title{font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-bottom:2px}.schedule .schedule-text{font-size:14px;color:var(--text);line-height:1.5}.compare-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}@media(max-width:768px){.compare-grid{grid-template-columns:1fr}}.day-card{margin-bottom:0;min-width:0;overflow:hidden}.day-card.today{border-color:#3b82f6;background:linear-gradient(180deg,#dbeafe,#fff 50%)}.day-card.yesterday{background:#fafbfc}.day-date-nav-wrap{position:relative;margin-bottom:12px}.day-date-nav-reset{position:absolute;top:-8px;right:-8px;z-index:1;width:24px;height:24px;border:1px solid var(--border);border-radius:50%;background:#fff;color:var(--muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;box-shadow:0 1px 3px #0f172a14}.day-date-nav-reset i{font-size:10px}.day-date-nav-reset:hover{background:#fee2e2;border-color:#fecaca;color:#dc2626}.day-date-nav-reset:active{background:#fee2e2;color:#dc2626}.day-date-strip{display:grid;grid-template-columns:32px 1fr 32px;gap:6px;align-items:stretch;padding:6px 8px;border-radius:10px;background:#fff;border:1px solid var(--border);touch-action:manipulation}.day-date-strip-scroller{display:flex;gap:4px;min-width:0;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;scrollbar-width:thin;padding:1px 2px}.day-date-strip-scroller::-webkit-scrollbar{height:4px}.day-date-strip-scroller::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:999px}.day-date-strip-day{flex:0 0 64px;scroll-snap-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-width:0;padding:6px 4px;border:1px solid transparent;border-radius:8px;background:#f8fafc;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.day-date-strip-day:hover{background:#eef2ff;border-color:#c7d2fe}.day-date-strip-day.active{background:#dbeafe;border-color:#3b82f6;box-shadow:inset 0 0 0 1px #3b82f626}.day-date-strip-date{font-size:12px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.2}.day-date-strip-ml{font-size:11px;font-weight:600;color:#1d4ed8;font-variant-numeric:tabular-nums;line-height:1.2}.day-date-strip-ml.empty{color:var(--muted);font-weight:500}.day-date-strip-arrow{width:32px;min-height:52px;flex-shrink:0;border:none;border-radius:8px;background:#f1f5f9;color:var(--text);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.day-date-strip-arrow i{font-size:12px}.day-date-strip-arrow:hover:not(:disabled){background:var(--primary);color:#fff}.day-date-strip-arrow:active:not(:disabled){background:var(--primary);color:#fff}.day-date-strip-arrow:disabled{opacity:.35;cursor:not-allowed}.day-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:12px}.day-head h3{margin:4px 0 0;font-size:16px;color:var(--text);font-variant-numeric:tabular-nums}.big-total{display:flex;align-items:baseline;gap:3px}.big-total .num{font-size:32px;font-weight:800;color:var(--text);line-height:1;font-variant-numeric:tabular-nums}.big-total .unit{font-size:14px;color:var(--muted);font-weight:500}.day-stats{display:flex;flex-wrap:wrap;gap:10px 16px;padding:10px 0 0;border-top:1px solid var(--border)}.day-stats>div{font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:5px}.day-stats>div i{color:var(--primary);font-size:12px}.compare-banner{margin-top:12px;padding:12px;background:var(--primary-soft);border-radius:12px;font-size:12px;color:var(--text);display:flex;flex-direction:column;gap:8px}.compare-banner strong{color:var(--primary);font-variant-numeric:tabular-nums;font-weight:700}.compare-banner .compare-row{display:flex;align-items:center;justify-content:space-between;gap:12px}.compare-banner .compare-row:not(:last-child){padding-bottom:8px;border-bottom:1px dashed rgba(15,23,42,.1)}.compare-banner .compare-stats{display:flex;align-items:center;gap:6px;flex:1}.compare-banner .compare-stats .label{color:var(--muted);font-weight:500;font-size:11px}.compare-banner .compare-stats .count{color:var(--muted-2);font-size:11px}.compare-banner .compare-change{display:flex;align-items:center;gap:4px;font-size:11px;font-weight:600;flex-shrink:0}.compare-banner .compare-change i{font-size:10px}.compare-banner .compare-change i.up{color:var(--mint)}.compare-banner .compare-change i.down{color:var(--amber)}.compare-banner .compare-change strong{font-size:12px}.compare-banner .compare-change span{color:var(--muted-2);font-weight:500}.today-logs{margin-top:12px;padding:12px;background:#fafbfc;border:1px solid var(--border);border-radius:12px}.logs-header{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px}.logs-header span{display:flex;align-items:center;gap:6px}.logs-header span:before{content:\"\\1f37c\";font-size:14px}.logs-header .logs-more{text-transform:none;letter-spacing:0;background:transparent;border:none;color:var(--primary);font-size:12px;font-weight:600;padding:4px 8px;border-radius:6px;cursor:pointer;display:inline-flex;align-items:center;gap:3px;transition:background .2s ease}.logs-header .logs-more i{font-size:10px}.logs-header .logs-more:hover{background:var(--primary-soft)}.log-list{display:flex;flex-direction:column;gap:6px;min-width:0}.log-row{display:flex;align-items:center;gap:10px;padding:8px 10px;background:#fafbfc;border-radius:8px;font-size:13px;min-width:0;max-width:100%;transition:all .2s ease;position:relative}.log-row.low-volume .log-volume{color:#f59e0b;font-weight:900}.log-row.high-volume .log-volume{color:#10b981;font-weight:900}.log-row:hover{background:#f1f5f9;transform:translateY(-1px);box-shadow:0 2px 8px #0000000d}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}.log-time{font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;min-width:42px}.log-volume{font-weight:800;color:var(--primary);font-size:16px;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.log-gap{display:inline-flex;align-items:center;gap:3px;padding:2px 7px;background:#f3f4f6;color:#6b7280;border-radius:999px;font-size:10.5px;font-weight:600;white-space:nowrap;flex-shrink:0;font-variant-numeric:tabular-nums;transition:all .2s ease}.log-gap i{font-size:9px;opacity:.7}.log-gap.feed-gap-warn{background:linear-gradient(135deg,#f59e0b,#ea580c);color:#fff;font-weight:700;border:1px solid rgba(234,88,12,.45);box-shadow:0 0 0 1px #fff3 inset,0 2px 8px #ea580c59}.log-gap.feed-gap-warn i{opacity:.95;color:inherit}.log-note{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.log-actions{margin-left:auto;display:inline-flex;align-items:center;gap:2px}.log-edit,.log-del{background:transparent;border:none;color:var(--muted-2);cursor:pointer;padding:4px 6px;border-radius:6px;font-size:12px;transition:all .2s ease}.log-edit:hover{color:var(--primary);background:var(--primary-soft)}.log-del:hover{color:var(--rose);background:var(--rose-soft)}.empty-mini{padding:12px;text-align:center;color:var(--muted-2);font-size:13px;font-style:italic}.countdown-hero{display:flex;flex-direction:column;gap:16px;padding:18px 20px;background:#fff;border-radius:16px;border:1px solid #e6e9ff;transition:all .3s ease;margin-bottom:20px}.countdown-hero .hero-main{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:20px}.countdown-hero .feeding-time-card{flex:1;min-width:0;text-align:center}.countdown-hero .feeding-time-card .time-header{margin-bottom:12px;display:flex;justify-content:center}.countdown-hero .feeding-time-card .time-header .status-badge{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;padding:6px 12px;border-radius:14px;white-space:nowrap}.countdown-hero .feeding-time-card .time-header .status-badge i{font-size:11px}.countdown-hero .feeding-time-card .time-header .status-badge.status-waiting{background:var(--primary-soft);color:var(--primary)}.countdown-hero .feeding-time-card .time-header .status-badge.status-now{background:#fee2e2;color:#dc2626;animation:pulse-gentle 2s ease-in-out infinite;font-size:11px;text-transform:none;font-weight:700}.countdown-hero .feeding-time-card .time-header .status-badge.status-late{background:var(--rose-soft);color:var(--rose)}.countdown-hero .feeding-time-card .time-display .predicted-time{font-size:42px;font-weight:800;line-height:1;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.02em;margin-bottom:4px}.countdown-hero .feeding-time-card .time-display .time-remaining{font-size:15px;font-weight:500;color:var(--muted);font-variant-numeric:tabular-nums}.countdown-hero .countdown-next{display:flex;flex-direction:column;gap:8px;padding-left:16px;border-left:1px dashed #d8dcff;flex-shrink:0;min-width:0}.countdown-hero .next-item{display:flex;align-items:center;gap:6px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.countdown-hero .next-item i{color:var(--primary);font-size:13px}.countdown-hero .next-item strong{font-weight:700}.countdown-hero .next-item .predict-label,.countdown-hero .next-item .recommend-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-2);margin-left:4px}.countdown-hero .next-item .recommend-label{color:var(--mint)}.countdown-hero .volume-info{display:flex;flex-direction:column;gap:8px;padding-left:20px;border-left:1px dashed #d8dcff;flex-shrink:0;min-width:160px;transition:all .3s ease}.countdown-hero .volume-info .volume-row{display:flex;align-items:center;justify-content:space-between;gap:12px}.countdown-hero .volume-info .volume-row .volume-prefix{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-2);flex-shrink:0}.countdown-hero .volume-info .volume-row .volume-amount{font-size:22px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1;text-align:right}.countdown-hero .volume-info .volume-row.predicted-row .volume-prefix,.countdown-hero .volume-info .volume-row.predicted-row .volume-amount{color:var(--primary)}.countdown-hero .volume-info .volume-row.recommended-row .volume-prefix,.countdown-hero .volume-info .volume-row.recommended-row .volume-amount{color:var(--mint)}.countdown-hero[data-status=waiting]{border-color:#bbf7d0;background:linear-gradient(135deg,#f7fef8,#f0fdf4)}.countdown-hero[data-status=waiting] .feeding-time-card .time-display .predicted-time{color:#16a34a}.countdown-hero[data-status=waiting] .feeding-time-card .time-display .time-remaining{color:#15803d}.countdown-hero[data-status=waiting] .feeding-time-card .status-badge.status-waiting{background:#dcfce7!important;color:#15803d!important;border:1px solid #86efac}.countdown-hero[data-status=waiting] .volume-info .volume-amount{color:#16a34a}.countdown-hero[data-status=waiting] .volume-info .volume-prefix{color:#15803d}.countdown-hero[data-status=late]{border-color:#fca5a5;background:linear-gradient(135deg,#fef2f2,#fee2e2)}.countdown-hero[data-status=late] .feeding-time-card .time-display .predicted-time{color:#dc2626}.countdown-hero[data-status=late] .feeding-time-card .time-display .time-remaining{color:#b91c1c}.countdown-hero[data-status=late] .feeding-time-card .status-badge.status-late{background:#fee2e2;color:#dc2626;border:1px solid #fca5a5}.countdown-hero[data-status=late] .volume-info .volume-amount{color:#dc2626}.countdown-hero[data-status=late] .volume-info .volume-prefix{color:#b91c1c}.countdown-hero[data-status=now]{border-color:#fbbf24;background:linear-gradient(135deg,#fefce8,#fef3c7);animation:pulse-card 2s ease-in-out infinite}.countdown-hero[data-status=now] .feeding-time-card .time-display .predicted-time{color:#92400e}.countdown-hero[data-status=now] .feeding-time-card .time-display .time-remaining{color:#a16207}.countdown-hero[data-status=now] .feeding-time-card .status-badge.status-now{background:#fef3c7!important;color:#b45309!important;border:1px solid #f59e0b!important}.countdown-hero[data-status=now] .volume-info .volume-amount{color:#92400e}.countdown-hero[data-status=now] .volume-info .volume-prefix{color:#a16207}@media(max-width:540px){.countdown-hero .hero-main{flex-direction:column;align-items:stretch;gap:12px}.countdown-hero .hero-main .volume-info{border-left:none;border-top:1px dashed #d8dcff;padding-left:0;padding-top:12px;min-width:auto}.countdown-hero .hero-main .volume-info .volume-row{justify-content:space-between;padding:0 4px}.countdown-hero .hero-main .feeding-time-card .time-display .predicted-time{font-size:36px}.countdown-hero .hero-main .feeding-time-card .volume-info .volume-amount{font-size:20px}}@media(max-width:400px){.countdown-hero .feeding-time-card .status-badge{font-size:10px;padding:4px 10px}.countdown-hero .feeding-time-card .time-display .predicted-time{font-size:32px}.countdown-hero .volume-info .volume-amount{font-size:18px}}@keyframes pulse-soft{0%,to{opacity:1}50%{opacity:.65}}@keyframes pulse-gentle{0%,to{opacity:1}50%{opacity:.75}}@keyframes pulse-urgent{0%,to{opacity:1;text-shadow:0 0 0 rgba(239,68,68,0)}50%{opacity:.8;text-shadow:0 0 8px rgba(239,68,68,.25)}}@keyframes pulse-card{0%,to{transform:scale(1);box-shadow:0 1px 3px #0000001a,0 0 #f8717100}50%{transform:scale(1.02);box-shadow:0 4px 12px #00000026,0 0 0 2px #f871714d}}.burp-warning{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;margin:0 0 16px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:1px solid #f59e0b;border-radius:14px;box-shadow:0 2px 8px #f59e0b33;animation:burp-pulse 2s ease-in-out infinite}.burp-warning__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:40px;height:40px;background:#f59e0b;border-radius:50%;color:#fff;font-size:18px;animation:burp-icon-bounce 1.5s ease-in-out infinite}.burp-warning__content{flex:1;min-width:0}.burp-warning__title{font-size:15px;font-weight:700;color:#92400e;margin-bottom:4px}.burp-warning__text{font-size:13px;color:#78350f;line-height:1.5;margin-bottom:8px}.burp-warning__text strong{font-weight:600;color:#92400e}.burp-warning__countdown{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:#ffffffb3;border-radius:8px;font-size:13px;color:#92400e;font-weight:500}.burp-warning__countdown i{font-size:14px;color:#f59e0b}.burp-warning__countdown strong{font-size:16px;font-weight:700;color:#d97706}@keyframes burp-pulse{0%,to{box-shadow:0 2px 8px #f59e0b33}50%{box-shadow:0 4px 16px #f59e0b59}}@keyframes burp-icon-bounce{0%,to{transform:scale(1)}50%{transform:scale(1.1)}}.countdown-progress{margin-top:10px}.countdown-progress .cp-track{position:relative;height:6px;background:#ffffffbf;border-radius:999px;overflow:hidden}.countdown-progress .cp-fill{height:100%;background:linear-gradient(90deg,var(--primary),var(--accent));border-radius:999px;transition:width .4s ease}.countdown-progress .cp-fill[data-status=waiting]{background:linear-gradient(90deg,#22c55e,#16a34a)}.countdown-progress .cp-fill[data-status=late]{background:linear-gradient(90deg,#f87171,#dc2626)}.countdown-progress .cp-fill[data-status=now]{background:linear-gradient(90deg,#fbbf24,#d97706)}.countdown-progress .cp-labels{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:6px;font-size:11.5px;color:var(--muted)}.countdown-progress .cp-labels i{font-size:10px;margin-right:2px;color:var(--muted-2)}.countdown-progress .cp-labels .muted{color:var(--muted-2)}.countdown-progress .cp-labels .cp-right{font-weight:600;color:var(--muted);white-space:nowrap}.predict-head{display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:12px;margin-bottom:16px}.predict-head .eyebrow{color:var(--primary);display:flex;align-items:center;gap:4px}.predict-head .eyebrow.sparkle i{animation:sparkle 2s ease-in-out infinite}.predict-head h2{margin:4px 0 0;font-size:20px;font-weight:700}.last-feed{display:flex;align-items:center;gap:12px;padding:12px 14px;background:#fff;border-radius:12px;margin-bottom:14px;border:1px solid #e8e9ff}.last-feed .last-feed-icon{width:38px;height:38px;border-radius:50%;background:var(--primary-soft);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.last-feed .last-feed-icon i{color:var(--primary);font-size:16px}.last-feed .last-feed-body{flex:1;min-width:0}.last-feed .last-feed-label{font-size:10px;font-weight:700;text-transform:uppercase;color:var(--muted-2);letter-spacing:.06em;margin-bottom:2px}.last-feed .last-feed-value{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.last-feed .last-feed-value strong{color:var(--primary);font-size:18px;font-weight:800}.last-feed .last-feed-value .sep{color:var(--muted-2)}.last-feed .last-feed-value .ago{color:var(--accent);font-weight:600;font-size:13px}.last-feed .last-feed-note{margin-top:4px;font-size:12px;color:var(--muted);font-style:italic;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.predict-empty{padding:14px 16px;background:#fff;border-radius:12px;color:var(--muted);font-size:13px;display:flex;align-items:center;gap:8px}.predict-empty i{color:var(--primary)}.predict-body{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:14px}@media(max-width:640px){.predict-body{grid-template-columns:1fr}}.predict-metric{background:#fff;border-radius:12px;padding:14px;text-align:center}.predict-metric .metric-label{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px;display:flex;align-items:center;justify-content:center;gap:5px}.predict-metric .metric-label i{color:var(--primary);font-size:12px}.predict-metric .metric-value{font-size:28px;font-weight:800;line-height:1;color:var(--primary);font-variant-numeric:tabular-nums}.predict-metric .metric-value .ml-unit{font-size:14px;color:var(--muted);font-weight:500;margin-left:2px}.predict-metric .metric-sub{margin-top:6px;font-size:12px;color:var(--muted)}.reasoning{background:#fff;border-radius:12px;padding:12px 14px;margin-bottom:12px}.reasoning .reasoning-head{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--muted);letter-spacing:.05em;margin-bottom:6px}.reasoning .reasoning-head i{color:var(--primary);margin-right:4px}.reasoning ul{margin:0;padding-left:18px;list-style:disc}.reasoning li{font-size:13px;color:var(--text);line-height:1.55;margin:2px 0}.predict-actions{display:flex;justify-content:flex-end}.feed-list-card{margin-bottom:16px}.feed-list-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:12px}.feed-list-head h2{margin:4px 0 0;font-size:18px;font-weight:700}.feed-list-compact{display:flex;flex-direction:column;gap:6px}.feed-row{display:grid;grid-template-columns:68px 80px 1fr auto;gap:10px;align-items:center;padding:10px 12px;transition:all .2s ease;position:relative}.feed-row.low-volume .feed-row-volume strong{color:#f59e0b;font-weight:900}.feed-row.high-volume .feed-row-volume strong{color:#10b981;font-weight:900}.feed-row{background:#fafbfc;border-radius:10px;border:1px solid var(--border)}.feed-row .feed-row-time{display:flex;flex-direction:column;line-height:1.2;font-variant-numeric:tabular-nums;gap:3px}.feed-row .feed-row-time .time{font-weight:700;color:var(--text);font-size:14px}.feed-row .feed-row-time .date{font-size:11px;color:var(--muted-2)}.feed-row .feed-row-time .feed-row-gap{display:inline-flex;align-items:center;gap:3px;font-size:10.5px;font-weight:600;color:#6b7280;background:#f3f4f6;padding:1px 6px;border-radius:999px;width:fit-content;white-space:nowrap;font-variant-numeric:tabular-nums}.feed-row .feed-row-time .feed-row-gap i{font-size:8px;opacity:.7}.feed-row .feed-row-time .feed-row-gap.feed-gap-warn{background:linear-gradient(135deg,#f59e0b,#ea580c);color:#fff;font-weight:700;border:1px solid rgba(234,88,12,.45);box-shadow:0 0 0 1px #fff3 inset,0 2px 8px #ea580c59}.feed-row .feed-row-time .feed-row-gap.feed-gap-warn i{opacity:.95;color:inherit}.feed-row .feed-row-volume{font-variant-numeric:tabular-nums}.feed-row .feed-row-volume strong{color:var(--primary);font-size:19px;font-weight:800;letter-spacing:-.01em}.feed-row .feed-row-volume .u{font-size:11px;color:var(--muted);margin-left:2px}.feed-row .feed-row-note{font-size:13px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.feed-row .feed-row-note.muted{color:var(--muted-2);font-style:italic}.feed-row .feed-row-actions{display:inline-flex;align-items:center;gap:2px;margin-left:auto}.feed-row .feed-row-edit,.feed-row .feed-row-del{background:transparent;border:none;color:var(--muted-2);cursor:pointer;padding:6px 8px;border-radius:6px;font-size:13px}.feed-row .feed-row-edit:hover{color:var(--primary, #5b6cff);background:#5b6cff1a}.feed-row .feed-row-del:hover{color:var(--rose);background:var(--rose-soft)}@media(max-width:480px){.feed-row{grid-template-columns:58px 70px 1fr auto;gap:8px;padding:8px 10px}.feed-row .feed-row-time .time{font-size:13px}}.dialog-wide{max-width:720px;display:flex;flex-direction:column;padding:0;overflow:hidden}@media(max-width:640px){.dialog-wide{max-height:calc(100dvh - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px) - 72px);border-radius:14px}}.dialog-wide .dialog-head{position:sticky;top:0;z-index:5;background:var(--surface);padding:16px 20px;margin:0;border-bottom:1px solid var(--border);-webkit-backdrop-filter:saturate(1.2) blur(6px);backdrop-filter:saturate(1.2) blur(6px)}@media(max-width:640px){.dialog-wide .dialog-head{padding:12px 14px}}.dialog-wide .dialog-close{width:40px;height:40px;font-size:16px;background:#f1f3f7;color:var(--text)}.dialog-wide .dialog-close:hover{background:var(--rose-soft);color:var(--rose)}.dialog-wide .history-body,.dialog-wide .tips-dialog-body{padding:18px 20px 24px;overflow-y:auto;flex:1;min-height:0}@media(max-width:640px){.dialog-wide .history-body,.dialog-wide .tips-dialog-body{padding:14px 14px 20px}}.history-body{display:flex;flex-direction:column;gap:18px}.history-paging-hint{margin:0;font-size:12px;line-height:1.45}.history-load-more{display:grid;justify-items:center;width:100%;box-sizing:border-box;padding:8px 0 12px}.history-load-more .btn{width:auto;max-width:min(320px,100%);min-width:0;margin-inline:auto;justify-content:center}.tips-nav{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px;background:#f1f3f7;border-radius:12px;margin-bottom:16px}.nav-arrow{width:40px;height:40px;border-radius:50%;border:none;background:#fff;color:var(--primary);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:16px;transition:all .15s;flex-shrink:0}.nav-arrow:hover:not(:disabled){background:var(--primary);color:#fff;transform:scale(1.05)}.nav-arrow:active:not(:disabled){transform:scale(.95)}.nav-arrow:disabled{opacity:.35;cursor:not-allowed}.tips-now-btn{flex:1;padding:9px 16px;border:none;background:transparent;border-radius:999px;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;justify-content:center;gap:6px;transition:all .15s}.tips-now-btn i{font-size:12px}.tips-now-btn:hover{color:var(--primary);background:#fff}.tips-now-btn.active{background:var(--primary);color:#fff;pointer-events:none}.tips-dialog-body .period-summary{font-size:14px;color:var(--muted);line-height:1.6;margin:0 0 14px}.tips-dialog-body .schedule-grid{grid-template-columns:repeat(2,1fr);margin-bottom:16px}@media(max-width:560px){.tips-dialog-body .schedule-grid{grid-template-columns:1fr}}.dialog-tips-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.history-group .history-group-head{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;background:var(--primary-soft);border-radius:10px;margin-bottom:8px}.history-group .history-group-head .h-date{font-size:14px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums}.history-group .history-group-head .h-day{font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.05em}.history-group .history-group-head .h-total{font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.history-group .history-group-head .h-total strong{color:var(--primary);font-size:20px;font-weight:800}.history-group .history-group-head .h-total .h-count{color:var(--muted);font-size:12px;font-weight:500;margin-left:4px}.history-group .history-group-head .h-total .h-avg{color:var(--primary);font-size:12px;font-weight:600;margin-left:4px;font-variant-numeric:tabular-nums}.history-group .history-group-rows{display:flex;flex-direction:column;gap:4px}.tips-section-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px;padding:4px 4px 0}.tips-section-head .eyebrow i{margin-right:4px}.tips-section-head h2{margin:4px 0 0;font-size:20px;font-weight:700;color:var(--text)}.filter-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}.filter-chip{padding:7px 14px;border:1.5px solid var(--border);background:#fff;border-radius:999px;font-size:13px;font-weight:500;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;gap:5px;transition:all .15s;font-family:inherit}.filter-chip i{font-size:12px}.filter-chip:hover{border-color:var(--cat-color, var(--primary));color:var(--cat-color, var(--primary))}.filter-chip.active{background:var(--cat-color, var(--primary));border-color:var(--cat-color, var(--primary));color:#fff}.tips-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;margin-bottom:20px}.tip-card{background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--cat-color, var(--primary));border-radius:12px;padding:16px;transition:transform .15s}.tip-card:hover{transform:translateY(-2px)}.tip-card .tip-head{margin-bottom:8px}.tip-card .tip-pill{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;background:var(--cat-color, var(--primary));color:#fff;font-size:11px;font-weight:600;border-radius:999px;text-transform:uppercase;letter-spacing:.04em}.tip-card .tip-pill i{font-size:10px}.tip-card .tip-title{margin:6px 0 8px;font-size:15px;font-weight:700;line-height:1.35;color:var(--text)}.tip-card .tip-body{margin:0;font-size:13px;line-height:1.55;color:var(--muted)}.empty{grid-column:1/-1;padding:40px 20px;text-align:center;color:var(--muted-2)}.empty i{font-size:32px;margin-bottom:8px;display:block}.upcoming{margin-bottom:24px}.upcoming h3{margin:0 0 12px;font-size:16px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:6px}.upcoming h3 i{color:var(--primary)}.upcoming-grid{display:flex;gap:8px;flex-wrap:wrap}.upcoming-item{padding:10px 14px;background:var(--surface);border:1px solid var(--border);border-radius:10px;font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:6px}.upcoming-item i{color:var(--primary);font-size:12px}.disclaimer{padding:16px;background:var(--amber-soft);border-radius:12px;color:#78350f;font-size:13px;line-height:1.5;margin-bottom:24px;display:flex;gap:8px;align-items:flex-start}.disclaimer i{color:var(--amber);margin-top:2px}.toast{position:fixed;bottom:100px;left:50%;transform:translate(-50%);z-index:90;padding:12px 18px;border-radius:12px;font-size:14px;font-weight:500;box-shadow:0 6px 24px #0f172a1f;display:flex;align-items:center;gap:8px;animation:toastIn .3s cubic-bezier(.4,0,.2,1)}.toast.success{background:var(--mint);color:#fff}.toast.error{background:var(--rose);color:#fff}@keyframes toastIn{0%{transform:translate(-50%,20px);opacity:0}to{transform:translate(-50%);opacity:1}}.fab{position:fixed;bottom:calc(80px + env(safe-area-inset-bottom,0px));right:20px;z-index:96;display:inline-flex;align-items:center;gap:10px;padding:14px 22px 14px 18px;background:var(--primary);color:#fff;border:none;border-radius:999px;font-size:15px;font-weight:700;font-family:inherit;cursor:pointer;box-shadow:0 8px 24px #5b6cff73;transition:transform .15s,box-shadow .15s,background .15s}.fab i{font-size:18px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;background:#ffffff2e}.fab .fab-label{white-space:nowrap}.fab:hover{background:var(--primary-2);transform:translateY(-2px);box-shadow:0 12px 28px #5b6cff8c}.fab:active{transform:translateY(0)}@media(max-width:480px){.fab{padding:14px}.fab .fab-label{display:none}.fab i{font-size:22px;width:28px;height:28px}}.dialog-overlay{position:fixed;inset:0;background:#0f172a8c;z-index:110;display:flex;align-items:center;justify-content:center;padding:20px;animation:overlayIn .2s ease-out}.dialog-overlay.dialog-overlay--front{z-index:400}.dialog-overlay.dialog-overlay--event-reminder{z-index:410}@media(max-width:640px){.dialog-overlay{padding:calc(env(safe-area-inset-top,0px) + 16px) 12px calc(env(safe-area-inset-bottom,0px) + 16px);align-items:flex-start}}@keyframes overlayIn{0%{opacity:0}to{opacity:1}}.dialog{background:var(--surface);border-radius:20px;width:100%;max-width:560px;max-height:min(100vh - 40px,100dvh - 40px);overflow-y:auto;padding:24px;animation:dialogIn .25s cubic-bezier(.4,0,.2,1);box-shadow:0 20px 60px #0f172a40}@media(max-width:640px){.dialog{max-height:calc(100dvh - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px) - 32px);border-radius:16px}}@keyframes dialogIn{0%{opacity:0;transform:translateY(20px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.dialog-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:18px}.dialog-head h2{margin:4px 0 0;font-size:20px;font-weight:700;color:var(--text);display:flex;align-items:center;gap:8px}.dialog-head h2 i{color:var(--primary)}.dialog-close{background:#f1f3f7;border:none;width:36px;height:36px;border-radius:50%;cursor:pointer;color:var(--muted);font-size:14px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;transition:background .15s,color .15s}.dialog-close:hover{background:var(--rose-soft);color:var(--rose)}.log-form{display:flex;flex-direction:column;gap:14px}.log-volume-field{margin:0}.log-volume-field .log-volume-input-row{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px 10px;min-width:0}.log-volume-field .log-volume-input-row>input[type=number]{flex:0 0 118px;width:118px;max-width:min(118px,100%);min-width:0}.log-volume-field .predict-hint--inline{flex:1 1 auto;min-width:0;margin:0;padding:6px 10px;gap:6px;font-size:12px;border-radius:8px}.log-volume-field .predict-hint--inline>i{font-size:13px;flex-shrink:0}.log-volume-field .predict-hint--inline .hint-text{flex:1 1 auto;min-width:0;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.log-volume-field .predict-hint--inline .btn.small{flex-shrink:0;padding:4px 8px;font-size:11px}@media(max-width:400px){.log-volume-field .log-volume-input-row>input[type=number]{flex:1 1 100px;width:100%;max-width:none}.log-volume-field .predict-hint--inline{flex:1 1 100%;white-space:normal}.log-volume-field .predict-hint--inline .hint-text{white-space:normal;overflow:visible;text-overflow:unset}}.edit-date-banner{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:10px 14px;background:linear-gradient(135deg,#eef2ff,#f5f3ff);border:1px solid #dbe1ff;border-radius:12px;font-size:13px;color:var(--text)}.edit-date-banner>i.pi-calendar{color:var(--primary, #5b6cff);font-size:15px}.edit-date-banner .edb-label{color:var(--muted, #6b7280);font-weight:500}.edit-date-banner .edb-value{font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.01em}.edit-date-banner .edb-lock{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;flex-shrink:0;border-radius:50%;background:#ffffffe0;border:1px solid #e2e8f0;color:var(--muted, #64748b)}.edit-date-banner .edb-lock i{font-size:14px;line-height:1}.log-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.log-grid .field.full{grid-column:1/-1}.log-grid.log-grid--date-time{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:560px){.log-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:380px){.log-grid{grid-template-columns:1fr}}.quick-volumes{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.quick-volumes .quick-label{font-size:12px;color:var(--muted);font-weight:600;margin-right:4px}.quick-chip{padding:7px 13px;background:#f1f3f7;border:none;border-radius:999px;font-size:12px;font-weight:600;cursor:pointer;color:var(--muted);transition:all .15s;font-family:inherit}.quick-chip:hover{background:var(--primary-soft);color:var(--primary)}.quick-chip.now-chip{background:var(--primary-soft);color:var(--primary);display:inline-flex;align-items:center;gap:4px}.quick-chip.now-chip:hover{background:var(--primary);color:#fff}.quick-chip.formula-chip{display:inline-flex;align-items:center;gap:5px;background:#fff7ed;color:#c2410c;border:1px solid #fed7aa}.quick-chip.formula-chip i{font-size:11px;opacity:.9}.quick-chip.formula-chip:hover{background:#ffedd5;color:#9a3412;border-color:#fdba74}.quick-chip.formula-chip.active{background:#c2410c;color:#fff;border-color:#c2410c;box-shadow:0 2px 8px #c2410c40}.quick-chip.formula-chip.active:hover{background:#9a3412;border-color:#9a3412;color:#fff}.bottle-prep{background:#f0f9ff;border:1px solid #bae6fd;border-radius:12px;padding:8px 12px;margin-bottom:16px;display:flex;flex-direction:column;gap:8px;transition:background .2s,border-color .2s}.bottle-prep:has(.bp-warning){background:#fffbeb;border-color:#fde68a}.bottle-prep:has(.bp-warning) .bp-info>i{color:#f59e0b}.bottle-prep:has(.bp-warning) .bp-info strong{color:#d97706}.bottle-prep:has(.bp-warning) .bp-prep-user{color:#92400e;background:#fbbf246b}.bottle-prep:has(.bp-warning) .bp-prep-time{color:#c2410c;background:linear-gradient(180deg,#fff7ed,#ffedd5);border-color:#fb923c73}.bottle-prep:has(.bp-form){align-items:stretch;padding:10px 12px 12px}.bottle-prep .bp-warning{display:flex;align-items:center;justify-content:space-between;gap:10px;animation:slideDown .2s ease;flex-wrap:wrap}.bottle-prep .bp-warning__content{display:flex;align-items:center;gap:8px;font-size:13px;flex:1;min-width:0}.bottle-prep .bp-warning__content i{font-size:16px;flex-shrink:0}.bottle-prep .bp-warning__content strong{font-weight:700}.bottle-prep .bp-warning--expired{background:#fef2f2;border:1px solid #fecaca;border-radius:8px;padding:8px 10px;color:#991b1b}.bottle-prep .bp-warning--expired i{color:#dc2626}.bottle-prep .bp-warning--soon{background:#fefce8;border:1px solid #fde68a;border-radius:8px;padding:8px 10px;color:#92400e}.bottle-prep .bp-warning--soon i{color:#f59e0b}.bottle-prep .bp-warning__btn{flex-shrink:0;display:inline-flex;align-items:center;gap:5px;padding:7px 12px;font-size:12px;font-weight:700;font-family:inherit;color:#fff;background:linear-gradient(180deg,#f59e0b,#d97706);border:none;border-radius:8px;cursor:pointer;box-shadow:0 2px 4px #f59e0b40;transition:all .15s ease}.bottle-prep .bp-warning__btn i{font-size:12px}.bottle-prep .bp-warning__btn:hover{background:linear-gradient(180deg,#fbbf24,#f59e0b);transform:translateY(-1px);box-shadow:0 4px 8px #f59e0b59}.bottle-prep .bp-warning__btn:active{transform:translateY(0)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.bottle-prep .bp-info-row{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%}.bottle-prep:not(:has(.bp-warning)):not(:has(.bp-form)){flex-direction:row;align-items:center;justify-content:space-between;flex-wrap:wrap}.bottle-prep .bp-info{display:flex;align-items:flex-start;gap:8px;font-size:14px;color:var(--text);flex:1;min-width:0}.bottle-prep .bp-info>i{color:#0ea5e9;font-size:16px;margin-top:2px;flex-shrink:0}.bottle-prep .bp-info .bp-text{line-height:1.45;min-width:0}.bottle-prep .bp-info .bp-useby{display:inline-block;margin-top:2px;font-size:13px}.bottle-prep .bp-info strong{color:#0284c7;font-weight:800;font-variant-numeric:tabular-nums}.bottle-prep .bp-info .muted{color:var(--muted);font-size:13px}.bottle-prep .bp-actions{display:flex;gap:4px}.bottle-prep .bp-add{flex:1;background:transparent;border:none;padding:6px 4px;font-size:13px;font-weight:600;color:#0284c7;cursor:pointer;display:flex;align-items:center;gap:8px;font-family:inherit;text-align:left}.bottle-prep .bp-add>i{font-size:15px}.bottle-prep .bp-add:hover{color:#0369a1}.bottle-prep .bp-form{display:flex;flex-direction:column;gap:8px;width:100%}.bottle-prep .bp-form-head{display:flex;align-items:center;gap:6px}.bottle-prep .bp-form-head>i{color:#0ea5e9;font-size:15px}.bottle-prep .bp-form-head .bp-label{font-size:13px;color:var(--muted);font-weight:600;white-space:nowrap}.bottle-prep .bp-input-wrap{display:flex;align-items:center;gap:6px;background:#fff;border:1px solid #7dd3fc;border-radius:10px;padding:3px;transition:border-color .15s,box-shadow .15s}.bottle-prep .bp-input-wrap:focus-within{border-color:#0ea5e9;box-shadow:0 0 0 3px #0ea5e926}.bottle-prep .bp-input-wrap .bp-step{width:30px;height:30px;flex-shrink:0;border-radius:8px;border:none;background:#e0f2fe;color:#0369a1;font-size:12px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-family:inherit;transition:all .12s}.bottle-prep .bp-input-wrap .bp-step:hover{background:#bae6fd;color:#0284c7}.bottle-prep .bp-input-wrap .bp-step:active{transform:scale(.94)}.bottle-prep .bp-input-wrap .bp-step:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.bottle-prep .bp-input-wrap .bp-input{flex:1;min-width:60px;padding:4px 6px;font-size:18px;font-weight:800;border:none;background:transparent;font-variant-numeric:tabular-nums;font-family:inherit;color:#d97706;text-align:center;letter-spacing:-.01em}.bottle-prep .bp-input-wrap .bp-input:focus{outline:none}.bottle-prep .bp-input-wrap .bp-input:disabled{opacity:.55;cursor:not-allowed}.bottle-prep .bp-input-wrap .bp-unit{font-size:12px;color:var(--muted);font-weight:600;padding-right:4px}.bottle-prep .bp-quick{display:flex;flex-wrap:wrap;align-items:center;gap:5px}.bottle-prep .bp-quick .bp-quick-label{font-size:11px;color:var(--muted);font-weight:600;margin-right:2px}.bottle-prep .bp-quick .bp-quick-chip{padding:4px 9px;background:#f0f9ff;border:1px solid #7dd3fc;border-radius:999px;font-size:11.5px;font-weight:700;color:#0369a1;cursor:pointer;font-family:inherit;font-variant-numeric:tabular-nums;transition:all .12s}.bottle-prep .bp-quick .bp-quick-chip:hover{background:#e0f2fe;border-color:#38bdf8;color:#0284c7}.bottle-prep .bp-quick .bp-quick-chip:active{transform:scale(.95)}.bottle-prep .bp-quick .bp-quick-chip:disabled{opacity:.45;cursor:not-allowed}.bottle-prep .bp-form-actions{display:flex;gap:6px;justify-content:flex-end}.bottle-prep .bp-btn{width:32px;height:32px;border-radius:8px;border:none;background:#fff;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:12px;transition:all .15s;flex-shrink:0}.bottle-prep .bp-btn:hover:not(:disabled){background:#e0f2fe;color:#0284c7}.bottle-prep .bp-btn:disabled{opacity:.45;cursor:not-allowed}.bottle-prep .bp-btn.primary{background:#0ea5e9;color:#fff}.bottle-prep .bp-btn.primary:hover:not(:disabled){background:#0284c7}.bottle-prep .bp-btn.danger:hover{background:var(--rose-soft);color:var(--rose)}.calc-block{border:1px solid #fde7c2;background:#fffaf0;border-radius:12px;overflow:hidden}.calc-block .calc-head{padding:10px 14px 0}.calc-block .prep-info{display:flex;align-items:flex-start;gap:6px;font-size:13px;color:var(--text)}.calc-block .prep-info>i{color:#f59e0b;font-size:14px;margin-top:2px;flex-shrink:0}.calc-block .prep-info .prep-info-text{line-height:1.45;min-width:0}.calc-block .prep-info strong{color:#d97706;font-weight:800;font-variant-numeric:tabular-nums}.calc-block .prep-info .muted{color:var(--muted-2);font-size:12px;display:inline-block;margin-top:2px}.calc-block .calc-body{padding:8px 14px 14px;display:flex;flex-direction:column;gap:10px}.calc-block .field.mini.remaining-input{position:relative;margin:0;display:flex;flex-direction:column}.calc-block .field.mini.remaining-input .label{font-size:11px;font-weight:600;color:var(--muted);margin-bottom:4px}.calc-block .field.mini.remaining-input input{width:100%;padding:10px 36px 10px 12px;font-size:16px;font-weight:700;border:1px solid #fadf9e;border-radius:8px;background:#fff;font-variant-numeric:tabular-nums;font-family:inherit;color:#d97706}.calc-block .field.mini.remaining-input input:focus{outline:none;border-color:#f59e0b;box-shadow:0 0 0 3px #f59e0b26}.calc-block .field.mini.remaining-input .suffix{position:absolute;right:12px;top:50%;transform:translateY(4px);font-size:12px;color:var(--muted-2);pointer-events:none}.calc-block .calc-result-row{display:flex;align-items:center;justify-content:space-between;gap:10px}.calc-block .calc-result{display:flex;align-items:baseline;gap:4px;font-variant-numeric:tabular-nums}.calc-block .calc-result .calc-label{font-size:13px;color:var(--muted);font-weight:600}.calc-block .calc-result strong{font-size:22px;font-weight:800;color:var(--primary)}.calc-block .calc-result .u{font-size:12px;color:var(--primary);margin-left:2px}.calc-block .calc-result .muted{color:var(--muted-2);font-size:18px}.calc-block .calc-apply{flex-shrink:0}.calc-block .calc-apply:disabled{background:#e5e7eb;color:var(--muted-2);cursor:not-allowed;box-shadow:none}.predict-hint{display:flex;align-items:center;gap:10px;padding:10px 14px;background:linear-gradient(135deg,var(--primary-soft) 0%,var(--accent-soft) 100%);border-radius:10px;font-size:13px}.predict-hint>i{color:var(--primary);font-size:16px}.predict-hint .hint-text{flex:1;color:var(--text)}.predict-hint .hint-text strong{color:var(--primary);font-weight:700}.predict-hint.predict-hint--inline .hint-text strong{font-weight:800;font-variant-numeric:tabular-nums}.sync-error{padding:10px 14px;background:var(--rose-soft);color:#991b1b;border-radius:10px;font-size:13px;display:flex;align-items:center;gap:6px}.sync-success{padding:10px 14px;background:var(--mint-soft);color:#166534;border-radius:10px;font-size:13px;display:flex;align-items:center;gap:6px;animation:fadeIn .2s ease}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:4px}.feeding-settings-dialog .feeding-settings-hint{margin:0 0 14px;font-size:13px;line-height:1.45}.feeding-settings-dialog .feeding-settings-hint code{font-size:11px;padding:1px 5px;border-radius:4px;background:#f1f5f9}.feeding-settings-dialog .feeding-settings-grid{grid-template-columns:1fr;gap:16px}.feeding-settings-dialog .field-hint{display:block;margin-top:8px;font-size:12px;line-height:1.4;padding:8px 12px;background:#f8fafc;border-radius:8px;border-left:3px solid #e2e8f0}.feeding-settings-dialog .label{position:relative}.feeding-settings-dialog .label code{font-size:11px;font-weight:600;color:var(--primary);background:var(--primary-soft);padding:2px 6px;border-radius:4px}.feeding-settings-dialog .label .notification-badge{display:inline-flex;align-items:center;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:#fff;background:linear-gradient(135deg,#10b981,#059669);padding:2px 6px;border-radius:10px;margin-left:6px;box-shadow:0 1px 2px #10b98133;animation:gentle-pulse 2s ease-in-out infinite}.feeding-settings-dialog .notification-setting-field{position:relative}.feeding-settings-dialog .notification-setting-field input{border:1.5px solid #10b981;background:linear-gradient(to right,#fff,#f0fdf4)}.feeding-settings-dialog .notification-setting-field input:focus{border-color:#059669;box-shadow:0 0 0 3px #10b9811a;background:#fff}.feeding-settings-dialog .notification-setting-field input::placeholder{color:#6b7280;opacity:.7}.feeding-settings-dialog .notification-setting-field .field-hint{border-left-color:#10b981;background:linear-gradient(to right,#f0fdf4,#f8fafc)}@keyframes gentle-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.85;transform:scale(1.02)}}.log-time--with-badge,.feed-row-time .time--with-badge{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}.log-merge-badge,.feed-merge-badge{font:inherit;font-size:10px;font-weight:700;padding:2px 7px;border-radius:999px;border:1px solid rgba(99,102,241,.35);background:linear-gradient(135deg,#e0e7ff,#c7d2fe);color:#312e81;cursor:pointer;line-height:1.2;white-space:nowrap}.log-merge-badge:hover,.feed-merge-badge:hover{filter:brightness(1.03)}.log-row--clickable,.feed-row--clickable{cursor:pointer}.log-row--clickable:hover,.feed-row--clickable:hover{background:#6366f10f}.log-row--clickable:focus-visible,.feed-row--clickable:focus-visible{outline:2px solid rgba(99,102,241,.45);outline-offset:2px}.dialog-overlay.dialog-overlay--front.feed-group-detail-overlay{z-index:125}.dialog-overlay.dialog-overlay--front.feed-detail-overlay{z-index:140;animation:overlayIn .12s ease-out}.dialog-overlay.dialog-overlay--front.feed-detail-overlay .feed-detail-dialog{animation:feedDetailIn .14s ease-out}@keyframes feedDetailIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.feed-detail-dialog{--fd-accent: 99, 102, 241;--fd-soft: #eef2ff;--fd-strong: #4338ca;max-width:min(400px,96vw);padding:0;overflow:hidden;display:flex;flex-direction:column}.feed-detail-dialog[data-status=low]{--fd-accent: 245, 158, 11;--fd-soft: #fffbeb;--fd-strong: #b45309}.feed-detail-dialog[data-status=high]{--fd-accent: 244, 63, 94;--fd-soft: #fff1f2;--fd-strong: #e11d48}.feed-detail-dialog[data-status=ok]{--fd-accent: 16, 185, 129;--fd-soft: #ecfdf5;--fd-strong: #059669}.feed-detail-top{position:relative;padding:20px 20px 16px;text-align:center;background:radial-gradient(120% 80% at 50% -20%,rgba(var(--fd-accent),.22),transparent 55%),linear-gradient(180deg,var(--fd-soft) 0%,#ffffff 72%);border-bottom:1px solid rgba(var(--fd-accent),.12)}.feed-detail-close{position:absolute;top:12px;right:12px;width:36px;height:36px;border:none;border-radius:50%;background:#ffffffd9;color:#64748b;cursor:pointer;display:grid;place-items:center;box-shadow:0 2px 8px #0f172a14;transition:background .15s ease,color .15s ease}.feed-detail-close:hover{background:#fff;color:#0f172a}.feed-detail-eyebrow{margin:0 0 6px;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#64748b}.feed-detail-metric{display:flex;align-items:flex-end;justify-content:center;gap:4px;line-height:1;margin-bottom:10px}.feed-detail-metric__value{font-size:clamp(48px,14vw,56px);font-weight:800;letter-spacing:-.04em;color:var(--fd-strong);font-variant-numeric:tabular-nums}.feed-detail-metric__unit{font-size:18px;font-weight:700;color:rgba(var(--fd-accent),.85);padding-bottom:8px}.feed-detail-status{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:999px;font-size:12px;font-weight:700;background:#fff;border:1px solid rgba(var(--fd-accent),.28);color:var(--fd-strong);box-shadow:0 2px 6px rgba(var(--fd-accent),.1)}.feed-detail-status .pi{font-size:13px}.feed-detail-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:14px}.feed-detail-chip{display:inline-flex;align-items:center;gap:6px;padding:7px 11px;border-radius:12px;background:#ffffffeb;border:1px solid #e2e8f0;font-size:12px;font-weight:600;color:#334155;line-height:1.3;box-shadow:0 1px 4px #0f172a0a}.feed-detail-chip .pi{font-size:13px;color:#6366f1;flex-shrink:0}.feed-detail-chip em{font-style:normal;font-weight:500;color:#94a3b8;margin-left:4px}.feed-detail-chip--time .pi{color:#dc2626}.feed-detail-chip--time span{font-variant-numeric:tabular-nums;font-weight:700;color:#dc2626}.feed-detail-chip--muted{background:#f8fafc;border-color:#e2e8f0;color:#64748b;font-weight:500}.feed-detail-chip--muted .pi{color:#94a3b8}.feed-detail-body{padding:16px 18px 8px;overflow-y:auto;flex:1;min-height:0}.feed-detail-section{margin-bottom:14px}.feed-detail-section:last-child{margin-bottom:0}.feed-detail-section__title{margin:0 0 10px;font-size:12px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#64748b;display:flex;align-items:center;gap:7px}.feed-detail-section__title .pi{font-size:13px;color:#6366f1}.feed-detail-cards{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.feed-detail-card{display:flex;align-items:flex-start;gap:12px;padding:12px 13px;border-radius:14px;background:linear-gradient(180deg,#fafbff,#fff);border:1px solid #e2e8f0;box-shadow:0 2px 8px #0f172a0a}.feed-detail-card--warn,.feed-detail-card--gap.feed-detail-card--warn{border-color:#f59e0b66;background:linear-gradient(180deg,#fffbeb,#fff)}.feed-detail-card--warn .feed-detail-card__icon,.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__icon{background:#fef3c7;color:#b45309}.feed-detail-card--warn .feed-detail-card__text,.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__text{color:#92400e}.feed-detail-card--position{border-color:#8b5cf659;background:linear-gradient(180deg,#f5f3ff,#fff)}.feed-detail-card--average{border-color:#0ea5e959;background:linear-gradient(180deg,#f0f9ff,#fff)}.feed-detail-card--next{border-color:#10b98159;background:linear-gradient(180deg,#ecfdf5,#fff)}.feed-detail-card--gap:not(.feed-detail-card--warn){border-color:#64748b59;background:linear-gradient(180deg,#f8fafc,#fff)}.feed-detail-card__icon{flex-shrink:0;width:36px;height:36px;border-radius:10px;display:grid;place-items:center;background:#eef2ff;color:#4f46e5;font-size:15px}.feed-detail-card__icon[data-kind=position]{background:#ede9fe;color:#7c3aed}.feed-detail-card__icon[data-kind=average]{background:#e0f2fe;color:#0284c7}.feed-detail-card__icon[data-kind=next]{background:#d1fae5;color:#059669}.feed-detail-card__icon[data-kind=gap]{background:#e2e8f0;color:#475569}.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__icon{background:#fef3c7;color:#b45309}.feed-detail-card__body{min-width:0;flex:1}.feed-detail-card__label{display:block;font-size:11px;font-weight:800;color:#64748b;margin-bottom:3px;letter-spacing:.02em}.feed-detail-card__text{margin:0;font-size:13px;line-height:1.5;color:#0f172a}.fdc-position__head{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin-bottom:8px}.fdc-position__idx{font-size:18px;font-weight:800;color:#6d28d9;letter-spacing:-.02em}.fdc-position__of{font-size:14px;font-weight:700;color:#a78bfa}.fdc-position__tag{font-size:11px;font-weight:600;color:#64748b;padding:2px 8px;border-radius:999px;background:#8b5cf61a}.fdc-progress{height:8px;border-radius:999px;background:#ede9fe;overflow:hidden;margin-bottom:10px}.fdc-progress__fill{height:100%;border-radius:inherit;background:linear-gradient(90deg,#8b5cf6,#6366f1);transition:width .2s ease}.fdc-position__stats{display:flex;flex-wrap:wrap;gap:8px}.fdc-stat{display:inline-flex;align-items:baseline;gap:4px;padding:6px 10px;border-radius:10px;font-size:12px}.fdc-stat strong{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums}.fdc-stat small{font-size:11px;font-weight:600;opacity:.85}.fdc-stat--violet{background:#f5f3ff;color:#5b21b6}.fdc-stat--violet strong{color:#6d28d9}.fdc-stat--indigo{background:#eef2ff;color:#4338ca}.fdc-stat--indigo strong{color:#4f46e5}.fdc-avg,.fdc-next{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}.fdc-pill{display:inline-flex;padding:4px 10px;border-radius:999px;font-size:13px;font-weight:800;font-variant-numeric:tabular-nums}.fdc-pill--up{background:#dcfce7;color:#15803d}.fdc-pill--down{background:#fee2e2;color:#b91c1c}.fdc-pill--neutral{background:#f1f5f9;color:#475569}.fdc-avg__meta{font-size:12px;color:#64748b;line-height:1.4}.fdc-avg__meta strong{color:#0f172a;font-weight:700}.fdc-next__time{font-size:16px;font-weight:800;color:#dc2626;font-variant-numeric:tabular-nums}.fdc-next__vol{font-size:14px;font-weight:800;color:#059669;padding:4px 10px;border-radius:8px;background:#d1fae5}.fdc-next__gap{font-size:12px;font-weight:600;color:#64748b;display:inline-flex;align-items:center;gap:4px}.fdc-gap{display:flex;flex-direction:column;gap:10px}.fdc-gap__prev{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px;padding:10px 12px;border-radius:10px;background:#ffffffe6;border:1px solid #e2e8f0}.fdc-gap__prev-label{font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#64748b;width:100%}.fdc-gap__prev-time{font-size:17px;font-weight:800;color:#0f172a;font-variant-numeric:tabular-nums}.fdc-gap__prev-vol{font-size:14px;font-weight:800;color:#475569;padding:3px 8px;border-radius:8px;background:#f1f5f9}.fdc-gap__prev-date{font-size:11px;font-weight:600;color:#94a3b8}.fdc-gap__row{display:flex;flex-wrap:nowrap;align-items:center;gap:8px;min-width:0}.fdc-gap__interval{display:inline-flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;padding:6px 10px;border-radius:999px;font-size:12px;font-weight:700;color:#475569;background:#e2e8f0;white-space:nowrap}.fdc-gap__interval .pi{font-size:13px;flex-shrink:0}.fdc-gap__interval span{overflow:hidden;text-overflow:ellipsis}.fdc-gap__interval--warn{color:#b45309;background:#fde68a;border:1px solid rgba(245,158,11,.35)}.fdc-gap__vol-diff{flex:0 0 auto;white-space:nowrap;font-size:12px;padding:5px 10px}.feed-detail-quote{margin:0;padding:12px 14px 12px 16px;border-radius:0;border-left:3px solid #c7d2fe;background:#f8fafc;font-size:14px;line-height:1.55;color:#334155;font-style:normal}.feed-detail-footer{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#fafbff}.feed-detail-cta{display:flex;gap:8px;justify-content:stretch}.feed-detail-cta .btn{flex:1;justify-content:center}.feed-detail-cta .btn.primary{flex:1.2}.feed-group-detail-dialog .feed-group-detail-summary{margin:0 0 8px;padding:0 2px;font-size:13px;line-height:1.45}.feed-group-detail-dialog .feed-group-detail-hint{margin:0 0 12px;font-size:12px;line-height:1.4;display:flex;align-items:center;gap:6px}.feed-group-detail-dialog .feed-group-detail-history{margin-bottom:4px}.feed-group-detail-dialog .feed-group-detail-rows{max-height:min(58vh,420px);overflow-y:auto;padding-right:2px}.mom-food-card{--mf-tone: 244, 114, 182;--mf-soft: #fdf2f8;--mf-ring: #fbcfe8;--mf-strong: #db2777;position:relative;overflow:hidden;background:radial-gradient(900px 260px at 0% 0%,rgba(var(--mf-tone),.14),transparent 60%),#fff;border-color:rgba(var(--mf-tone),.22);padding:18px;margin-top:16px}.mom-food-card[data-accent=rose]{--mf-tone: 244, 63, 94;--mf-soft: #fff1f2;--mf-ring: #fecdd3;--mf-strong: #e11d48}.mom-food-card[data-accent=peach]{--mf-tone: 251, 146, 60;--mf-soft: #fff7ed;--mf-ring: #fed7aa;--mf-strong: #ea580c}.mom-food-card[data-accent=mint]{--mf-tone: 16, 185, 129;--mf-soft: #ecfdf5;--mf-ring: #a7f3d0;--mf-strong: #059669}.mom-food-card[data-accent=lavender]{--mf-tone: 139, 92, 246;--mf-soft: #f5f3ff;--mf-ring: #ddd6fe;--mf-strong: #7c3aed}.mom-food-card[data-accent=amber]{--mf-tone: 245, 158, 11;--mf-soft: #fffbeb;--mf-ring: #fde68a;--mf-strong: #d97706}.mf-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:12px}.mf-head__lead{min-width:0;flex:1}.mf-head .eyebrow{display:inline-flex;align-items:center;gap:6px;color:var(--mf-strong);font-weight:700}.mf-head .eyebrow i{font-size:13px}.mf-head h2{margin:4px 0 0;font-size:18px;font-weight:800;color:var(--text);line-height:1.25}.mf-headline{margin:4px 0 0;font-size:13px;color:var(--mf-strong);font-weight:600}.mf-nav{display:inline-flex;align-items:center;gap:6px;background:var(--mf-soft);border-radius:999px;padding:4px;border:1px solid rgba(var(--mf-tone),.25);flex-shrink:0}.mf-arrow{width:30px;height:30px;border-radius:50%;border:none;background:#fff;color:var(--mf-strong);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .15s ease,background .15s ease}.mf-arrow i{font-size:12px}.mf-arrow:hover:not(:disabled){transform:scale(1.08);background:var(--mf-strong);color:#fff}.mf-arrow:disabled{opacity:.35;cursor:not-allowed}.mf-step{font-variant-numeric:tabular-nums;font-size:12px;color:var(--muted);padding:0 4px}.mf-step strong{color:var(--mf-strong);font-weight:800;font-size:13px}.mf-reset{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--mf-strong);background:transparent;border:1px dashed rgba(var(--mf-tone),.5);border-radius:999px;padding:4px 12px;cursor:pointer;margin-bottom:10px;transition:background .15s ease}.mf-reset:hover{background:var(--mf-soft)}.mf-reset i{font-size:11px}.mf-desc{margin:0 0 14px;font-size:13px;color:var(--muted);line-height:1.55}.mf-columns{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px}@media(max-width:640px){.mf-columns{grid-template-columns:1fr}}.mf-col{padding:12px 14px;border-radius:14px;background:#fff;border:1px solid #eef0f3}.mf-col--good{background:linear-gradient(180deg,#f0fdf4,#fff 80%);border-color:#bbf7d0}.mf-col--bad{background:linear-gradient(180deg,#fef2f2,#fff 80%);border-color:#fecaca}.mf-col-title{display:flex;align-items:center;gap:8px;margin:0 0 10px;font-size:14px;font-weight:800;color:var(--text);letter-spacing:.01em}.mf-dot{width:22px;height:22px;border-radius:50%;display:inline-grid;place-items:center;color:#fff;flex-shrink:0;font-size:11px}.mf-dot i{font-size:10px}.mf-dot.good{background:#10b981;box-shadow:0 2px 6px #10b9814d}.mf-dot.bad{background:#ef4444;box-shadow:0 2px 6px #ef44444d}.mf-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.mf-item{display:flex;align-items:flex-start;gap:10px;padding:8px 10px;border-radius:10px;background:#ffffffb3;transition:background .15s ease,transform .15s ease}.mf-item:hover{background:#fff;transform:translate(2px)}.mf-item--bad .mf-name{color:#7f1d1d}.mf-item--good .mf-name{color:#064e3b}.mf-emoji{width:28px;height:28px;border-radius:8px;background:#fff;display:inline-grid;place-items:center;font-size:16px;flex-shrink:0;box-shadow:0 1px 2px #0f172a0f}.mf-emoji--x{background:#fef2f2;color:#ef4444}.mf-emoji--x i{font-size:12px}.mf-item-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.mf-name{font-size:13px;font-weight:700;color:var(--text);line-height:1.3}.mf-note{font-size:11.5px;color:var(--muted);line-height:1.35}.mf-tip{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;border-radius:12px;background:var(--mf-soft);border:1px solid rgba(var(--mf-tone),.22);font-size:12.5px;color:var(--text);line-height:1.5}.mf-tip i{color:var(--mf-strong);font-size:15px;margin-top:1px;flex-shrink:0}.mom-tab .card{padding:12px 14px;margin-bottom:10px;border-radius:14px}.mom-tab .mom-wellness-section,.mom-tab .mom-tips-week{margin-bottom:10px}.mom-tab .mom-food-card{padding:12px 14px;margin-top:10px}.mom-tab .mf-head{margin-bottom:8px}.mom-tab .mf-head h2{font-size:16px}.mom-tab .mf-desc{margin-bottom:10px;font-size:12px;line-height:1.45;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.mom-tab .mf-columns{gap:8px;margin-bottom:8px}.mom-tab .mf-col{padding:8px 10px}.mom-tab .mf-list{gap:6px}.mom-tab .mf-item{padding:6px 8px}.mom-tab .mf-tip{padding:8px 10px;font-size:12px}.mom-hero{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;margin-bottom:14px;background:linear-gradient(135deg,#fdf2f8,#faf5ff,#eef2ff);border:1px solid #f9a8d4;border-radius:16px}.mom-hero .mom-hero__icon{font-size:36px;line-height:1;flex-shrink:0}.mom-hero h2{margin:0 0 6px;font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.02em}.mom-hero .mom-hero__sub{margin:0;font-size:13px;line-height:1.5;color:var(--muted)}.mom-hero .mom-hero__sub strong{color:var(--text)}.mom-hero .mom-hero__sub .muted-inline{display:block;margin-top:4px;font-size:12.5px;opacity:.92}.mom-hero--compact{align-items:center;padding:10px 12px;margin-bottom:10px;border-radius:14px;gap:10px}.mom-hero--compact .mom-hero__icon{font-size:26px}.mom-hero--compact h2{margin:0;font-size:16px;letter-spacing:-.01em}.mom-hero--compact .mom-hero__title-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px}.mom-hero--compact .mom-hero__baby{font-size:12px;font-weight:700;color:#be185d;padding:2px 8px;border-radius:999px;background:#ffffffbf;border:1px solid rgba(244,114,182,.35)}.mom-hero--compact .mom-hero__sub{margin:4px 0 0;font-size:11.5px;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.mom-hero--compact .mom-hero__sub .muted-inline{display:inline;margin-top:0;font-size:11.5px}.section-head--tight{margin-bottom:8px}.section-head--tight h3{margin:0}.mom-disclaimer--compact{font-size:11px;line-height:1.4;padding:8px 10px;margin-top:4px;margin-bottom:6px}.section-head{margin-bottom:14px}.section-head h3{margin:0 0 6px;font-size:16px;font-weight:800;display:flex;align-items:center;gap:8px;color:var(--text)}.section-head h3 i{color:#db2777;font-size:15px}.section-head .section-sub{margin:0;font-size:12.5px;color:var(--muted);line-height:1.45}.mom-wellness-section{margin-bottom:16px}.mom-tab .mom-wellness-grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:8px}.mom-wellness-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.mom-w-card{padding:14px 14px 12px;border-radius:14px;border:1px solid var(--border);background:#fafafa;transition:border-color .15s,box-shadow .15s}.mom-w-card:hover{border-color:#f472b6;box-shadow:0 6px 18px -12px #db277759}.mom-w-card .mom-w-card__icon{width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,#fce7f3,#ede9fe);display:flex;align-items:center;justify-content:center;margin-bottom:10px}.mom-w-card .mom-w-card__icon i{font-size:16px;color:#be185d}.mom-w-card h4{margin:0 0 8px;font-size:13.5px;font-weight:800;color:var(--text);line-height:1.3}.mom-w-card p{margin:0;font-size:12.5px;line-height:1.5;color:var(--muted)}.mom-tips-week{margin-bottom:16px}.mom-tab .mom-tips-list{gap:6px}.mom-tab .mom-tips-list li{padding:8px 10px;border-radius:10px}.mom-tab .mom-tips-list li strong{margin-bottom:2px;font-size:12px}.mom-tab .mom-tips-list li span{font-size:11.5px;line-height:1.4}.mom-tips-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px}.mom-tips-list li{display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border-radius:12px;background:#fefce8;border:1px solid #fde047}.mom-tips-list li>i{color:#ca8a04;margin-top:2px;flex-shrink:0}.mom-tips-list li strong{display:block;font-size:13px;font-weight:800;color:var(--text);margin-bottom:4px}.mom-tips-list li span{font-size:12.5px;line-height:1.5;color:var(--muted)}.mom-disclaimer{margin-top:8px;margin-bottom:8px}.mom-empty-profile{max-width:520px;margin:24px auto 40px;text-align:center}.mom-empty-profile__inner{padding:28px 22px}.mom-empty-profile__inner .mom-empty-emoji{font-size:48px;display:block;margin-bottom:12px}.mom-empty-profile__inner h2{margin:0 0 10px;font-size:17px;font-weight:800;color:var(--text)}.mom-empty-profile__inner p{margin:0 0 18px;font-size:14px;line-height:1.55;color:var(--muted)}.event-reminder-dialog{max-width:min(520px,100vw - 28px);padding-bottom:8px}.event-reminder-dialog__head{align-items:flex-start;margin-bottom:4px}.event-reminder-dialog__title{margin:0;padding-right:40px;font-size:20px;font-weight:800;line-height:1.3;color:var(--text, #0f172a);display:flex;align-items:center;gap:10px;letter-spacing:-.02em}.event-reminder-dialog__title .pi-bell{color:#f59e0b;font-size:18px;flex-shrink:0}.event-reminder-list{list-style:none;margin:12px 0 0;padding:0;max-height:min(52vh,400px);overflow:auto;display:flex;flex-direction:column;gap:10px}.event-reminder-card{padding:14px 16px;background:linear-gradient(180deg,#fafbff,#fff);border:1px solid #e2e8f0;border-radius:14px;box-shadow:0 2px 8px #0f172a0d}.event-reminder-card__title{margin:0;font-size:16px;font-weight:800;color:var(--text, #0f172a);line-height:1.35}.event-reminder-card__datetime{margin:5px 0 0;font-size:12.5px;font-weight:500;color:#64748b;line-height:1.4}.event-reminder-card__date{color:#475569;font-weight:600}.event-reminder-card__sep{color:#94a3b8}.event-reminder-card__hour{color:#dc2626;font-weight:700;font-variant-numeric:tabular-nums}.event-reminder-card__place{margin:6px 0 0;display:flex;align-items:flex-start;gap:6px;font-size:13px;color:#475569;line-height:1.4}.event-reminder-card__place .pi-map-marker{margin-top:2px;flex-shrink:0;font-size:13px;color:var(--primary, #5b6cff)}.event-reminder-card__content-wrap{margin-top:10px;padding-top:10px;border-top:1px solid #eef1f6}.event-reminder-card__content-label{display:block;margin-bottom:4px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:#94a3b8}.event-reminder-card__content{margin:0;font-size:13.5px;color:#334155;line-height:1.5;white-space:pre-wrap}.event-reminder-actions{display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding-top:14px;border-top:1px solid var(--border, #e5e7eb)}.event-reminder-actions__link{flex:0 1 auto;min-width:0;padding:6px 4px;border:none;background:transparent;color:#64748b;font-size:13px;font-weight:600;font-family:inherit;text-decoration:underline;text-underline-offset:3px;cursor:pointer}.event-reminder-actions__link:hover:not(:disabled){color:#334155}.event-reminder-actions__link:disabled{opacity:.5;cursor:not-allowed}.event-reminder-actions__primary{flex:1 1 auto;display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:10px 18px;font-size:15px;font-weight:700;text-align:center}\n"] }]
17135
+ ChatShellComponent,
17136
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"feeding-root\">\n <div class=\"feeding-page\" #feedingPage>\n <div class=\"backdrop\"></div>\n\n <header class=\"hero\" [class.hero--profile-merged]=\"profile() && !editing() && ageBreakdown()\">\n @if (profile() && !editing() && ageBreakdown(); as age) {\n <!-- \u2550\u2550 REDESIGNED HERO \u2550\u2550 -->\n <app-hero-header\n [profile]=\"profile()!\"\n [age]=\"age\"\n [user]=\"user()\"\n [weightLabel]=\"profileHeroWeightLabel()\"\n [isAnyLoading]=\"isAnyLoading()\"\n [showRefresh]=\"bottomTab() !== 'schedule'\"\n (openMenu)=\"openSettingsMenu()\"\n (openChat)=\"openChatRoute()\"\n (refresh)=\"refreshAll()\"\n >\n <app-activity-log slot=\"activity-log\" (activityChanged)=\"onActivityChanged()\"></app-activity-log>\n </app-hero-header>\n\n <app-hero-stats-strip\n [currentTime]=\"currentTimeStr\"\n [dateLabel]=\"heroDateLabel\"\n [nextFeedTime]=\"prediction()?.nextTime ?? null\"\n [nextFeedCountdown]=\"heroNextFeedCountdown()\"\n [weightLabel]=\"profileHeroWeightLabel()\"\n [whoStatus]=\"nutritionTarget()?.ageLabel ?? null\"\n ></app-hero-stats-strip>\n\n <div class=\"hero-notif-wrap\">\n <app-notification-banner\n [notifications]=\"visibleNotifications()\"\n [saving]=\"notificationSaving()\"\n [currentUser]=\"user()\"\n [dialogOpen]=\"notifDialogOpen()\"\n (openDialog)=\"openNotificationRoute()\"\n (closeDialog)=\"notifDialogOpen.set(false)\"\n (acknowledge)=\"acknowledgeNotification($event)\"\n (acknowledgeAll)=\"notifDialogOpen.set(false); openAcknowledgeAllConfirmDialog()\"\n (delete)=\"deleteNotification($event)\"\n (openComposer)=\"notifDialogOpen.set(false); openNotificationComposerDialog()\"\n ></app-notification-banner>\n </div>\n\n } @else {\n <!-- \u2500\u2500 Fallback: no profile / editing \u2500\u2500 -->\n <div class=\"hero-inner\">\n <div class=\"hero-brand\">\n <div class=\"hero-title-row\">\n <div class=\"hero-title\">\n <div class=\"emoji\" aria-hidden=\"true\">\uD83D\uDC76</div>\n <div class=\"hero-text\">\n <h1>B\u00E9 y\u00EAu c\u1EE7a b\u1EA1n</h1>\n <p class=\"hero-userline\">\n <i class=\"pi pi-user\" aria-hidden=\"true\"></i>\n <strong>{{ user() }}</strong>\n </p>\n </div>\n </div>\n @if (profile() && !editing()) {\n <div class=\"hero-actions\">\n <app-activity-log (activityChanged)=\"onActivityChanged()\"></app-activity-log>\n <button\n class=\"btn icon-btn\"\n type=\"button\"\n (click)=\"feedingDialogs.openFeedingSettingsDialog()\"\n title=\"C\u00E0i \u0111\u1EB7t\"\n aria-label=\"C\u00E0i \u0111\u1EB7t c\u1EEF b\u00FA\"\n >\n <i class=\"pi pi-sliders-h\"></i>\n </button>\n @if (bottomTab() !== 'schedule') {\n <button\n class=\"btn icon-btn\"\n type=\"button\"\n (click)=\"refreshAll()\"\n [disabled]=\"isAnyLoading()\"\n [title]=\"\n isAnyLoading() ? '\u0110ang t\u1EA3i\u2026' : 'T\u1EA3i l\u1EA1i C\u1EEF b\u00FA, C\u00E2n, L\u1ECBch, Y t\u1EBF, T\u00E0i li\u1EC7u'\n \"\n aria-label=\"T\u1EA3i l\u1EA1i C\u1EEF b\u00FA, Th\u1EC3 tr\u1EA1ng, L\u1ECBch, Ti\u1EC1n s\u1EED y t\u1EBF v\u00E0 T\u00E0i li\u1EC7u\"\n >\n <i class=\"pi pi-refresh\" [class.spin]=\"isAnyLoading()\"></i>\n </button>\n }\n </div>\n }\n </div>\n </div>\n\n <div class=\"hero-datetime\" aria-live=\"polite\">\n <div class=\"hero-datetime-strip\">\n <div class=\"hero-datetime-strip__block hero-datetime-strip__block--date\">\n <i class=\"pi pi-calendar\" aria-hidden=\"true\"></i>\n <span class=\"hero-datetime-strip__wd\">{{ heroWeekday }}</span>\n <time class=\"hero-datetime-strip__date\" [attr.datetime]=\"todayDateStr()\">{{\n heroDateNumeric\n }}</time>\n </div>\n <span class=\"hero-datetime-strip__divider\" aria-hidden=\"true\"></span>\n <div class=\"hero-datetime-strip__block hero-datetime-strip__block--time\">\n <i class=\"pi pi-clock\" aria-hidden=\"true\"></i>\n <span class=\"hero-datetime-strip__clock\">{{ currentTimeStr }}</span>\n </div>\n </div>\n </div>\n\n <section class=\"hero-notification\" aria-label=\"Th\u00F4ng b\u00E1o n\u1ED9i b\u1ED9\">\n <!-- watermark background icons -->\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-bell\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-megaphone\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-comments\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--send\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-send\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--star\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-star\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--bolt\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-bolt\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--heart\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-heart\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--info\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-info-circle\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--check\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-check-circle\"></i>\n </span>\n <span\n class=\"hero-notification__bg-icon hero-notification__bg-icon--eye\"\n aria-hidden=\"true\"\n >\n <i class=\"pi pi-eye\"></i>\n </span>\n\n <div class=\"hero-notification__head\">\n <label class=\"hero-notification__composer-label\" for=\"hero-notification-input\">\n <i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i>\n <span>Th\u00F4ng b\u00E1o</span>\n @if (visibleNotifications().length > 0) {\n <span class=\"hero-notification__unread-badge\">{{\n visibleNotifications().length\n }}</span>\n }\n </label>\n <div class=\"hero-notification__head-actions\">\n <button\n type=\"button\"\n class=\"hero-notification__mark-all\"\n (click)=\"openAcknowledgeAllConfirmDialog()\"\n [disabled]=\"notificationSaving() || visibleNotifications().length === 0\"\n title=\"\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc\"\n >\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i>\n \u0110\u00E3 \u0111\u1ECDc t\u1EA5t c\u1EA3\n </button>\n <button\n type=\"button\"\n class=\"hero-notification__add\"\n (click)=\"openNotificationComposerDialog()\"\n aria-label=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n title=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n @if (displayedNotifications().length > 0) {\n <ul class=\"hero-notification__list\">\n @for (notice of displayedNotifications(); track notice) {\n <li class=\"hero-notification__item\">\n <div class=\"hero-notification__avatar\" aria-hidden=\"true\">\n {{ notice.user | slice: 0 : 2 | uppercase }}\n </div>\n <div class=\"hero-notification__body\">\n <div class=\"hero-notification__body-head\">\n <span class=\"hero-notification__author\">{{ notice.user }}</span>\n </div>\n <p class=\"hero-notification__content\">{{ notice.content }}</p>\n @if (notice.createdAt) {\n <span class=\"hero-notification__created\">{{\n formatNotificationCreatedAt(notice.createdAt)\n }}</span>\n }\n </div>\n <div class=\"hero-notification__item-actions\">\n <button\n type=\"button\"\n class=\"hero-notification__ack-top\"\n (click)=\"acknowledgeNotification(notice)\"\n [disabled]=\"notificationSaving()\"\n aria-label=\"\u0110\u00E3 \u0111\u1ECDc th\u00F4ng b\u00E1o\"\n title=\"\u0110\u00E3 \u0111\u1ECDc\"\n >\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n @if (canDeleteNotification(notice)) {\n <button\n type=\"button\"\n class=\"hero-notification__delete\"\n (click)=\"deleteNotification(notice)\"\n [disabled]=\"notificationSaving()\"\n aria-label=\"X\u00F3a th\u00F4ng b\u00E1o\"\n title=\"X\u00F3a th\u00F4ng b\u00E1o\"\n >\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </li>\n }\n </ul>\n } @else {\n <div class=\"hero-notification__empty\">\n <i class=\"pi pi-bell hero-notification__empty-icon\" aria-hidden=\"true\"></i>\n <span class=\"hero-notification__empty-title\">Kh\u00F4ng c\u00F3 th\u00F4ng b\u00E1o m\u1EDBi</span>\n <span class=\"hero-notification__empty-sub\"\n >M\u1ECDi th\u1EE9 \u0111\u1EC1u \u1ED5n. Th\u00F4ng b\u00E1o m\u1EDBi s\u1EBD xu\u1EA5t hi\u1EC7n \u1EDF \u0111\u00E2y.</span\n >\n </div>\n }\n\n @if (hiddenNotificationCount() > 0) {\n <button\n type=\"button\"\n class=\"hero-notification__more\"\n (click)=\"openNotificationListDialog()\"\n >\n Xem th\u00EAm {{ hiddenNotificationCount() }} th\u00F4ng b\u00E1o \u2192\n </button>\n }\n </section>\n\n </div>\n } <!-- end @else no-profile -->\n </header>\n\n <main\n class=\"content\"\n [class.is-documents]=\"bottomTab() === 'documents'\"\n [class.is-weight]=\"bottomTab() === 'weight'\"\n [class.is-schedule]=\"bottomTab() === 'schedule'\"\n [class.is-mom]=\"bottomTab() === 'mom'\"\n [class.is-medical]=\"bottomTab() === 'medical'\"\n >\n <!--\n ============ TAB PANES ============\n D\u00F9ng `[hidden]` thay v\u00EC `*ngIf` \u0111\u1EC3 c\u00E1c tab c\u00F9ng gi\u1EEF tr\u1EA1ng th\u00E1i khi\n user qua l\u1EA1i: scroll position, search query \u0111ang g\u00F5, viewMode, folder\n \u0111ang \u0111\u1EE9ng, file \u0111ang ch\u1ECDn, draft \u0111ang nh\u1EADp\u2026 \u0111\u1EC1u kh\u00F4ng b\u1ECB reset. H\u1EC7\n qu\u1EA3: `<app-documents>` \u0111\u01B0\u1EE3c mount 1 l\u1EA7n \u1EDF app load \u2014 `loadEntries()`\n ch\u1EA1y 1 l\u1EA7n, c\u00E1c l\u1EA7n switch tab k\u1EBF ti\u1EBFp kh\u00F4ng g\u1ECDi API th\u00EAm.\n -->\n <!-- ============ TAB: DOCUMENTS \u2014 \u0111\u00E3 chuy\u1EC3n sang subroute (m\u1EDF t\u1EEB Settings menu) ============ -->\n\n <!-- ============ TAB: WEIGHT ============ -->\n <div class=\"tab-pane tab-pane--weight\" [hidden]=\"bottomTab() !== 'weight'\">\n <app-weight\n [user]=\"user()\"\n [birthDate]=\"profile()?.birthDate\"\n [gender]=\"profile()?.gender\"\n [babyName]=\"profile()?.babyName\"\n ></app-weight>\n </div>\n\n <!-- ============ TAB: L\u1ECACH \u2014 Google Sheet tab \"Event\" ============ -->\n <div class=\"tab-pane tab-pane--schedule\" [hidden]=\"bottomTab() !== 'schedule'\">\n <app-feeding-schedule [user]=\"user()\"></app-feeding-schedule>\n </div>\n\n <!-- ============ TAB: TI\u1EC0N S\u1EEC Y T\u1EBE \u2014 Medical history V2 ============ -->\n <div class=\"tab-pane tab-pane--medical\" [hidden]=\"bottomTab() !== 'medical'\">\n <app-medical-history\n [user]=\"user()\"\n (openExplorerFile)=\"openMedicalAttachmentInDocuments($event)\"\n ></app-medical-history>\n </div>\n\n <!-- ============ TAB: M\u1EB8 \u2014 \u0111\u00E3 chuy\u1EC3n sang subroute (m\u1EDF t\u1EEB Settings menu) ============ -->\n\n <!-- ============ TAB: FEEDING ============ -->\n <div class=\"tab-pane tab-pane--feeding\" [hidden]=\"bottomTab() !== 'feeding'\">\n <app-feeding-profile\n [user]=\"user()\"\n [profile]=\"profile()\"\n [draft]=\"draft()\"\n [editing]=\"editing()\"\n [maxBirthDate]=\"maxBirthDate\"\n (save)=\"save()\"\n (cancelEdit)=\"cancelEdit()\"\n (startEdit)=\"startEdit()\"\n (clearProfile)=\"clearProfile()\"\n (draftNameChange)=\"updateDraftName($event)\"\n (draftBirthChange)=\"updateDraftBirth($event)\"\n (draftGenderChange)=\"setDraftGender($event)\"\n />\n\n @if (profile() && !editing() && ageBreakdown()) {\n <app-feeding-daily\n [logs]=\"logs()\"\n [feedingSettings]=\"feedingSettings()\"\n [now]=\"now()\"\n [nutritionTarget]=\"nutritionTarget()\"\n [user]=\"user()\"\n [syncMessage]=\"syncMessage()\"\n [syncError]=\"syncError()\"\n [logDialogOpen]=\"logDialogOpen()\"\n [loadingLogs]=\"loadingLogs()\"\n [refreshToken]=\"dailyRefreshToken()\"\n (logsChanged)=\"onFeedingLogsChanged()\"\n (bottlePrepChange)=\"bottlePrep.set($event)\"\n (editLog)=\"feedingDialogs.openEditDialog($event)\"\n (historyOpen)=\"feedingDialogs.openHistoryDialog($event.filter, $event.dateStr)\"\n (feedRowClick)=\"feedingDialogs.onFeedRowClick($event)\"\n >\n <app-feeding-charts\n data-feeding-charts\n [logs]=\"logs()\"\n [now]=\"now()\"\n [nutritionTarget]=\"nutritionTarget()\"\n />\n </app-feeding-daily>\n <app-feeding-nutrition\n [nutritionTarget]=\"nutritionTarget()\"\n [todayStats]=\"todayStats()\"\n [now]=\"now()\"\n [latestWeightKg]=\"latestWeightKgFromSheet()\"\n [editing]=\"editing()\"\n (goToWeight)=\"setBottomTab('weight')\"\n />\n }\n\n <!-- ============ FAB \u00AB Ghi c\u1EEF b\u00FA \u00BB c\u0169 \u0111\u00E3 \u0111\u01B0\u1EE3c thay b\u1EB1ng FAB gi\u1EEFa bottom-nav ============ -->\n </div>\n <!-- /.tab-pane--feeding -->\n </main>\n </div>\n <!-- /.feeding-page -->\n\n <!-- ============ BOTTOM NAVIGATION (C\u1EEF b\u00FA \u00B7 Th\u1EC3 tr\u1EA1ng \u00B7 + \u00B7 L\u1ECBch \u00B7 Y t\u1EBF) ============ -->\n <nav\n class=\"bottom-nav\"\n role=\"tablist\"\n aria-label=\"\u0110i\u1EC1u h\u01B0\u1EDBng ch\u00EDnh\"\n >\n <div class=\"bn-side bn-side--left\">\n @for (tab of navLeftTabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"bn-item\"\n role=\"tab\"\n [attr.aria-selected]=\"bottomTab() === tab.id\"\n [class.active]=\"bottomTab() === tab.id\"\n (click)=\"setBottomTab(tab.id)\"\n >\n <span class=\"bn-icon-wrap\">\n <i class=\"pi {{ tab.icon }} bn-icon\" aria-hidden=\"true\"></i>\n </span>\n <span class=\"bn-label\">{{ tab.label }}</span>\n </button>\n }\n </div>\n\n <button\n type=\"button\"\n class=\"bn-fab\"\n (click)=\"feedingDialogs.openLogDialog()\"\n [disabled]=\"!profile() || editing()\"\n [title]=\"(!profile() || editing()) ? 'Ch\u1ECDn b\u00E9 tr\u01B0\u1EDBc khi ghi c\u1EEF b\u00FA' : 'Ghi nh\u1EADn c\u1EEF b\u00FA m\u1EDBi'\"\n aria-label=\"Ghi nh\u1EADn c\u1EEF b\u00FA\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n\n <div class=\"bn-side bn-side--right\">\n @for (tab of navRightTabs(); track tab.id) {\n <button\n type=\"button\"\n class=\"bn-item\"\n role=\"tab\"\n [attr.aria-selected]=\"bottomTab() === tab.id\"\n [class.active]=\"bottomTab() === tab.id\"\n (click)=\"setBottomTab(tab.id)\"\n >\n <span class=\"bn-icon-wrap\">\n <i class=\"pi {{ tab.icon }} bn-icon\" aria-hidden=\"true\"></i>\n </span>\n <span class=\"bn-label\">{{ tab.label }}</span>\n </button>\n }\n </div>\n </nav>\n\n <!-- ============ NOTIFICATION SUBROUTE (full-screen) ============ -->\n @if (notifRouteOpen()) {\n <app-notification-list\n [notifications]=\"allNotifications()\"\n [currentUser]=\"user()\"\n [saving]=\"notificationSaving()\"\n (back)=\"closeNotificationRoute()\"\n (acknowledge)=\"acknowledgeNotification($event)\"\n (acknowledgeAll)=\"openAcknowledgeAllConfirmDialog()\"\n (delete)=\"deleteNotification($event)\"\n (openComposer)=\"openNotificationComposerDialog()\"\n />\n }\n\n <!-- \u2550\u2550 NOTIFICATION DIALOGS \u2014 rendered as siblings of .feeding-page (outside the\n overflow/stacking-context scroll zone) so they always overlay the\n full-screen notification subroute. See .feeding-page overflow-y:auto +\n -webkit-overflow-scrolling:touch in feeding.component.scss. \u2550\u2550 -->\n @if (notificationComposerDialogOpen()) {\n <div\n class=\"dialog-overlay dialog-overlay--front\"\n (click)=\"closeNotificationComposerDialog()\"\n >\n <div\n class=\"dialog hero-notification-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"T\u1EA1o th\u00F4ng b\u00E1o\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\" aria-hidden=\"true\"><i class=\"pi pi-bell\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\" aria-hidden=\"true\"><i class=\"pi pi-megaphone\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--send\" aria-hidden=\"true\"><i class=\"pi pi-send\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--star\" aria-hidden=\"true\"><i class=\"pi pi-star\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\" aria-hidden=\"true\"><i class=\"pi pi-comments\"></i></span>\n\n <div class=\"dialog-head hero-notification-dialog__head\">\n <div class=\"hero-notification-dialog__title-group\">\n <div class=\"hero-notification-dialog__icon-wrap\">\n <i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i>\n </div>\n <div>\n <h2 class=\"hero-notification-dialog__title\">T\u1EA1o th\u00F4ng b\u00E1o</h2>\n <p class=\"hero-notification-dialog__subtitle\">Th\u00F4ng b\u00E1o s\u1EBD hi\u1EC3n th\u1ECB cho to\u00E0n b\u1ED9 th\u00E0nh vi\u00EAn</p>\n </div>\n </div>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeNotificationComposerDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <div class=\"hero-notification__composer-panel\">\n <div class=\"hero-notification__composer-row\">\n <div class=\"hero-notification__input-wrap\">\n <textarea\n id=\"hero-notification-input\"\n class=\"hero-notification__input\"\n [value]=\"notificationDraft()\"\n (input)=\"updateNotificationDraft($any($event.target).value)\"\n [disabled]=\"notificationSaving()\"\n maxlength=\"300\"\n placeholder=\"Nh\u1EADp n\u1ED9i dung th\u00F4ng b\u00E1o cho m\u1ECDi ng\u01B0\u1EDDi...\"\n aria-label=\"N\u1ED9i dung th\u00F4ng b\u00E1o\"\n ></textarea>\n <div class=\"hero-notification__char-ring\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 36 36\">\n <circle class=\"hero-notification__char-ring-track\" cx=\"18\" cy=\"18\" r=\"15\" />\n <circle class=\"hero-notification__char-ring-fill\" cx=\"18\" cy=\"18\" r=\"15\"\n [style.stroke-dashoffset]=\"94 - (notificationDraft().trim().length / 300) * 94\" />\n </svg>\n <span class=\"hero-notification__char-count\">{{ notificationDraft().trim().length }}</span>\n </div>\n </div>\n </div>\n <div class=\"hero-notification__composer-actions\">\n <button type=\"button\" class=\"btn ghost hero-notification__cancel\"\n (click)=\"closeNotificationComposerDialog()\" [disabled]=\"notificationSaving()\">H\u1EE7y</button>\n <button type=\"button\" class=\"btn hero-notification__send\"\n (click)=\"createNotification()\"\n [disabled]=\"notificationSaving() || !notificationDraft().trim()\">\n <i class=\"pi pi-send\"></i>\n <span>G\u1EEDi th\u00F4ng b\u00E1o</span>\n </button>\n </div>\n </div>\n @if (notificationError()) {\n <p class=\"hero-notification__error\">{{ notificationError() }}</p>\n }\n </div>\n </div>\n }\n\n @if (notificationListDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeNotificationListDialog()\">\n <div class=\"dialog hero-notification-list-dialog\" role=\"dialog\" aria-modal=\"true\"\n aria-label=\"Danh s\u00E1ch th\u00F4ng b\u00E1o\" (click)=\"$event.stopPropagation()\">\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--bell\" aria-hidden=\"true\"><i class=\"pi pi-bell\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--megaphone\" aria-hidden=\"true\"><i class=\"pi pi-megaphone\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--comments\" aria-hidden=\"true\"><i class=\"pi pi-comments\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--star\" aria-hidden=\"true\"><i class=\"pi pi-star\"></i></span>\n <span class=\"hero-notification__bg-icon hero-notification__bg-icon--check\" aria-hidden=\"true\"><i class=\"pi pi-check-circle\"></i></span>\n\n <div class=\"dialog-head hero-notification-list-dialog__head\">\n <div class=\"hero-notification-dialog__title-group\">\n <div class=\"hero-notification-dialog__icon-wrap\"><i class=\"pi pi-megaphone\" aria-hidden=\"true\"></i></div>\n <div>\n <h2 class=\"hero-notification-list-dialog__title\">To\u00E0n b\u1ED9 th\u00F4ng b\u00E1o</h2>\n <p class=\"hero-notification-dialog__subtitle\">{{ visibleNotifications().length }} th\u00F4ng b\u00E1o</p>\n </div>\n </div>\n <div class=\"hero-notification-list-dialog__head-actions\">\n <button type=\"button\" class=\"hero-notification__mark-all\"\n (click)=\"openAcknowledgeAllConfirmDialog()\"\n [disabled]=\"notificationSaving() || visibleNotifications().length === 0\"\n title=\"\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc\">\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i> \u0110\u00E3 \u0111\u1ECDc t\u1EA5t c\u1EA3\n </button>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeNotificationListDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n </div>\n <div class=\"hero-notification-list-dialog__body\">\n @if (visibleNotifications().length > 0) {\n <ul class=\"hero-notification__list\">\n @for (notice of visibleNotifications(); track notice) {\n <li class=\"hero-notification__item\">\n <div class=\"hero-notification__avatar\" aria-hidden=\"true\">{{ notice.user | slice: 0 : 2 | uppercase }}</div>\n <div class=\"hero-notification__body\">\n <div class=\"hero-notification__body-head\">\n <span class=\"hero-notification__author\">{{ notice.user }}</span>\n </div>\n <p class=\"hero-notification__content\">{{ notice.content }}</p>\n @if (notice.createdAt) {\n <span class=\"hero-notification__created\">{{ formatNotificationCreatedAt(notice.createdAt) }}</span>\n }\n </div>\n <div class=\"hero-notification__item-actions\">\n <button type=\"button\" class=\"hero-notification__ack-top\"\n (click)=\"acknowledgeNotification(notice)\" [disabled]=\"notificationSaving()\"\n aria-label=\"\u0110\u00E3 \u0111\u1ECDc th\u00F4ng b\u00E1o\" title=\"\u0110\u00E3 \u0111\u1ECDc\">\n <i class=\"pi pi-times\" aria-hidden=\"true\"></i>\n </button>\n @if (canDeleteNotification(notice)) {\n <button type=\"button\" class=\"hero-notification__delete\"\n (click)=\"deleteNotification(notice)\" [disabled]=\"notificationSaving()\"\n aria-label=\"X\u00F3a th\u00F4ng b\u00E1o\" title=\"X\u00F3a th\u00F4ng b\u00E1o\">\n <i class=\"pi pi-trash\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n </li>\n }\n </ul>\n } @else {\n <div class=\"hero-notification__empty\">\n <i class=\"pi pi-bell hero-notification__empty-icon\" aria-hidden=\"true\"></i>\n <span class=\"hero-notification__empty-title\">Kh\u00F4ng c\u00F3 th\u00F4ng b\u00E1o m\u1EDBi</span>\n <span class=\"hero-notification__empty-sub\">M\u1ECDi th\u1EE9 \u0111\u1EC1u \u1ED5n. Th\u00F4ng b\u00E1o m\u1EDBi s\u1EBD xu\u1EA5t hi\u1EC7n \u1EDF \u0111\u00E2y.</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n\n @if (acknowledgeAllConfirmDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeAcknowledgeAllConfirmDialog()\">\n <div class=\"dialog ack-all-confirm-dialog\" role=\"alertdialog\" aria-modal=\"true\"\n aria-labelledby=\"ack-all-confirm-title\" (click)=\"$event.stopPropagation()\">\n <div class=\"ack-all-confirm-dialog__icon-wrap\" aria-hidden=\"true\"><i class=\"pi pi-check-circle\"></i></div>\n <h2 id=\"ack-all-confirm-title\" class=\"ack-all-confirm-dialog__title\">\u0110\u00E1nh d\u1EA5u t\u1EA5t c\u1EA3 \u0111\u00E3 \u0111\u1ECDc?</h2>\n <p class=\"ack-all-confirm-dialog__desc\">\n T\u1EA5t c\u1EA3 {{ visibleNotifications().length }} th\u00F4ng b\u00E1o s\u1EBD \u0111\u01B0\u1EE3c \u0111\u00E1nh d\u1EA5u \u0111\u00E3 \u0111\u1ECDc v\u00E0 \u1EA9n kh\u1ECFi danh s\u00E1ch.\n </p>\n <div class=\"ack-all-confirm-dialog__actions\">\n <button type=\"button\" class=\"btn ghost\" (click)=\"closeAcknowledgeAllConfirmDialog()\" [disabled]=\"notificationSaving()\">H\u1EE7y</button>\n <button type=\"button\" class=\"btn ack-all-confirm-dialog__confirm-btn\"\n (click)=\"confirmAcknowledgeAll()\" [disabled]=\"notificationSaving()\">\n <i class=\"pi pi-check\" aria-hidden=\"true\"></i> X\u00E1c nh\u1EADn\n </button>\n </div>\n </div>\n </div>\n }\n\n <!-- ============ SETTINGS FLOAT MENU (full-screen) ============ -->\n @if (settingsMenuOpen()) {\n <app-settings-menu\n [appName]=\"appInfo.name\"\n [appVersion]=\"appInfo.version\"\n [showDocuments]=\"explorerEnabled\"\n [unreadCount]=\"visibleNotifications().length\"\n (close)=\"closeSettingsMenu()\"\n (select)=\"onSettingsMenuSelect($event)\"\n />\n }\n\n <!-- ============ M\u1EB8 SUBROUTE (full-screen) ============ -->\n @if (momRouteOpen()) {\n <app-subroute-shell\n title=\"M\u1EB9\"\n (back)=\"closeMomRoute()\"\n >\n <app-feeding-mom\n [profile]=\"profile()\"\n [editing]=\"editing()\"\n (goToFeeding)=\"closeMomRoute(); setBottomTab('feeding')\"\n ></app-feeding-mom>\n </app-subroute-shell>\n }\n\n <!-- ============ T\u00C0I LI\u1EC6U SUBROUTE (full-screen) ============ -->\n @if (documentsRouteOpen()) {\n <app-subroute-shell\n title=\"T\u00E0i li\u1EC7u\"\n (back)=\"closeDocumentsRoute()\"\n >\n <app-documents></app-documents>\n </app-subroute-shell>\n }\n\n <!-- ============ TR\u1EE2 L\u00DD AI SUBROUTE (full-screen, m\u1EDF t\u1EEB n\u00FAt chat tr\u00EAn hero) ============ -->\n @if (chatRouteOpen()) {\n <app-subroute-shell\n title=\"Tr\u1EE3 l\u00FD AI\"\n (back)=\"closeChatRoute()\"\n >\n <app-chat-shell\n [context]=\"chatContext()\"\n [disabled]=\"chatDisabled()\"\n ></app-chat-shell>\n </app-subroute-shell>\n }\n\n <!-- About -->\n @if (aboutDialogOpen()) {\n <div class=\"dialog-overlay dialog-overlay--front\" (click)=\"closeAboutDialog()\">\n <div\n class=\"dialog about-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"feeding-about-title\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"dialog-head about-dialog__head\">\n <h2 id=\"feeding-about-title\" class=\"about-dialog__title\">\n <i class=\"pi pi-info-circle\" aria-hidden=\"true\"></i>\n About\n </h2>\n <button type=\"button\" class=\"dialog-close\" (click)=\"closeAboutDialog()\" aria-label=\"\u0110\u00F3ng\">\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <dl class=\"about-dialog__meta\">\n <div class=\"about-dialog__row\">\n <dt>\u1EE8ng d\u1EE5ng</dt>\n <dd>{{ appInfo.name }}</dd>\n </div>\n <div class=\"about-dialog__row\">\n <dt>Phi\u00EAn b\u1EA3n</dt>\n <dd>\n <code>{{ appInfo.version }}</code>\n </dd>\n </div>\n </dl>\n <div class=\"dialog-actions\">\n <button type=\"button\" class=\"btn primary\" (click)=\"closeAboutDialog()\">\u0110\u00F3ng</button>\n </div>\n </div>\n </div>\n }\n\n <!-- Nh\u1EAFc s\u1EF1 ki\u1EC7n l\u1ECBch (sheet Event + Settings) -->\n @if (eventReminderDialogOpen() && scheduleReminderEvents().length > 0) {\n <div\n class=\"dialog-overlay dialog-overlay--front dialog-overlay--event-reminder\"\n (click)=\"closeEventReminderDialog()\"\n >\n <div\n class=\"dialog event-reminder-dialog\"\n role=\"dialog\"\n aria-modal=\"true\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"dialog-head event-reminder-dialog__head\">\n <h2 class=\"event-reminder-dialog__title\">\n <i class=\"pi pi-bell\" aria-hidden=\"true\"></i>\n B\u1EA1n c\u00F3 l\u1ECBch s\u1EAFp t\u1EDBi\n </h2>\n <button\n type=\"button\"\n class=\"dialog-close\"\n (click)=\"closeEventReminderDialog()\"\n aria-label=\"\u0110\u00F3ng\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n </div>\n <ul class=\"event-reminder-list\">\n @for (ev of scheduleReminderEvents(); track ev) {\n <li>\n <article class=\"event-reminder-card\">\n <h3 class=\"event-reminder-card__title\">{{ ev.title }}</h3>\n <p class=\"event-reminder-card__datetime\">\n <span class=\"event-reminder-card__date\">{{ formatReminderEventWhen(ev) }}</span>\n <span class=\"event-reminder-card__sep\" aria-hidden=\"true\"> \u2013 </span>\n <span class=\"event-reminder-card__hour\">{{\n formatReminderEventTime(ev.time)\n }}</span>\n </p>\n @if (ev.place) {\n <p class=\"event-reminder-card__place\">\n <i class=\"pi pi-map-marker\" aria-hidden=\"true\"></i>\n <span>{{ ev.place }}</span>\n </p>\n }\n @if (ev.note) {\n <div class=\"event-reminder-card__content-wrap\">\n <span class=\"event-reminder-card__content-label\">N\u1ED9i dung</span>\n <p class=\"event-reminder-card__content\">{{ ev.note }}</p>\n </div>\n }\n </article>\n </li>\n }\n </ul>\n <div class=\"dialog-actions event-reminder-actions\">\n <button\n type=\"button\"\n class=\"event-reminder-actions__link\"\n (click)=\"acknowledgeAllEventReminders()\"\n >\n Kh\u00F4ng nh\u1EAFc l\u1EA1i\n </button>\n <button\n type=\"button\"\n class=\"btn primary event-reminder-actions__primary\"\n (click)=\"skipEventReminderSession()\"\n >\n \u0110\u00E3 hi\u1EC3u\n </button>\n </div>\n </div>\n </div>\n }\n\n <app-feeding-dialogs\n #feedingDialogs\n [logs]=\"logs()\"\n [user]=\"user()\"\n [now]=\"now()\"\n [bottlePrep]=\"bottlePrep()\"\n [feedingSettings]=\"feedingSettings()\"\n [prediction]=\"prediction()\"\n [todayStats]=\"todayStats()\"\n [yesterdayStats]=\"yesterdayStats()\"\n [todayLogs]=\"todayLogs()\"\n [yesterdayLogs]=\"yesterdayLogs()\"\n [maxBirthDate]=\"maxBirthDate\"\n [syncError]=\"syncError()\"\n [syncMessage]=\"syncMessage()\"\n (logsChanged)=\"onFeedingLogsChanged()\"\n (settingsChanged)=\"onFeedingSettingsChanged($event)\"\n (syncErrorChange)=\"syncError.set($event)\"\n (syncMessageChange)=\"syncMessage.set($event)\"\n (logDialogOpenChange)=\"logDialogOpen.set($event)\"\n (bottlePrepClearRequested)=\"clearBottlePrep()\"\n />\n</div>\n<!-- /.feeding-root -->\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;position:absolute;inset:0;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;--bg: #f6f7fb;--surface: #ffffff;--border: #e6e8ef;--border-strong: #d1d5db;--primary: #5b6cff;--primary-2: #4c5cf0;--primary-soft: #eef0ff;--accent: #ff5c8a;--accent-soft: #ffe7ef;--mint: #10b981;--mint-soft: #d1fae5;--amber: #f59e0b;--amber-soft: #fef3c7;--rose: #ef4444;--rose-soft: #fee2e2;--text: #0f172a;--muted: #64748b;--muted-2: #94a3b8}.feeding-root{flex:1;min-height:0;width:100%;display:flex;flex-direction:column;position:relative}.feeding-root .bp-prep-user{font-weight:800;color:#0369a1;background:#0ea5e933;padding:0 5px;margin-right:2px;border-radius:5px;white-space:nowrap;transition:color .2s,background .2s}.feeding-root .bp-prep-time{font-weight:800;font-variant-numeric:tabular-nums;color:#0284c7;background:linear-gradient(180deg,#f0f9ff,#e0f2fe);border:1px solid rgba(14,165,233,.35);padding:1px 7px;margin-left:2px;border-radius:6px;white-space:nowrap;box-shadow:0 1px #ffffffa6 inset;transition:color .2s,background .2s,border-color .2s}.feeding-page{position:relative;flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;color:var(--text);padding-bottom:calc(170px + env(safe-area-inset-bottom,0px))}.backdrop{position:fixed;inset:0;background:var(--bg);z-index:-1}.hero-notif-wrap{padding:0 16px 8px}.hero{padding:0;background:#fffffff5;border-bottom:1px solid rgba(226,232,240,.9)}@media(max-width:640px){.hero{padding-top:calc(26px + env(safe-area-inset-top,0px));padding-bottom:10px}}.hero-inner{max-width:1100px;margin:0 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:14px 18px}.hero-brand{min-width:0}.hero-title-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0;width:100%}.hero-title{display:flex;align-items:center;gap:12px;min-width:0;flex:1}.hero-title .emoji{font-size:36px;line-height:1;flex-shrink:0;filter:drop-shadow(0 2px 4px rgba(15,23,42,.08))}@media(max-width:640px){.hero-title .emoji{font-size:32px}}.hero-title .hero-text{min-width:0}.hero-title h1{margin:0;font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.02em;line-height:1.2}@media(max-width:640px){.hero-title h1{font-size:17px}}.hero-title .hero-userline{margin:5px 0 0;display:inline-flex;align-items:center;flex-wrap:wrap;gap:4px 6px;font-size:12.5px;color:var(--muted)}.hero-title .hero-userline i{font-size:12px;color:var(--primary);opacity:.9}.hero-title .hero-userline strong{color:var(--primary);font-weight:700;letter-spacing:.01em}.hero-title .hero-userline .hero-last-update{font-size:11px;color:#94a3b8;font-weight:400}.hero--profile-merged{background:var(--primary-soft);padding-bottom:10px;margin-bottom:8px}.hero-title--merged{align-items:flex-start}.hero-title--merged .emoji{font-size:30px}.hero-title--merged h1{font-size:18px;line-height:1.15}.hero-merged-head{display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px;min-width:0;row-gap:6px}.hero-age-chip{font-size:10.5px;font-weight:800;letter-spacing:.04em;text-transform:lowercase;color:var(--primary);background:var(--primary-soft);padding:3px 9px;border-radius:999px;border:1px solid color-mix(in srgb,var(--primary) 18%,transparent);white-space:nowrap}.hero-merged-stat{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:6px;font-size:11px;font-weight:700;color:var(--muted);background:#94a3b824;border:1px solid rgba(148,163,184,.28);white-space:nowrap;line-height:1.25}.hero-merged-stat>i{font-size:10px;opacity:.88;color:var(--muted-2)}.hero-merged-stat--weight>i{color:var(--accent);opacity:1}.hero-merged-meta{margin:5px 0 0;display:flex;flex-wrap:wrap;align-items:center;gap:2px 4px;font-size:11.5px;line-height:1.45;color:var(--muted)}.hero-merged-meta .dot{color:var(--muted-2);font-weight:700;-webkit-user-select:none;user-select:none}.hero-merged-meta i{font-size:10px;margin-right:3px;color:var(--muted-2);opacity:.95}.hero-merged-meta strong{color:var(--primary);font-weight:700}.hero-merged-sync{color:#94a3b8;font-weight:400;font-size:11px}.hero-actions--merged{flex-shrink:0}.hero-profile-menu{position:relative;flex:0 0 auto;list-style:none}.hero-profile-menu__trigger{list-style:none}.hero-profile-menu__trigger::-webkit-details-marker{display:none}.hero-profile-menu__trigger::marker{content:\"\"}.hero-profile-menu__panel{position:absolute;top:calc(100% + 6px);right:0;z-index:30;min-width:180px;padding:6px;border-radius:12px;border:1px solid var(--border);background:#fff;box-shadow:0 8px 24px -8px #0f172a2e}.hero-profile-menu__item{display:flex;align-items:center;gap:10px;width:100%;padding:10px 12px;border:0;border-radius:8px;background:transparent;font:inherit;font-size:13px;font-weight:600;color:var(--text);text-align:left;cursor:pointer;transition:background .12s ease,color .12s ease}.hero-profile-menu__item i{font-size:14px;color:var(--muted-2);width:1.1em;text-align:center}.hero-profile-menu__item:hover:not(:disabled){background:var(--primary-soft, #eef0ff);color:var(--primary)}.hero-profile-menu__item:hover:not(:disabled) i{color:var(--primary)}.hero-profile-menu__item--danger:hover:not(:disabled){color:var(--rose);background:var(--rose-soft)}.hero-profile-menu__item--danger:hover:not(:disabled) i{color:var(--rose)}.about-dialog{max-width:360px}.about-dialog__head{margin-bottom:8px}.about-dialog__title{display:flex;align-items:center;gap:8px;margin:0;font-size:18px;font-weight:700}.about-dialog__title i{color:var(--primary)}.about-dialog__meta{margin:0 0 16px;padding:0}.about-dialog__row{display:grid;grid-template-columns:96px 1fr;gap:8px 12px;padding:10px 0;border-bottom:1px solid var(--border)}.about-dialog__row:last-child{border-bottom:0}.about-dialog__row dt{margin:0;font-size:13px;font-weight:600;color:var(--muted-2)}.about-dialog__row dd{margin:0;font-size:14px;font-weight:600;color:var(--text)}.about-dialog__row dd code{font-size:13px;font-weight:600;padding:2px 8px;border-radius:6px;background:var(--primary-soft, #eef0ff);color:var(--primary)}@media(max-width:640px){.hero-title--merged .emoji{font-size:26px}.hero-merged-meta{font-size:11px}.hero-merged-stat{font-size:10.5px;padding:2px 7px}}.hero-datetime{display:flex;flex-wrap:wrap;align-items:center;flex-shrink:0}.hero-datetime-strip{display:inline-flex;align-items:stretch;flex-wrap:nowrap;max-width:100%;min-height:34px;border:1px solid var(--border);border-radius:8px;background:linear-gradient(180deg,#fff,#f1f5f9);box-shadow:0 1px 1px #0f172a0d}.hero-datetime-strip__block{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;min-width:0}.hero-datetime-strip__block>.pi{font-size:12px;color:var(--primary);opacity:.82;flex-shrink:0}.hero-datetime-strip__block--date{flex-wrap:wrap;row-gap:0}.hero-datetime-strip__wd{font-size:10px;font-weight:700;color:var(--muted);text-transform:capitalize;letter-spacing:.02em;line-height:1.15;max-width:88px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hero-datetime-strip__date{font-size:12px;font-weight:800;font-variant-numeric:tabular-nums;color:var(--text);letter-spacing:.02em;white-space:nowrap}.hero-datetime-strip__divider{align-self:stretch;width:1px;margin:5px 0;background:#94a3b866;flex-shrink:0}.hero-datetime-strip__clock{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:.04em;color:var(--primary);line-height:1;white-space:nowrap}.hero-datetime-strip__block--time{padding-right:10px}.hero-datetime-strip__block--time>.pi{font-size:11px}@media(max-width:520px){.hero-inner{flex-direction:column;align-items:stretch}.hero-datetime{width:100%;justify-content:flex-start}.hero-datetime-strip{flex:1 1 auto;width:100%;justify-content:space-between}.hero-notification__composer-row{flex-direction:column;align-items:stretch}.hero-notification__send,.hero-notification__cancel{width:100%;justify-content:center}}.hero-notification__bg-icon{position:absolute;pointer-events:none;color:var(--primary);opacity:.13;line-height:1}.hero-notification__bg-icon i{display:block}.hero-notification__bg-icon--bell{top:8%;left:6%;font-size:28px;transform:rotate(-18deg)}.hero-notification__bg-icon--megaphone{top:10%;right:8%;font-size:24px;transform:rotate(12deg)}.hero-notification__bg-icon--comments{bottom:14%;right:10%;font-size:22px;transform:rotate(-8deg)}.hero-notification__bg-icon--send{bottom:10%;left:50%;font-size:20px;transform:rotate(-22deg)}.hero-notification__bg-icon--star{bottom:16%;left:4%;font-size:18px;transform:rotate(20deg)}.hero-notification__bg-icon--bolt{top:46%;right:2%;font-size:20px;transform:rotate(-5deg)}.hero-notification__bg-icon--heart{top:38%;left:14%;font-size:17px;transform:rotate(15deg)}.hero-notification__bg-icon--info{top:4%;left:50%;font-size:18px;transform:rotate(0)}.hero-notification__bg-icon--check{bottom:24%;left:35%;font-size:17px;transform:rotate(8deg)}.hero-notification__bg-icon--eye{top:14%;left:28%;font-size:18px;transform:rotate(-10deg)}.hero-notification{flex:1 1 100%;display:flex;flex-direction:column;gap:10px;margin-top:2px;padding:10px 12px;border:1px solid rgba(148,163,184,.28);border-radius:14px;background:#fff;position:relative;overflow:hidden}.hero-notification__head{display:flex;align-items:center;justify-content:space-between;gap:10px;position:relative}.hero-notification__head-actions{display:inline-flex;align-items:center;gap:6px}.hero-notification__composer-label{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;color:var(--muted)}.hero-notification__composer-label i{color:var(--primary);font-size:12px}.hero-notification__unread-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:var(--primary);color:#fff;font-size:10px;font-weight:700;line-height:1}.hero-notification__add{width:28px;height:28px;border:1px solid rgba(var(--primary-rgb, 76, 92, 240),.25);border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.1);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0}.hero-notification__add i{font-size:11px}.hero-notification__add:hover:not(:disabled){background:var(--primary);border-color:var(--primary);color:#fff}.hero-notification__mark-all{height:26px;border:none;border-radius:0;background:transparent;color:var(--primary);font-size:11px;font-weight:600;padding:0;cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;gap:4px}.hero-notification__mark-all i{font-size:10px}.hero-notification__mark-all:hover:not(:disabled){opacity:.75}.hero-notification__mark-all:disabled{color:var(--muted-2);cursor:default}.hero-notification__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px;position:relative}.hero-notification__item{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:10px;background:#f8fafc;border:1px solid #e2e8f0;position:relative;transition:border-color .18s ease,transform .18s ease}@media(hover:hover){.hero-notification__item:hover{border-color:#c7d2fe;transform:translateY(-1px)}}.hero-notification__avatar{width:34px;height:34px;border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.12);border:1.5px solid rgba(var(--primary-rgb, 76, 92, 240),.22);color:var(--primary);font-size:11px;font-weight:700;letter-spacing:.5px;display:flex;align-items:center;justify-content:center;flex-shrink:0}.hero-notification__body{flex:1;min-width:0;padding-right:52px}.hero-notification__body-head{display:flex;align-items:center;gap:6px;margin-bottom:3px}.hero-notification__author{font-size:12px;font-weight:700;color:var(--text)}.hero-notification__content{margin:0;font-size:13.5px;line-height:1.5;color:var(--text);white-space:pre-wrap;word-break:break-word}.hero-notification__created{display:block;margin-top:4px;font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums}.hero-notification__item-actions{position:absolute;top:7px;right:8px;display:inline-flex;align-items:center;gap:4px}.hero-notification__ack-top{width:24px;height:24px;border:none;border-radius:50%;background:#eff6ff;color:#1d4ed8;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s ease,color .15s ease,transform .15s ease}.hero-notification__ack-top i{font-size:10px}.hero-notification__ack-top:active:not(:disabled){transform:scale(.96)}.hero-notification__ack-top:hover:not(:disabled){background:#dbeafe;color:#1e40af}.hero-notification__delete{width:24px;height:24px;border:none;border-radius:50%;background:transparent;color:#94a3b8;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.hero-notification__delete i{font-size:10px}.hero-notification__delete:hover:not(:disabled){background:#fee2e2;color:#b91c1c}.hero-notification__empty{display:flex;flex-direction:column;align-items:center;gap:4px;padding:16px 8px;position:relative}.hero-notification__empty-icon{font-size:28px;color:var(--primary);opacity:.45;margin-bottom:4px}.hero-notification__empty-title{font-size:13px;font-weight:600;color:var(--muted)}.hero-notification__empty-sub{font-size:11px;color:var(--muted-2);text-align:center}.hero-notification__more{align-self:flex-start;border:none;background:transparent;color:var(--primary);font-size:12px;font-weight:700;cursor:pointer;padding:0;font-family:inherit;position:relative}.hero-notification__more:hover{opacity:.75}.hero-notification__composer-row{display:flex;align-items:stretch;gap:8px;min-width:0}.hero-notification__composer-panel{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid #dbe4f3;border-radius:12px;background:#f8fbff}.hero-notification__input-wrap{flex:1;min-width:0;border-radius:11px;border:1.5px solid #cfd8e6;background:#fff;transition:border-color .15s ease;position:relative}.hero-notification__composer-row:focus-within .hero-notification__input-wrap{border-color:var(--primary)}.hero-notification__input{width:100%;min-width:0;min-height:100px;border:0;border-radius:11px;padding:10px 12px 32px;font-size:13px;line-height:1.45;color:var(--text);background:transparent;font-family:inherit;resize:vertical}.hero-notification__input:focus{outline:none}.hero-notification__char-ring{position:absolute;bottom:8px;right:10px;display:flex;align-items:center;gap:4px;pointer-events:none}.hero-notification__char-ring svg{width:22px;height:22px;transform:rotate(-90deg)}.hero-notification__char-ring-track{fill:none;stroke:#e2e8f0;stroke-width:3}.hero-notification__char-ring-fill{fill:none;stroke:var(--primary);stroke-width:3;stroke-dasharray:94 94;stroke-linecap:round;transition:stroke-dashoffset .2s ease}.hero-notification__char-count{font-size:10px;color:var(--muted-2);font-variant-numeric:tabular-nums}.hero-notification__composer-actions{display:flex;align-items:center;justify-content:flex-end;gap:8px}.hero-notification__send,.hero-notification__cancel{height:36px;border-radius:10px;min-width:86px;padding:0 14px;font-size:12px;font-weight:700}.hero-notification__send{background:var(--primary);color:#fff}.hero-notification__send:not(:disabled):hover{background:var(--primary-2)}.hero-notification__cancel{min-width:72px}.hero-notification__error{margin:0;font-size:12px;color:#b91c1c;position:relative}.hero-notification-dialog{max-width:min(520px,100vw - 24px);overflow:hidden}.hero-notification-dialog .hero-notification__composer-row{align-items:stretch;gap:10px}.hero-notification-dialog .hero-notification__input-wrap{min-height:110px}.hero-notification-dialog__head{margin-bottom:14px}.hero-notification-dialog__title-group{display:flex;align-items:flex-start;gap:10px}.hero-notification-dialog__icon-wrap{width:34px;height:34px;border-radius:10px;background:rgba(var(--primary-rgb, 76, 92, 240),.12);border:1px solid rgba(var(--primary-rgb, 76, 92, 240),.22);color:var(--primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.hero-notification-dialog__icon-wrap i{font-size:14px}.hero-notification-dialog__title{margin:0;font-size:15px;font-weight:800;color:var(--text);line-height:1.3}.hero-notification-dialog__subtitle{margin:2px 0 0;font-size:11px;color:var(--muted-2)}.hero-notification-list-dialog{max-width:min(620px,100vw - 24px)}.hero-notification-list-dialog__head{margin-bottom:10px;align-items:flex-start}.hero-notification-list-dialog__head-actions{display:inline-flex;align-items:center;gap:8px;flex-shrink:0}.hero-notification-list-dialog__title{margin:0;font-size:15px;font-weight:800;color:var(--text);line-height:1.3}.hero-notification-list-dialog__body{max-height:min(60vh,480px);overflow-y:auto;padding-right:2px}.ack-all-confirm-dialog{max-width:min(380px,100vw - 24px);text-align:center;padding:28px 24px 24px;display:flex;flex-direction:column;align-items:center;gap:10px;overflow:hidden}.ack-all-confirm-dialog__icon-wrap{width:52px;height:52px;border-radius:50%;background:rgba(var(--primary-rgb, 76, 92, 240),.1);border:1.5px solid rgba(var(--primary-rgb, 76, 92, 240),.2);color:var(--primary);display:flex;align-items:center;justify-content:center;margin-bottom:2px}.ack-all-confirm-dialog__icon-wrap i{font-size:22px}.ack-all-confirm-dialog__title{margin:0;font-size:16px;font-weight:800;color:var(--text)}.ack-all-confirm-dialog__desc{margin:0;font-size:13px;color:var(--muted);line-height:1.55;max-width:280px}.ack-all-confirm-dialog__actions{display:flex;gap:10px;margin-top:6px;width:100%;justify-content:center}.ack-all-confirm-dialog__actions .btn{min-width:96px;height:38px;border-radius:10px;font-size:13px;font-weight:700}.ack-all-confirm-dialog__confirm-btn{background:var(--primary);color:#fff;display:inline-flex;align-items:center;gap:6px}.ack-all-confirm-dialog__confirm-btn i{font-size:12px}.ack-all-confirm-dialog__confirm-btn:not(:disabled):hover{background:var(--primary-2)}.hero-actions{display:flex;gap:8px;align-items:center;flex-shrink:0;align-self:center}.content{width:100%}.content .tab-pane[hidden]{display:none!important}.content .tab-pane--feeding{max-width:1100px;margin:0 auto;padding:0 20px}.content .tab-pane--documents{max-width:none;padding:0}.content .tab-pane--weight{max-width:none;padding:0;background:linear-gradient(180deg,color-mix(in srgb,var(--primary, #5b6cff) 5%,var(--surface, #fff)) 0%,var(--surface, #fff) min(36vh,280px),var(--surface, #fff) 100%)}.content .tab-pane--mom{max-width:1100px;margin:0 auto;padding:0 20px calc(24px + env(safe-area-inset-bottom,0px))}.content .tab-pane--medical{max-width:none;padding:0;background:linear-gradient(180deg,color-mix(in srgb,var(--primary, #5b6cff) 7%,var(--surface, #fff)) 0%,var(--surface, #fff) min(42vh,320px),var(--surface, #fff) 100%)}.bottom-nav{--bn-primary: #5b6cff;--bn-primary-rgb: 91, 108, 255;--bn-inactive: #b0b7c3;--bn-height: 62px;position:fixed;left:0;right:0;bottom:0;width:100%;box-sizing:border-box;z-index:90;display:flex;align-items:center;justify-content:space-between;gap:4px;min-height:var(--bn-height);padding:0 4px env(safe-area-inset-bottom,0px);background:#fffffff5;backdrop-filter:blur(24px) saturate(200%);-webkit-backdrop-filter:blur(24px) saturate(200%);border-top:1px solid rgba(0,0,0,.055);box-shadow:0 -4px 24px -4px #0f172a14}.bottom-nav .bn-side{flex:1;display:flex;align-items:center;justify-content:space-around;min-width:0}.bottom-nav .bn-fab{flex-shrink:0;width:56px;height:56px;margin-top:-20px;border-radius:999px;border:3px solid rgba(255,255,255,.96);background:var(--bn-primary);color:#fff;font-size:22px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:transform .15s ease,background .15s ease,opacity .15s ease}.bottom-nav .bn-fab:hover:not(:disabled){background:var(--primary-2, #4c5cf0);transform:translateY(-2px)}.bottom-nav .bn-fab:active:not(:disabled){transform:translateY(0) scale(.94)}.bottom-nav .bn-fab:disabled{background:var(--bn-inactive);cursor:not-allowed;opacity:.7}.bottom-nav .bn-item{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;height:var(--bn-height);padding:0 2px;background:transparent;border:none;color:var(--bn-inactive);cursor:pointer;font-family:inherit;-webkit-tap-highlight-color:transparent;transition:color .22s ease}.bottom-nav .bn-item .bn-icon-wrap{display:flex;align-items:center;justify-content:center;width:32px;height:30px;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}.bottom-nav .bn-item .bn-icon{font-size:21px;line-height:1;transition:filter .22s ease;display:block}.bottom-nav .bn-item .bn-label{font-size:10px;font-weight:500;letter-spacing:.025em;line-height:1;transition:font-weight .22s ease}.bottom-nav .bn-item:not(.active):hover{color:rgba(var(--bn-primary-rgb),.7)}.bottom-nav .bn-item:active .bn-icon-wrap{transform:scale(.88)}.bottom-nav .bn-item.active{color:var(--bn-primary)}.bottom-nav .bn-item.active .bn-icon-wrap{transform:translateY(-3px) scale(1.15)}.bottom-nav .bn-item.active .bn-icon{filter:drop-shadow(0 2px 8px rgba(var(--bn-primary-rgb),.4))}.bottom-nav .bn-item.active .bn-label{font-weight:700}.card{background:var(--surface);border:1px solid var(--border);border-radius:16px;padding:20px;margin-bottom:16px}.card-header{margin-bottom:16px}.card-header h2{margin:0;font-size:18px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:8px}.card-header h2 i{color:var(--primary)}.card-header p{margin:6px 0 0;color:var(--muted);font-size:13px}.eyebrow{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--muted-2);letter-spacing:.06em}.eyebrow i{margin-right:4px}.form{display:flex;flex-direction:column;gap:14px}.field{display:flex;flex-direction:column;gap:6px}.field .label{font-size:12px;font-weight:600;color:var(--muted);letter-spacing:.02em;display:flex;align-items:center;gap:6px;flex-wrap:wrap}.field .label .label-hint{font-size:11px;font-weight:500;color:var(--muted-2);font-style:italic;text-transform:none;letter-spacing:0}.field input[type=text],.field input[type=date],.field input[type=time],.field input[type=number]{padding:12px 14px;border:1.5px solid var(--border);border-radius:10px;font-size:14px;font-family:inherit;color:var(--text);background:#fafbfc;width:100%;min-width:0;box-sizing:border-box;appearance:none;-webkit-appearance:none;transition:border-color .15s,background .15s;min-height:46px;font-variant-numeric:tabular-nums}.field input[type=text]:focus,.field input[type=date]:focus,.field input[type=time]:focus,.field input[type=number]:focus{outline:none;border-color:var(--primary);background:#fff}.field input[type=text]::placeholder,.field input[type=date]::placeholder,.field input[type=time]::placeholder,.field input[type=number]::placeholder{color:var(--muted-2)}.field input[type=number]{-moz-appearance:textfield}.field input[type=number]::-webkit-outer-spin-button,.field input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.radio-group{display:flex;gap:8px;flex-wrap:wrap}.chip{padding:9px 16px;border:1.5px solid var(--border);background:#fff;border-radius:999px;font-size:13px;cursor:pointer;color:var(--text);transition:all .15s;font-family:inherit}.chip:hover{border-color:var(--primary);color:var(--primary)}.chip.active{background:var(--primary);border-color:var(--primary);color:#fff}.form-actions{display:flex;gap:10px;margin-top:4px;flex-wrap:wrap}.btn{display:inline-flex;align-items:center;gap:6px;padding:10px 18px;border:none;border-radius:10px;font-size:14px;font-weight:600;font-family:inherit;cursor:pointer;transition:background .15s,color .15s,border-color .15s}.btn:disabled{opacity:.5;cursor:not-allowed}.btn.small{padding:6px 12px;font-size:12px}.btn.primary{background:var(--primary);color:#fff}.btn.primary:not(:disabled):hover{background:var(--primary-2)}.btn.ghost{background:transparent;color:var(--muted);border:1.5px solid var(--border)}.btn.ghost:hover{color:var(--text);border-color:var(--border-strong)}.btn.danger-ghost{background:transparent;color:var(--rose);border:1.5px solid var(--rose-soft)}.btn.danger-ghost:hover{background:var(--rose-soft)}.btn.icon-btn{padding:0;width:36px;height:36px;justify-content:center;background:transparent;color:var(--muted);border:1.5px solid var(--border);border-radius:10px}.btn.icon-btn i{font-size:14px}.btn.icon-btn:not(:disabled):hover{color:var(--primary);border-color:var(--primary);background:var(--primary-soft)}.btn.icon-btn .spin{animation:spin-refresh .9s linear infinite}@keyframes spin-refresh{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.age-stats{display:flex;align-items:baseline;justify-content:flex-start;gap:16px;padding:14px 16px;background:var(--primary-soft);border-radius:12px}.age-stats .stat{text-align:center}.age-stats .stat .num{font-size:26px;font-weight:700;color:var(--primary);line-height:1;font-variant-numeric:tabular-nums}.age-stats .stat .unit{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-top:3px}.age-stats .dot{color:var(--muted-2);font-size:20px}.period-card{margin-bottom:0}.period-card h2{margin:6px 0 8px;font-size:20px;font-weight:700}.period-card .period-summary{color:var(--muted);font-size:14px;margin:0 0 14px;line-height:1.55}.schedule-grid{display:grid;grid-template-columns:1fr;gap:10px}.schedule{display:flex;gap:12px;padding:12px;background:#fafbfc;border:1px solid var(--border);border-radius:12px}.schedule i{color:var(--primary);font-size:18px;margin-top:2px}.schedule .schedule-title{font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin-bottom:2px}.schedule .schedule-text{font-size:14px;color:var(--text);line-height:1.5}.compare-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}@media(max-width:768px){.compare-grid{grid-template-columns:1fr}}.day-card{margin-bottom:0;min-width:0;overflow:hidden}.day-card.today{border-color:#3b82f6;background:linear-gradient(180deg,#dbeafe,#fff 50%)}.day-card.yesterday{background:#fafbfc}.day-date-nav-wrap{position:relative;margin-bottom:12px}.day-date-nav-reset{position:absolute;top:-8px;right:-8px;z-index:1;width:24px;height:24px;border:1px solid var(--border);border-radius:50%;background:#fff;color:var(--muted);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;box-shadow:0 1px 3px #0f172a14}.day-date-nav-reset i{font-size:10px}.day-date-nav-reset:hover{background:#fee2e2;border-color:#fecaca;color:#dc2626}.day-date-nav-reset:active{background:#fee2e2;color:#dc2626}.day-date-strip{display:grid;grid-template-columns:32px 1fr 32px;gap:6px;align-items:stretch;padding:6px 8px;border-radius:10px;background:#fff;border:1px solid var(--border);touch-action:manipulation}.day-date-strip-scroller{display:flex;gap:4px;min-width:0;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;scrollbar-width:thin;padding:1px 2px}.day-date-strip-scroller::-webkit-scrollbar{height:4px}.day-date-strip-scroller::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:999px}.day-date-strip-day{flex:0 0 64px;scroll-snap-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-width:0;padding:6px 4px;border:1px solid transparent;border-radius:8px;background:#f8fafc;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.day-date-strip-day:hover{background:#eef2ff;border-color:#c7d2fe}.day-date-strip-day.active{background:#dbeafe;border-color:#3b82f6;box-shadow:inset 0 0 0 1px #3b82f626}.day-date-strip-date{font-size:12px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.2}.day-date-strip-ml{font-size:11px;font-weight:600;color:#1d4ed8;font-variant-numeric:tabular-nums;line-height:1.2}.day-date-strip-ml.empty{color:var(--muted);font-weight:500}.day-date-strip-arrow{width:32px;min-height:52px;flex-shrink:0;border:none;border-radius:8px;background:#f1f5f9;color:var(--text);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.day-date-strip-arrow i{font-size:12px}.day-date-strip-arrow:hover:not(:disabled){background:var(--primary);color:#fff}.day-date-strip-arrow:active:not(:disabled){background:var(--primary);color:#fff}.day-date-strip-arrow:disabled{opacity:.35;cursor:not-allowed}.day-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:12px}.day-head h3{margin:4px 0 0;font-size:16px;color:var(--text);font-variant-numeric:tabular-nums}.big-total{display:flex;align-items:baseline;gap:3px}.big-total .num{font-size:32px;font-weight:800;color:var(--text);line-height:1;font-variant-numeric:tabular-nums}.big-total .unit{font-size:14px;color:var(--muted);font-weight:500}.day-stats{display:flex;flex-wrap:wrap;gap:10px 16px;padding:10px 0 0;border-top:1px solid var(--border)}.day-stats>div{font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:5px}.day-stats>div i{color:var(--primary);font-size:12px}.compare-banner{margin-top:12px;padding:12px;background:var(--primary-soft);border-radius:12px;font-size:12px;color:var(--text);display:flex;flex-direction:column;gap:8px}.compare-banner strong{color:var(--primary);font-variant-numeric:tabular-nums;font-weight:700}.compare-banner .compare-row{display:flex;align-items:center;justify-content:space-between;gap:12px}.compare-banner .compare-row:not(:last-child){padding-bottom:8px;border-bottom:1px dashed rgba(15,23,42,.1)}.compare-banner .compare-stats{display:flex;align-items:center;gap:6px;flex:1}.compare-banner .compare-stats .label{color:var(--muted);font-weight:500;font-size:11px}.compare-banner .compare-stats .count{color:var(--muted-2);font-size:11px}.compare-banner .compare-change{display:flex;align-items:center;gap:4px;font-size:11px;font-weight:600;flex-shrink:0}.compare-banner .compare-change i{font-size:10px}.compare-banner .compare-change i.up{color:var(--mint)}.compare-banner .compare-change i.down{color:var(--amber)}.compare-banner .compare-change strong{font-size:12px}.compare-banner .compare-change span{color:var(--muted-2);font-weight:500}.today-logs{margin-top:12px;padding:12px;background:#fafbfc;border:1px solid var(--border);border-radius:12px}.logs-header{display:flex;align-items:center;justify-content:space-between;gap:8px;font-size:12px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px}.logs-header span{display:flex;align-items:center;gap:6px}.logs-header span:before{content:\"\\1f37c\";font-size:14px}.logs-header .logs-more{text-transform:none;letter-spacing:0;background:transparent;border:none;color:var(--primary);font-size:12px;font-weight:600;padding:4px 8px;border-radius:6px;cursor:pointer;display:inline-flex;align-items:center;gap:3px;transition:background .2s ease}.logs-header .logs-more i{font-size:10px}.logs-header .logs-more:hover{background:var(--primary-soft)}.log-list{display:flex;flex-direction:column;gap:6px;min-width:0}.log-row{display:flex;align-items:center;gap:10px;padding:8px 10px;background:#fafbfc;border-radius:8px;font-size:13px;min-width:0;max-width:100%;transition:all .2s ease;position:relative}.log-row.low-volume .log-volume{color:#f59e0b;font-weight:900}.log-row.high-volume .log-volume{color:#10b981;font-weight:900}.log-row:hover{background:#f1f5f9;transform:translateY(-1px);box-shadow:0 2px 8px #0000000d}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}.log-time{font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;min-width:42px}.log-volume{font-weight:800;color:var(--primary);font-size:16px;font-variant-numeric:tabular-nums;letter-spacing:-.01em}.log-gap{display:inline-flex;align-items:center;gap:3px;padding:2px 7px;background:#f3f4f6;color:#6b7280;border-radius:999px;font-size:10.5px;font-weight:600;white-space:nowrap;flex-shrink:0;font-variant-numeric:tabular-nums;transition:all .2s ease}.log-gap i{font-size:9px;opacity:.7}.log-gap.feed-gap-warn{background:linear-gradient(135deg,#f59e0b,#ea580c);color:#fff;font-weight:700;border:1px solid rgba(234,88,12,.45);box-shadow:0 0 0 1px #fff3 inset,0 2px 8px #ea580c59}.log-gap.feed-gap-warn i{opacity:.95;color:inherit}.log-note{color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.log-actions{margin-left:auto;display:inline-flex;align-items:center;gap:2px}.log-edit,.log-del{background:transparent;border:none;color:var(--muted-2);cursor:pointer;padding:4px 6px;border-radius:6px;font-size:12px;transition:all .2s ease}.log-edit:hover{color:var(--primary);background:var(--primary-soft)}.log-del:hover{color:var(--rose);background:var(--rose-soft)}.empty-mini{padding:12px;text-align:center;color:var(--muted-2);font-size:13px;font-style:italic}.countdown-hero{display:flex;flex-direction:column;gap:16px;padding:18px 20px;background:#fff;border-radius:16px;border:1px solid #e6e9ff;transition:all .3s ease;margin-bottom:20px}.countdown-hero .hero-main{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:20px}.countdown-hero .feeding-time-card{flex:1;min-width:0;text-align:center}.countdown-hero .feeding-time-card .time-header{margin-bottom:12px;display:flex;justify-content:center}.countdown-hero .feeding-time-card .time-header .status-badge{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;padding:6px 12px;border-radius:14px;white-space:nowrap}.countdown-hero .feeding-time-card .time-header .status-badge i{font-size:11px}.countdown-hero .feeding-time-card .time-header .status-badge.status-waiting{background:var(--primary-soft);color:var(--primary)}.countdown-hero .feeding-time-card .time-header .status-badge.status-now{background:#fee2e2;color:#dc2626;animation:pulse-gentle 2s ease-in-out infinite;font-size:11px;text-transform:none;font-weight:700}.countdown-hero .feeding-time-card .time-header .status-badge.status-late{background:var(--rose-soft);color:var(--rose)}.countdown-hero .feeding-time-card .time-display .predicted-time{font-size:42px;font-weight:800;line-height:1;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.02em;margin-bottom:4px}.countdown-hero .feeding-time-card .time-display .time-remaining{font-size:15px;font-weight:500;color:var(--muted);font-variant-numeric:tabular-nums}.countdown-hero .countdown-next{display:flex;flex-direction:column;gap:8px;padding-left:16px;border-left:1px dashed #d8dcff;flex-shrink:0;min-width:0}.countdown-hero .next-item{display:flex;align-items:center;gap:6px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.countdown-hero .next-item i{color:var(--primary);font-size:13px}.countdown-hero .next-item strong{font-weight:700}.countdown-hero .next-item .predict-label,.countdown-hero .next-item .recommend-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-2);margin-left:4px}.countdown-hero .next-item .recommend-label{color:var(--mint)}.countdown-hero .volume-info{display:flex;flex-direction:column;gap:8px;padding-left:20px;border-left:1px dashed #d8dcff;flex-shrink:0;min-width:160px;transition:all .3s ease}.countdown-hero .volume-info .volume-row{display:flex;align-items:center;justify-content:space-between;gap:12px}.countdown-hero .volume-info .volume-row .volume-prefix{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted-2);flex-shrink:0}.countdown-hero .volume-info .volume-row .volume-amount{font-size:22px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;line-height:1;text-align:right}.countdown-hero .volume-info .volume-row.predicted-row .volume-prefix,.countdown-hero .volume-info .volume-row.predicted-row .volume-amount{color:var(--primary)}.countdown-hero .volume-info .volume-row.recommended-row .volume-prefix,.countdown-hero .volume-info .volume-row.recommended-row .volume-amount{color:var(--mint)}.countdown-hero[data-status=waiting]{border-color:#bbf7d0;background:linear-gradient(135deg,#f7fef8,#f0fdf4)}.countdown-hero[data-status=waiting] .feeding-time-card .time-display .predicted-time{color:#16a34a}.countdown-hero[data-status=waiting] .feeding-time-card .time-display .time-remaining{color:#15803d}.countdown-hero[data-status=waiting] .feeding-time-card .status-badge.status-waiting{background:#dcfce7!important;color:#15803d!important;border:1px solid #86efac}.countdown-hero[data-status=waiting] .volume-info .volume-amount{color:#16a34a}.countdown-hero[data-status=waiting] .volume-info .volume-prefix{color:#15803d}.countdown-hero[data-status=late]{border-color:#fca5a5;background:linear-gradient(135deg,#fef2f2,#fee2e2)}.countdown-hero[data-status=late] .feeding-time-card .time-display .predicted-time{color:#dc2626}.countdown-hero[data-status=late] .feeding-time-card .time-display .time-remaining{color:#b91c1c}.countdown-hero[data-status=late] .feeding-time-card .status-badge.status-late{background:#fee2e2;color:#dc2626;border:1px solid #fca5a5}.countdown-hero[data-status=late] .volume-info .volume-amount{color:#dc2626}.countdown-hero[data-status=late] .volume-info .volume-prefix{color:#b91c1c}.countdown-hero[data-status=now]{border-color:#fbbf24;background:linear-gradient(135deg,#fefce8,#fef3c7);animation:pulse-card 2s ease-in-out infinite}.countdown-hero[data-status=now] .feeding-time-card .time-display .predicted-time{color:#92400e}.countdown-hero[data-status=now] .feeding-time-card .time-display .time-remaining{color:#a16207}.countdown-hero[data-status=now] .feeding-time-card .status-badge.status-now{background:#fef3c7!important;color:#b45309!important;border:1px solid #f59e0b!important}.countdown-hero[data-status=now] .volume-info .volume-amount{color:#92400e}.countdown-hero[data-status=now] .volume-info .volume-prefix{color:#a16207}@media(max-width:540px){.countdown-hero .hero-main{flex-direction:column;align-items:stretch;gap:12px}.countdown-hero .hero-main .volume-info{border-left:none;border-top:1px dashed #d8dcff;padding-left:0;padding-top:12px;min-width:auto}.countdown-hero .hero-main .volume-info .volume-row{justify-content:space-between;padding:0 4px}.countdown-hero .hero-main .feeding-time-card .time-display .predicted-time{font-size:36px}.countdown-hero .hero-main .feeding-time-card .volume-info .volume-amount{font-size:20px}}@media(max-width:400px){.countdown-hero .feeding-time-card .status-badge{font-size:10px;padding:4px 10px}.countdown-hero .feeding-time-card .time-display .predicted-time{font-size:32px}.countdown-hero .volume-info .volume-amount{font-size:18px}}@keyframes pulse-soft{0%,to{opacity:1}50%{opacity:.65}}@keyframes pulse-gentle{0%,to{opacity:1}50%{opacity:.75}}@keyframes pulse-urgent{0%,to{opacity:1;text-shadow:0 0 0 rgba(239,68,68,0)}50%{opacity:.8;text-shadow:0 0 8px rgba(239,68,68,.25)}}@keyframes pulse-card{0%,to{transform:scale(1);box-shadow:0 1px 3px #0000001a,0 0 #f8717100}50%{transform:scale(1.02);box-shadow:0 4px 12px #00000026,0 0 0 2px #f871714d}}.burp-warning{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;margin:0 0 16px;background:linear-gradient(135deg,#fef3c7,#fde68a);border:1px solid #f59e0b;border-radius:14px;box-shadow:0 2px 8px #f59e0b33;animation:burp-pulse 2s ease-in-out infinite}.burp-warning__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:40px;height:40px;background:#f59e0b;border-radius:50%;color:#fff;font-size:18px;animation:burp-icon-bounce 1.5s ease-in-out infinite}.burp-warning__content{flex:1;min-width:0}.burp-warning__title{font-size:15px;font-weight:700;color:#92400e;margin-bottom:4px}.burp-warning__text{font-size:13px;color:#78350f;line-height:1.5;margin-bottom:8px}.burp-warning__text strong{font-weight:600;color:#92400e}.burp-warning__countdown{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;background:#ffffffb3;border-radius:8px;font-size:13px;color:#92400e;font-weight:500}.burp-warning__countdown i{font-size:14px;color:#f59e0b}.burp-warning__countdown strong{font-size:16px;font-weight:700;color:#d97706}@keyframes burp-pulse{0%,to{box-shadow:0 2px 8px #f59e0b33}50%{box-shadow:0 4px 16px #f59e0b59}}@keyframes burp-icon-bounce{0%,to{transform:scale(1)}50%{transform:scale(1.1)}}.countdown-progress{margin-top:10px}.countdown-progress .cp-track{position:relative;height:6px;background:#ffffffbf;border-radius:999px;overflow:hidden}.countdown-progress .cp-fill{height:100%;background:linear-gradient(90deg,var(--primary),var(--accent));border-radius:999px;transition:width .4s ease}.countdown-progress .cp-fill[data-status=waiting]{background:linear-gradient(90deg,#22c55e,#16a34a)}.countdown-progress .cp-fill[data-status=late]{background:linear-gradient(90deg,#f87171,#dc2626)}.countdown-progress .cp-fill[data-status=now]{background:linear-gradient(90deg,#fbbf24,#d97706)}.countdown-progress .cp-labels{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:6px;font-size:11.5px;color:var(--muted)}.countdown-progress .cp-labels i{font-size:10px;margin-right:2px;color:var(--muted-2)}.countdown-progress .cp-labels .muted{color:var(--muted-2)}.countdown-progress .cp-labels .cp-right{font-weight:600;color:var(--muted);white-space:nowrap}.predict-head{display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:12px;margin-bottom:16px}.predict-head .eyebrow{color:var(--primary);display:flex;align-items:center;gap:4px}.predict-head .eyebrow.sparkle i{animation:sparkle 2s ease-in-out infinite}.predict-head h2{margin:4px 0 0;font-size:20px;font-weight:700}.last-feed{display:flex;align-items:center;gap:12px;padding:12px 14px;background:#fff;border-radius:12px;margin-bottom:14px;border:1px solid #e8e9ff}.last-feed .last-feed-icon{width:38px;height:38px;border-radius:50%;background:var(--primary-soft);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.last-feed .last-feed-icon i{color:var(--primary);font-size:16px}.last-feed .last-feed-body{flex:1;min-width:0}.last-feed .last-feed-label{font-size:10px;font-weight:700;text-transform:uppercase;color:var(--muted-2);letter-spacing:.06em;margin-bottom:2px}.last-feed .last-feed-value{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.last-feed .last-feed-value strong{color:var(--primary);font-size:18px;font-weight:800}.last-feed .last-feed-value .sep{color:var(--muted-2)}.last-feed .last-feed-value .ago{color:var(--accent);font-weight:600;font-size:13px}.last-feed .last-feed-note{margin-top:4px;font-size:12px;color:var(--muted);font-style:italic;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.predict-empty{padding:14px 16px;background:#fff;border-radius:12px;color:var(--muted);font-size:13px;display:flex;align-items:center;gap:8px}.predict-empty i{color:var(--primary)}.predict-body{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:14px}@media(max-width:640px){.predict-body{grid-template-columns:1fr}}.predict-metric{background:#fff;border-radius:12px;padding:14px;text-align:center}.predict-metric .metric-label{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-bottom:6px;display:flex;align-items:center;justify-content:center;gap:5px}.predict-metric .metric-label i{color:var(--primary);font-size:12px}.predict-metric .metric-value{font-size:28px;font-weight:800;line-height:1;color:var(--primary);font-variant-numeric:tabular-nums}.predict-metric .metric-value .ml-unit{font-size:14px;color:var(--muted);font-weight:500;margin-left:2px}.predict-metric .metric-sub{margin-top:6px;font-size:12px;color:var(--muted)}.reasoning{background:#fff;border-radius:12px;padding:12px 14px;margin-bottom:12px}.reasoning .reasoning-head{font-size:11px;font-weight:700;text-transform:uppercase;color:var(--muted);letter-spacing:.05em;margin-bottom:6px}.reasoning .reasoning-head i{color:var(--primary);margin-right:4px}.reasoning ul{margin:0;padding-left:18px;list-style:disc}.reasoning li{font-size:13px;color:var(--text);line-height:1.55;margin:2px 0}.predict-actions{display:flex;justify-content:flex-end}.feed-list-card{margin-bottom:16px}.feed-list-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:12px}.feed-list-head h2{margin:4px 0 0;font-size:18px;font-weight:700}.feed-list-compact{display:flex;flex-direction:column;gap:6px}.feed-row{display:grid;grid-template-columns:68px 80px 1fr auto;gap:10px;align-items:center;padding:10px 12px;transition:all .2s ease;position:relative}.feed-row.low-volume .feed-row-volume strong{color:#f59e0b;font-weight:900}.feed-row.high-volume .feed-row-volume strong{color:#10b981;font-weight:900}.feed-row{background:#fafbfc;border-radius:10px;border:1px solid var(--border)}.feed-row .feed-row-time{display:flex;flex-direction:column;line-height:1.2;font-variant-numeric:tabular-nums;gap:3px}.feed-row .feed-row-time .time{font-weight:700;color:var(--text);font-size:14px}.feed-row .feed-row-time .date{font-size:11px;color:var(--muted-2)}.feed-row .feed-row-time .feed-row-gap{display:inline-flex;align-items:center;gap:3px;font-size:10.5px;font-weight:600;color:#6b7280;background:#f3f4f6;padding:1px 6px;border-radius:999px;width:fit-content;white-space:nowrap;font-variant-numeric:tabular-nums}.feed-row .feed-row-time .feed-row-gap i{font-size:8px;opacity:.7}.feed-row .feed-row-time .feed-row-gap.feed-gap-warn{background:linear-gradient(135deg,#f59e0b,#ea580c);color:#fff;font-weight:700;border:1px solid rgba(234,88,12,.45);box-shadow:0 0 0 1px #fff3 inset,0 2px 8px #ea580c59}.feed-row .feed-row-time .feed-row-gap.feed-gap-warn i{opacity:.95;color:inherit}.feed-row .feed-row-volume{font-variant-numeric:tabular-nums}.feed-row .feed-row-volume strong{color:var(--primary);font-size:19px;font-weight:800;letter-spacing:-.01em}.feed-row .feed-row-volume .u{font-size:11px;color:var(--muted);margin-left:2px}.feed-row .feed-row-note{font-size:13px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.feed-row .feed-row-note.muted{color:var(--muted-2);font-style:italic}.feed-row .feed-row-actions{display:inline-flex;align-items:center;gap:2px;margin-left:auto}.feed-row .feed-row-edit,.feed-row .feed-row-del{background:transparent;border:none;color:var(--muted-2);cursor:pointer;padding:6px 8px;border-radius:6px;font-size:13px}.feed-row .feed-row-edit:hover{color:var(--primary, #5b6cff);background:#5b6cff1a}.feed-row .feed-row-del:hover{color:var(--rose);background:var(--rose-soft)}@media(max-width:480px){.feed-row{grid-template-columns:58px 70px 1fr auto;gap:8px;padding:8px 10px}.feed-row .feed-row-time .time{font-size:13px}}.dialog-wide{max-width:720px;display:flex;flex-direction:column;padding:0;overflow:hidden}@media(max-width:640px){.dialog-wide{max-height:calc(100dvh - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px) - 72px);border-radius:14px}}.dialog-wide .dialog-head{position:sticky;top:0;z-index:5;background:var(--surface);padding:16px 20px;margin:0;border-bottom:1px solid var(--border);-webkit-backdrop-filter:saturate(1.2) blur(6px);backdrop-filter:saturate(1.2) blur(6px)}@media(max-width:640px){.dialog-wide .dialog-head{padding:12px 14px}}.dialog-wide .dialog-close{width:40px;height:40px;font-size:16px;background:#f1f3f7;color:var(--text)}.dialog-wide .dialog-close:hover{background:var(--rose-soft);color:var(--rose)}.dialog-wide .history-body,.dialog-wide .tips-dialog-body{padding:18px 20px 24px;overflow-y:auto;flex:1;min-height:0}@media(max-width:640px){.dialog-wide .history-body,.dialog-wide .tips-dialog-body{padding:14px 14px 20px}}.history-body{display:flex;flex-direction:column;gap:18px}.history-paging-hint{margin:0;font-size:12px;line-height:1.45}.history-load-more{display:grid;justify-items:center;width:100%;box-sizing:border-box;padding:8px 0 12px}.history-load-more .btn{width:auto;max-width:min(320px,100%);min-width:0;margin-inline:auto;justify-content:center}.tips-nav{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px;background:#f1f3f7;border-radius:12px;margin-bottom:16px}.nav-arrow{width:40px;height:40px;border-radius:50%;border:none;background:#fff;color:var(--primary);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:16px;transition:all .15s;flex-shrink:0}.nav-arrow:hover:not(:disabled){background:var(--primary);color:#fff;transform:scale(1.05)}.nav-arrow:active:not(:disabled){transform:scale(.95)}.nav-arrow:disabled{opacity:.35;cursor:not-allowed}.tips-now-btn{flex:1;padding:9px 16px;border:none;background:transparent;border-radius:999px;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer;font-family:inherit;display:inline-flex;align-items:center;justify-content:center;gap:6px;transition:all .15s}.tips-now-btn i{font-size:12px}.tips-now-btn:hover{color:var(--primary);background:#fff}.tips-now-btn.active{background:var(--primary);color:#fff;pointer-events:none}.tips-dialog-body .period-summary{font-size:14px;color:var(--muted);line-height:1.6;margin:0 0 14px}.tips-dialog-body .schedule-grid{grid-template-columns:repeat(2,1fr);margin-bottom:16px}@media(max-width:560px){.tips-dialog-body .schedule-grid{grid-template-columns:1fr}}.dialog-tips-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.history-group .history-group-head{display:flex;justify-content:space-between;align-items:center;padding:10px 12px;background:var(--primary-soft);border-radius:10px;margin-bottom:8px}.history-group .history-group-head .h-date{font-size:14px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums}.history-group .history-group-head .h-day{font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.05em}.history-group .history-group-head .h-total{font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}.history-group .history-group-head .h-total strong{color:var(--primary);font-size:20px;font-weight:800}.history-group .history-group-head .h-total .h-count{color:var(--muted);font-size:12px;font-weight:500;margin-left:4px}.history-group .history-group-head .h-total .h-avg{color:var(--primary);font-size:12px;font-weight:600;margin-left:4px;font-variant-numeric:tabular-nums}.history-group .history-group-rows{display:flex;flex-direction:column;gap:4px}.tips-section-head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px;padding:4px 4px 0}.tips-section-head .eyebrow i{margin-right:4px}.tips-section-head h2{margin:4px 0 0;font-size:20px;font-weight:700;color:var(--text)}.filter-bar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}.filter-chip{padding:7px 14px;border:1.5px solid var(--border);background:#fff;border-radius:999px;font-size:13px;font-weight:500;cursor:pointer;color:var(--muted);display:inline-flex;align-items:center;gap:5px;transition:all .15s;font-family:inherit}.filter-chip i{font-size:12px}.filter-chip:hover{border-color:var(--cat-color, var(--primary));color:var(--cat-color, var(--primary))}.filter-chip.active{background:var(--cat-color, var(--primary));border-color:var(--cat-color, var(--primary));color:#fff}.tips-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;margin-bottom:20px}.tip-card{background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--cat-color, var(--primary));border-radius:12px;padding:16px;transition:transform .15s}.tip-card:hover{transform:translateY(-2px)}.tip-card .tip-head{margin-bottom:8px}.tip-card .tip-pill{display:inline-flex;align-items:center;gap:5px;padding:3px 10px;background:var(--cat-color, var(--primary));color:#fff;font-size:11px;font-weight:600;border-radius:999px;text-transform:uppercase;letter-spacing:.04em}.tip-card .tip-pill i{font-size:10px}.tip-card .tip-title{margin:6px 0 8px;font-size:15px;font-weight:700;line-height:1.35;color:var(--text)}.tip-card .tip-body{margin:0;font-size:13px;line-height:1.55;color:var(--muted)}.empty{grid-column:1/-1;padding:40px 20px;text-align:center;color:var(--muted-2)}.empty i{font-size:32px;margin-bottom:8px;display:block}.upcoming{margin-bottom:24px}.upcoming h3{margin:0 0 12px;font-size:16px;font-weight:600;color:var(--text);display:flex;align-items:center;gap:6px}.upcoming h3 i{color:var(--primary)}.upcoming-grid{display:flex;gap:8px;flex-wrap:wrap}.upcoming-item{padding:10px 14px;background:var(--surface);border:1px solid var(--border);border-radius:10px;font-size:13px;color:var(--muted);display:inline-flex;align-items:center;gap:6px}.upcoming-item i{color:var(--primary);font-size:12px}.disclaimer{padding:16px;background:var(--amber-soft);border-radius:12px;color:#78350f;font-size:13px;line-height:1.5;margin-bottom:24px;display:flex;gap:8px;align-items:flex-start}.disclaimer i{color:var(--amber);margin-top:2px}.toast{position:fixed;bottom:100px;left:50%;transform:translate(-50%);z-index:90;padding:12px 18px;border-radius:12px;font-size:14px;font-weight:500;box-shadow:0 6px 24px #0f172a1f;display:flex;align-items:center;gap:8px;animation:toastIn .3s cubic-bezier(.4,0,.2,1)}.toast.success{background:var(--mint);color:#fff}.toast.error{background:var(--rose);color:#fff}@keyframes toastIn{0%{transform:translate(-50%,20px);opacity:0}to{transform:translate(-50%);opacity:1}}.fab{position:fixed;bottom:calc(80px + env(safe-area-inset-bottom,0px));right:20px;z-index:96;display:inline-flex;align-items:center;gap:10px;padding:14px 22px 14px 18px;background:var(--primary);color:#fff;border:none;border-radius:999px;font-size:15px;font-weight:700;font-family:inherit;cursor:pointer;box-shadow:0 8px 24px #5b6cff73;transition:transform .15s,box-shadow .15s,background .15s}.fab i{font-size:18px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;background:#ffffff2e}.fab .fab-label{white-space:nowrap}.fab:hover{background:var(--primary-2);transform:translateY(-2px);box-shadow:0 12px 28px #5b6cff8c}.fab:active{transform:translateY(0)}@media(max-width:480px){.fab{padding:14px}.fab .fab-label{display:none}.fab i{font-size:22px;width:28px;height:28px}}.dialog-overlay{position:fixed;inset:0;background:#0f172a8c;z-index:110;display:flex;align-items:center;justify-content:center;padding:20px;animation:overlayIn .2s ease-out}.dialog-overlay.dialog-overlay--front{z-index:400}.dialog-overlay.dialog-overlay--event-reminder{z-index:410}@media(max-width:640px){.dialog-overlay{padding:calc(env(safe-area-inset-top,0px) + 16px) 12px calc(env(safe-area-inset-bottom,0px) + 16px);align-items:flex-start}}@keyframes overlayIn{0%{opacity:0}to{opacity:1}}.dialog{background:var(--surface);border-radius:20px;width:100%;max-width:560px;max-height:min(100vh - 40px,100dvh - 40px);overflow-y:auto;padding:24px;animation:dialogIn .25s cubic-bezier(.4,0,.2,1);box-shadow:0 20px 60px #0f172a40}@media(max-width:640px){.dialog{max-height:calc(100dvh - env(safe-area-inset-top,0px) - env(safe-area-inset-bottom,0px) - 32px);border-radius:16px}}@keyframes dialogIn{0%{opacity:0;transform:translateY(20px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.dialog-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:18px}.dialog-head h2{margin:4px 0 0;font-size:20px;font-weight:700;color:var(--text);display:flex;align-items:center;gap:8px}.dialog-head h2 i{color:var(--primary)}.dialog-close{background:#f1f3f7;border:none;width:36px;height:36px;border-radius:50%;cursor:pointer;color:var(--muted);font-size:14px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;transition:background .15s,color .15s}.dialog-close:hover{background:var(--rose-soft);color:var(--rose)}.log-form{display:flex;flex-direction:column;gap:14px}.log-volume-field{margin:0}.log-volume-field .log-volume-input-row{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px 10px;min-width:0}.log-volume-field .log-volume-input-row>input[type=number]{flex:0 0 118px;width:118px;max-width:min(118px,100%);min-width:0}.log-volume-field .predict-hint--inline{flex:1 1 auto;min-width:0;margin:0;padding:6px 10px;gap:6px;font-size:12px;border-radius:8px}.log-volume-field .predict-hint--inline>i{font-size:13px;flex-shrink:0}.log-volume-field .predict-hint--inline .hint-text{flex:1 1 auto;min-width:0;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.log-volume-field .predict-hint--inline .btn.small{flex-shrink:0;padding:4px 8px;font-size:11px}@media(max-width:400px){.log-volume-field .log-volume-input-row>input[type=number]{flex:1 1 100px;width:100%;max-width:none}.log-volume-field .predict-hint--inline{flex:1 1 100%;white-space:normal}.log-volume-field .predict-hint--inline .hint-text{white-space:normal;overflow:visible;text-overflow:unset}}.edit-date-banner{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:10px 14px;background:linear-gradient(135deg,#eef2ff,#f5f3ff);border:1px solid #dbe1ff;border-radius:12px;font-size:13px;color:var(--text)}.edit-date-banner>i.pi-calendar{color:var(--primary, #5b6cff);font-size:15px}.edit-date-banner .edb-label{color:var(--muted, #6b7280);font-weight:500}.edit-date-banner .edb-value{font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;letter-spacing:-.01em}.edit-date-banner .edb-lock{margin-left:auto;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;flex-shrink:0;border-radius:50%;background:#ffffffe0;border:1px solid #e2e8f0;color:var(--muted, #64748b)}.edit-date-banner .edb-lock i{font-size:14px;line-height:1}.log-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.log-grid .field.full{grid-column:1/-1}.log-grid.log-grid--date-time{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:560px){.log-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:380px){.log-grid{grid-template-columns:1fr}}.quick-volumes{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.quick-volumes .quick-label{font-size:12px;color:var(--muted);font-weight:600;margin-right:4px}.quick-chip{padding:7px 13px;background:#f1f3f7;border:none;border-radius:999px;font-size:12px;font-weight:600;cursor:pointer;color:var(--muted);transition:all .15s;font-family:inherit}.quick-chip:hover{background:var(--primary-soft);color:var(--primary)}.quick-chip.now-chip{background:var(--primary-soft);color:var(--primary);display:inline-flex;align-items:center;gap:4px}.quick-chip.now-chip:hover{background:var(--primary);color:#fff}.quick-chip.formula-chip{display:inline-flex;align-items:center;gap:5px;background:#fff7ed;color:#c2410c;border:1px solid #fed7aa}.quick-chip.formula-chip i{font-size:11px;opacity:.9}.quick-chip.formula-chip:hover{background:#ffedd5;color:#9a3412;border-color:#fdba74}.quick-chip.formula-chip.active{background:#c2410c;color:#fff;border-color:#c2410c;box-shadow:0 2px 8px #c2410c40}.quick-chip.formula-chip.active:hover{background:#9a3412;border-color:#9a3412;color:#fff}.bottle-prep{background:#f0f9ff;border:1px solid #bae6fd;border-radius:12px;padding:8px 12px;margin-bottom:16px;display:flex;flex-direction:column;gap:8px;transition:background .2s,border-color .2s}.bottle-prep:has(.bp-warning){background:#fffbeb;border-color:#fde68a}.bottle-prep:has(.bp-warning) .bp-info>i{color:#f59e0b}.bottle-prep:has(.bp-warning) .bp-info strong{color:#d97706}.bottle-prep:has(.bp-warning) .bp-prep-user{color:#92400e;background:#fbbf246b}.bottle-prep:has(.bp-warning) .bp-prep-time{color:#c2410c;background:linear-gradient(180deg,#fff7ed,#ffedd5);border-color:#fb923c73}.bottle-prep:has(.bp-form){align-items:stretch;padding:10px 12px 12px}.bottle-prep .bp-warning{display:flex;align-items:center;justify-content:space-between;gap:10px;animation:slideDown .2s ease;flex-wrap:wrap}.bottle-prep .bp-warning__content{display:flex;align-items:center;gap:8px;font-size:13px;flex:1;min-width:0}.bottle-prep .bp-warning__content i{font-size:16px;flex-shrink:0}.bottle-prep .bp-warning__content strong{font-weight:700}.bottle-prep .bp-warning--expired{background:#fef2f2;border:1px solid #fecaca;border-radius:8px;padding:8px 10px;color:#991b1b}.bottle-prep .bp-warning--expired i{color:#dc2626}.bottle-prep .bp-warning--soon{background:#fefce8;border:1px solid #fde68a;border-radius:8px;padding:8px 10px;color:#92400e}.bottle-prep .bp-warning--soon i{color:#f59e0b}.bottle-prep .bp-warning__btn{flex-shrink:0;display:inline-flex;align-items:center;gap:5px;padding:7px 12px;font-size:12px;font-weight:700;font-family:inherit;color:#fff;background:linear-gradient(180deg,#f59e0b,#d97706);border:none;border-radius:8px;cursor:pointer;box-shadow:0 2px 4px #f59e0b40;transition:all .15s ease}.bottle-prep .bp-warning__btn i{font-size:12px}.bottle-prep .bp-warning__btn:hover{background:linear-gradient(180deg,#fbbf24,#f59e0b);transform:translateY(-1px);box-shadow:0 4px 8px #f59e0b59}.bottle-prep .bp-warning__btn:active{transform:translateY(0)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.bottle-prep .bp-info-row{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%}.bottle-prep:not(:has(.bp-warning)):not(:has(.bp-form)){flex-direction:row;align-items:center;justify-content:space-between;flex-wrap:wrap}.bottle-prep .bp-info{display:flex;align-items:flex-start;gap:8px;font-size:14px;color:var(--text);flex:1;min-width:0}.bottle-prep .bp-info>i{color:#0ea5e9;font-size:16px;margin-top:2px;flex-shrink:0}.bottle-prep .bp-info .bp-text{line-height:1.45;min-width:0}.bottle-prep .bp-info .bp-useby{display:inline-block;margin-top:2px;font-size:13px}.bottle-prep .bp-info strong{color:#0284c7;font-weight:800;font-variant-numeric:tabular-nums}.bottle-prep .bp-info .muted{color:var(--muted);font-size:13px}.bottle-prep .bp-actions{display:flex;gap:4px}.bottle-prep .bp-add{flex:1;background:transparent;border:none;padding:6px 4px;font-size:13px;font-weight:600;color:#0284c7;cursor:pointer;display:flex;align-items:center;gap:8px;font-family:inherit;text-align:left}.bottle-prep .bp-add>i{font-size:15px}.bottle-prep .bp-add:hover{color:#0369a1}.bottle-prep .bp-form{display:flex;flex-direction:column;gap:8px;width:100%}.bottle-prep .bp-form-head{display:flex;align-items:center;gap:6px}.bottle-prep .bp-form-head>i{color:#0ea5e9;font-size:15px}.bottle-prep .bp-form-head .bp-label{font-size:13px;color:var(--muted);font-weight:600;white-space:nowrap}.bottle-prep .bp-input-wrap{display:flex;align-items:center;gap:6px;background:#fff;border:1px solid #7dd3fc;border-radius:10px;padding:3px;transition:border-color .15s,box-shadow .15s}.bottle-prep .bp-input-wrap:focus-within{border-color:#0ea5e9;box-shadow:0 0 0 3px #0ea5e926}.bottle-prep .bp-input-wrap .bp-step{width:30px;height:30px;flex-shrink:0;border-radius:8px;border:none;background:#e0f2fe;color:#0369a1;font-size:12px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-family:inherit;transition:all .12s}.bottle-prep .bp-input-wrap .bp-step:hover{background:#bae6fd;color:#0284c7}.bottle-prep .bp-input-wrap .bp-step:active{transform:scale(.94)}.bottle-prep .bp-input-wrap .bp-step:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.bottle-prep .bp-input-wrap .bp-input{flex:1;min-width:60px;padding:4px 6px;font-size:18px;font-weight:800;border:none;background:transparent;font-variant-numeric:tabular-nums;font-family:inherit;color:#d97706;text-align:center;letter-spacing:-.01em}.bottle-prep .bp-input-wrap .bp-input:focus{outline:none}.bottle-prep .bp-input-wrap .bp-input:disabled{opacity:.55;cursor:not-allowed}.bottle-prep .bp-input-wrap .bp-unit{font-size:12px;color:var(--muted);font-weight:600;padding-right:4px}.bottle-prep .bp-quick{display:flex;flex-wrap:wrap;align-items:center;gap:5px}.bottle-prep .bp-quick .bp-quick-label{font-size:11px;color:var(--muted);font-weight:600;margin-right:2px}.bottle-prep .bp-quick .bp-quick-chip{padding:4px 9px;background:#f0f9ff;border:1px solid #7dd3fc;border-radius:999px;font-size:11.5px;font-weight:700;color:#0369a1;cursor:pointer;font-family:inherit;font-variant-numeric:tabular-nums;transition:all .12s}.bottle-prep .bp-quick .bp-quick-chip:hover{background:#e0f2fe;border-color:#38bdf8;color:#0284c7}.bottle-prep .bp-quick .bp-quick-chip:active{transform:scale(.95)}.bottle-prep .bp-quick .bp-quick-chip:disabled{opacity:.45;cursor:not-allowed}.bottle-prep .bp-form-actions{display:flex;gap:6px;justify-content:flex-end}.bottle-prep .bp-btn{width:32px;height:32px;border-radius:8px;border:none;background:#fff;color:var(--muted);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-size:12px;transition:all .15s;flex-shrink:0}.bottle-prep .bp-btn:hover:not(:disabled){background:#e0f2fe;color:#0284c7}.bottle-prep .bp-btn:disabled{opacity:.45;cursor:not-allowed}.bottle-prep .bp-btn.primary{background:#0ea5e9;color:#fff}.bottle-prep .bp-btn.primary:hover:not(:disabled){background:#0284c7}.bottle-prep .bp-btn.danger:hover{background:var(--rose-soft);color:var(--rose)}.calc-block{border:1px solid #fde7c2;background:#fffaf0;border-radius:12px;overflow:hidden}.calc-block .calc-head{padding:10px 14px 0}.calc-block .prep-info{display:flex;align-items:flex-start;gap:6px;font-size:13px;color:var(--text)}.calc-block .prep-info>i{color:#f59e0b;font-size:14px;margin-top:2px;flex-shrink:0}.calc-block .prep-info .prep-info-text{line-height:1.45;min-width:0}.calc-block .prep-info strong{color:#d97706;font-weight:800;font-variant-numeric:tabular-nums}.calc-block .prep-info .muted{color:var(--muted-2);font-size:12px;display:inline-block;margin-top:2px}.calc-block .calc-body{padding:8px 14px 14px;display:flex;flex-direction:column;gap:10px}.calc-block .field.mini.remaining-input{position:relative;margin:0;display:flex;flex-direction:column}.calc-block .field.mini.remaining-input .label{font-size:11px;font-weight:600;color:var(--muted);margin-bottom:4px}.calc-block .field.mini.remaining-input input{width:100%;padding:10px 36px 10px 12px;font-size:16px;font-weight:700;border:1px solid #fadf9e;border-radius:8px;background:#fff;font-variant-numeric:tabular-nums;font-family:inherit;color:#d97706}.calc-block .field.mini.remaining-input input:focus{outline:none;border-color:#f59e0b;box-shadow:0 0 0 3px #f59e0b26}.calc-block .field.mini.remaining-input .suffix{position:absolute;right:12px;top:50%;transform:translateY(4px);font-size:12px;color:var(--muted-2);pointer-events:none}.calc-block .calc-result-row{display:flex;align-items:center;justify-content:space-between;gap:10px}.calc-block .calc-result{display:flex;align-items:baseline;gap:4px;font-variant-numeric:tabular-nums}.calc-block .calc-result .calc-label{font-size:13px;color:var(--muted);font-weight:600}.calc-block .calc-result strong{font-size:22px;font-weight:800;color:var(--primary)}.calc-block .calc-result .u{font-size:12px;color:var(--primary);margin-left:2px}.calc-block .calc-result .muted{color:var(--muted-2);font-size:18px}.calc-block .calc-apply{flex-shrink:0}.calc-block .calc-apply:disabled{background:#e5e7eb;color:var(--muted-2);cursor:not-allowed;box-shadow:none}.predict-hint{display:flex;align-items:center;gap:10px;padding:10px 14px;background:linear-gradient(135deg,var(--primary-soft) 0%,var(--accent-soft) 100%);border-radius:10px;font-size:13px}.predict-hint>i{color:var(--primary);font-size:16px}.predict-hint .hint-text{flex:1;color:var(--text)}.predict-hint .hint-text strong{color:var(--primary);font-weight:700}.predict-hint.predict-hint--inline .hint-text strong{font-weight:800;font-variant-numeric:tabular-nums}.sync-error{padding:10px 14px;background:var(--rose-soft);color:#991b1b;border-radius:10px;font-size:13px;display:flex;align-items:center;gap:6px}.sync-success{padding:10px 14px;background:var(--mint-soft);color:#166534;border-radius:10px;font-size:13px;display:flex;align-items:center;gap:6px;animation:fadeIn .2s ease}.dialog-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:4px}.feeding-settings-dialog .feeding-settings-hint{margin:0 0 14px;font-size:13px;line-height:1.45}.feeding-settings-dialog .feeding-settings-hint code{font-size:11px;padding:1px 5px;border-radius:4px;background:#f1f5f9}.feeding-settings-dialog .feeding-settings-grid{grid-template-columns:1fr;gap:16px}.feeding-settings-dialog .field-hint{display:block;margin-top:8px;font-size:12px;line-height:1.4;padding:8px 12px;background:#f8fafc;border-radius:8px;border-left:3px solid #e2e8f0}.feeding-settings-dialog .label{position:relative}.feeding-settings-dialog .label code{font-size:11px;font-weight:600;color:var(--primary);background:var(--primary-soft);padding:2px 6px;border-radius:4px}.feeding-settings-dialog .label .notification-badge{display:inline-flex;align-items:center;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:#fff;background:linear-gradient(135deg,#10b981,#059669);padding:2px 6px;border-radius:10px;margin-left:6px;box-shadow:0 1px 2px #10b98133;animation:gentle-pulse 2s ease-in-out infinite}.feeding-settings-dialog .notification-setting-field{position:relative}.feeding-settings-dialog .notification-setting-field input{border:1.5px solid #10b981;background:linear-gradient(to right,#fff,#f0fdf4)}.feeding-settings-dialog .notification-setting-field input:focus{border-color:#059669;box-shadow:0 0 0 3px #10b9811a;background:#fff}.feeding-settings-dialog .notification-setting-field input::placeholder{color:#6b7280;opacity:.7}.feeding-settings-dialog .notification-setting-field .field-hint{border-left-color:#10b981;background:linear-gradient(to right,#f0fdf4,#f8fafc)}@keyframes gentle-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.85;transform:scale(1.02)}}.log-time--with-badge,.feed-row-time .time--with-badge{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}.log-merge-badge,.feed-merge-badge{font:inherit;font-size:10px;font-weight:700;padding:2px 7px;border-radius:999px;border:1px solid rgba(99,102,241,.35);background:linear-gradient(135deg,#e0e7ff,#c7d2fe);color:#312e81;cursor:pointer;line-height:1.2;white-space:nowrap}.log-merge-badge:hover,.feed-merge-badge:hover{filter:brightness(1.03)}.log-row--clickable,.feed-row--clickable{cursor:pointer}.log-row--clickable:hover,.feed-row--clickable:hover{background:#6366f10f}.log-row--clickable:focus-visible,.feed-row--clickable:focus-visible{outline:2px solid rgba(99,102,241,.45);outline-offset:2px}.dialog-overlay.dialog-overlay--front.feed-group-detail-overlay{z-index:125}.dialog-overlay.dialog-overlay--front.feed-detail-overlay{z-index:140;animation:overlayIn .12s ease-out}.dialog-overlay.dialog-overlay--front.feed-detail-overlay .feed-detail-dialog{animation:feedDetailIn .14s ease-out}@keyframes feedDetailIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.feed-detail-dialog{--fd-accent: 99, 102, 241;--fd-soft: #eef2ff;--fd-strong: #4338ca;max-width:min(400px,96vw);padding:0;overflow:hidden;display:flex;flex-direction:column}.feed-detail-dialog[data-status=low]{--fd-accent: 245, 158, 11;--fd-soft: #fffbeb;--fd-strong: #b45309}.feed-detail-dialog[data-status=high]{--fd-accent: 244, 63, 94;--fd-soft: #fff1f2;--fd-strong: #e11d48}.feed-detail-dialog[data-status=ok]{--fd-accent: 16, 185, 129;--fd-soft: #ecfdf5;--fd-strong: #059669}.feed-detail-top{position:relative;padding:20px 20px 16px;text-align:center;background:radial-gradient(120% 80% at 50% -20%,rgba(var(--fd-accent),.22),transparent 55%),linear-gradient(180deg,var(--fd-soft) 0%,#ffffff 72%);border-bottom:1px solid rgba(var(--fd-accent),.12)}.feed-detail-close{position:absolute;top:12px;right:12px;width:36px;height:36px;border:none;border-radius:50%;background:#ffffffd9;color:#64748b;cursor:pointer;display:grid;place-items:center;box-shadow:0 2px 8px #0f172a14;transition:background .15s ease,color .15s ease}.feed-detail-close:hover{background:#fff;color:#0f172a}.feed-detail-eyebrow{margin:0 0 6px;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:#64748b}.feed-detail-metric{display:flex;align-items:flex-end;justify-content:center;gap:4px;line-height:1;margin-bottom:10px}.feed-detail-metric__value{font-size:clamp(48px,14vw,56px);font-weight:800;letter-spacing:-.04em;color:var(--fd-strong);font-variant-numeric:tabular-nums}.feed-detail-metric__unit{font-size:18px;font-weight:700;color:rgba(var(--fd-accent),.85);padding-bottom:8px}.feed-detail-status{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:999px;font-size:12px;font-weight:700;background:#fff;border:1px solid rgba(var(--fd-accent),.28);color:var(--fd-strong);box-shadow:0 2px 6px rgba(var(--fd-accent),.1)}.feed-detail-status .pi{font-size:13px}.feed-detail-chips{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:14px}.feed-detail-chip{display:inline-flex;align-items:center;gap:6px;padding:7px 11px;border-radius:12px;background:#ffffffeb;border:1px solid #e2e8f0;font-size:12px;font-weight:600;color:#334155;line-height:1.3;box-shadow:0 1px 4px #0f172a0a}.feed-detail-chip .pi{font-size:13px;color:#6366f1;flex-shrink:0}.feed-detail-chip em{font-style:normal;font-weight:500;color:#94a3b8;margin-left:4px}.feed-detail-chip--time .pi{color:#dc2626}.feed-detail-chip--time span{font-variant-numeric:tabular-nums;font-weight:700;color:#dc2626}.feed-detail-chip--muted{background:#f8fafc;border-color:#e2e8f0;color:#64748b;font-weight:500}.feed-detail-chip--muted .pi{color:#94a3b8}.feed-detail-body{padding:16px 18px 8px;overflow-y:auto;flex:1;min-height:0}.feed-detail-section{margin-bottom:14px}.feed-detail-section:last-child{margin-bottom:0}.feed-detail-section__title{margin:0 0 10px;font-size:12px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#64748b;display:flex;align-items:center;gap:7px}.feed-detail-section__title .pi{font-size:13px;color:#6366f1}.feed-detail-cards{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.feed-detail-card{display:flex;align-items:flex-start;gap:12px;padding:12px 13px;border-radius:14px;background:linear-gradient(180deg,#fafbff,#fff);border:1px solid #e2e8f0;box-shadow:0 2px 8px #0f172a0a}.feed-detail-card--warn,.feed-detail-card--gap.feed-detail-card--warn{border-color:#f59e0b66;background:linear-gradient(180deg,#fffbeb,#fff)}.feed-detail-card--warn .feed-detail-card__icon,.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__icon{background:#fef3c7;color:#b45309}.feed-detail-card--warn .feed-detail-card__text,.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__text{color:#92400e}.feed-detail-card--position{border-color:#8b5cf659;background:linear-gradient(180deg,#f5f3ff,#fff)}.feed-detail-card--average{border-color:#0ea5e959;background:linear-gradient(180deg,#f0f9ff,#fff)}.feed-detail-card--next{border-color:#10b98159;background:linear-gradient(180deg,#ecfdf5,#fff)}.feed-detail-card--gap:not(.feed-detail-card--warn){border-color:#64748b59;background:linear-gradient(180deg,#f8fafc,#fff)}.feed-detail-card__icon{flex-shrink:0;width:36px;height:36px;border-radius:10px;display:grid;place-items:center;background:#eef2ff;color:#4f46e5;font-size:15px}.feed-detail-card__icon[data-kind=position]{background:#ede9fe;color:#7c3aed}.feed-detail-card__icon[data-kind=average]{background:#e0f2fe;color:#0284c7}.feed-detail-card__icon[data-kind=next]{background:#d1fae5;color:#059669}.feed-detail-card__icon[data-kind=gap]{background:#e2e8f0;color:#475569}.feed-detail-card--gap.feed-detail-card--warn .feed-detail-card__icon{background:#fef3c7;color:#b45309}.feed-detail-card__body{min-width:0;flex:1}.feed-detail-card__label{display:block;font-size:11px;font-weight:800;color:#64748b;margin-bottom:3px;letter-spacing:.02em}.feed-detail-card__text{margin:0;font-size:13px;line-height:1.5;color:#0f172a}.fdc-position__head{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin-bottom:8px}.fdc-position__idx{font-size:18px;font-weight:800;color:#6d28d9;letter-spacing:-.02em}.fdc-position__of{font-size:14px;font-weight:700;color:#a78bfa}.fdc-position__tag{font-size:11px;font-weight:600;color:#64748b;padding:2px 8px;border-radius:999px;background:#8b5cf61a}.fdc-progress{height:8px;border-radius:999px;background:#ede9fe;overflow:hidden;margin-bottom:10px}.fdc-progress__fill{height:100%;border-radius:inherit;background:linear-gradient(90deg,#8b5cf6,#6366f1);transition:width .2s ease}.fdc-position__stats{display:flex;flex-wrap:wrap;gap:8px}.fdc-stat{display:inline-flex;align-items:baseline;gap:4px;padding:6px 10px;border-radius:10px;font-size:12px}.fdc-stat strong{font-size:15px;font-weight:800;font-variant-numeric:tabular-nums}.fdc-stat small{font-size:11px;font-weight:600;opacity:.85}.fdc-stat--violet{background:#f5f3ff;color:#5b21b6}.fdc-stat--violet strong{color:#6d28d9}.fdc-stat--indigo{background:#eef2ff;color:#4338ca}.fdc-stat--indigo strong{color:#4f46e5}.fdc-avg,.fdc-next{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}.fdc-pill{display:inline-flex;padding:4px 10px;border-radius:999px;font-size:13px;font-weight:800;font-variant-numeric:tabular-nums}.fdc-pill--up{background:#dcfce7;color:#15803d}.fdc-pill--down{background:#fee2e2;color:#b91c1c}.fdc-pill--neutral{background:#f1f5f9;color:#475569}.fdc-avg__meta{font-size:12px;color:#64748b;line-height:1.4}.fdc-avg__meta strong{color:#0f172a;font-weight:700}.fdc-next__time{font-size:16px;font-weight:800;color:#dc2626;font-variant-numeric:tabular-nums}.fdc-next__vol{font-size:14px;font-weight:800;color:#059669;padding:4px 10px;border-radius:8px;background:#d1fae5}.fdc-next__gap{font-size:12px;font-weight:600;color:#64748b;display:inline-flex;align-items:center;gap:4px}.fdc-gap{display:flex;flex-direction:column;gap:10px}.fdc-gap__prev{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px;padding:10px 12px;border-radius:10px;background:#ffffffe6;border:1px solid #e2e8f0}.fdc-gap__prev-label{font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#64748b;width:100%}.fdc-gap__prev-time{font-size:17px;font-weight:800;color:#0f172a;font-variant-numeric:tabular-nums}.fdc-gap__prev-vol{font-size:14px;font-weight:800;color:#475569;padding:3px 8px;border-radius:8px;background:#f1f5f9}.fdc-gap__prev-date{font-size:11px;font-weight:600;color:#94a3b8}.fdc-gap__row{display:flex;flex-wrap:nowrap;align-items:center;gap:8px;min-width:0}.fdc-gap__interval{display:inline-flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;padding:6px 10px;border-radius:999px;font-size:12px;font-weight:700;color:#475569;background:#e2e8f0;white-space:nowrap}.fdc-gap__interval .pi{font-size:13px;flex-shrink:0}.fdc-gap__interval span{overflow:hidden;text-overflow:ellipsis}.fdc-gap__interval--warn{color:#b45309;background:#fde68a;border:1px solid rgba(245,158,11,.35)}.fdc-gap__vol-diff{flex:0 0 auto;white-space:nowrap;font-size:12px;padding:5px 10px}.feed-detail-quote{margin:0;padding:12px 14px 12px 16px;border-radius:0;border-left:3px solid #c7d2fe;background:#f8fafc;font-size:14px;line-height:1.55;color:#334155;font-style:normal}.feed-detail-footer{padding:12px 16px calc(12px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#fafbff}.feed-detail-cta{display:flex;gap:8px;justify-content:stretch}.feed-detail-cta .btn{flex:1;justify-content:center}.feed-detail-cta .btn.primary{flex:1.2}.feed-group-detail-dialog .feed-group-detail-summary{margin:0 0 8px;padding:0 2px;font-size:13px;line-height:1.45}.feed-group-detail-dialog .feed-group-detail-hint{margin:0 0 12px;font-size:12px;line-height:1.4;display:flex;align-items:center;gap:6px}.feed-group-detail-dialog .feed-group-detail-history{margin-bottom:4px}.feed-group-detail-dialog .feed-group-detail-rows{max-height:min(58vh,420px);overflow-y:auto;padding-right:2px}.mom-food-card{--mf-tone: 244, 114, 182;--mf-soft: #fdf2f8;--mf-ring: #fbcfe8;--mf-strong: #db2777;position:relative;overflow:hidden;background:radial-gradient(900px 260px at 0% 0%,rgba(var(--mf-tone),.14),transparent 60%),#fff;border-color:rgba(var(--mf-tone),.22);padding:18px;margin-top:16px}.mom-food-card[data-accent=rose]{--mf-tone: 244, 63, 94;--mf-soft: #fff1f2;--mf-ring: #fecdd3;--mf-strong: #e11d48}.mom-food-card[data-accent=peach]{--mf-tone: 251, 146, 60;--mf-soft: #fff7ed;--mf-ring: #fed7aa;--mf-strong: #ea580c}.mom-food-card[data-accent=mint]{--mf-tone: 16, 185, 129;--mf-soft: #ecfdf5;--mf-ring: #a7f3d0;--mf-strong: #059669}.mom-food-card[data-accent=lavender]{--mf-tone: 139, 92, 246;--mf-soft: #f5f3ff;--mf-ring: #ddd6fe;--mf-strong: #7c3aed}.mom-food-card[data-accent=amber]{--mf-tone: 245, 158, 11;--mf-soft: #fffbeb;--mf-ring: #fde68a;--mf-strong: #d97706}.mf-head{display:flex;justify-content:space-between;align-items:flex-start;gap:12px;flex-wrap:wrap;margin-bottom:12px}.mf-head__lead{min-width:0;flex:1}.mf-head .eyebrow{display:inline-flex;align-items:center;gap:6px;color:var(--mf-strong);font-weight:700}.mf-head .eyebrow i{font-size:13px}.mf-head h2{margin:4px 0 0;font-size:18px;font-weight:800;color:var(--text);line-height:1.25}.mf-headline{margin:4px 0 0;font-size:13px;color:var(--mf-strong);font-weight:600}.mf-nav{display:inline-flex;align-items:center;gap:6px;background:var(--mf-soft);border-radius:999px;padding:4px;border:1px solid rgba(var(--mf-tone),.25);flex-shrink:0}.mf-arrow{width:30px;height:30px;border-radius:50%;border:none;background:#fff;color:var(--mf-strong);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .15s ease,background .15s ease}.mf-arrow i{font-size:12px}.mf-arrow:hover:not(:disabled){transform:scale(1.08);background:var(--mf-strong);color:#fff}.mf-arrow:disabled{opacity:.35;cursor:not-allowed}.mf-step{font-variant-numeric:tabular-nums;font-size:12px;color:var(--muted);padding:0 4px}.mf-step strong{color:var(--mf-strong);font-weight:800;font-size:13px}.mf-reset{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--mf-strong);background:transparent;border:1px dashed rgba(var(--mf-tone),.5);border-radius:999px;padding:4px 12px;cursor:pointer;margin-bottom:10px;transition:background .15s ease}.mf-reset:hover{background:var(--mf-soft)}.mf-reset i{font-size:11px}.mf-desc{margin:0 0 14px;font-size:13px;color:var(--muted);line-height:1.55}.mf-columns{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px}@media(max-width:640px){.mf-columns{grid-template-columns:1fr}}.mf-col{padding:12px 14px;border-radius:14px;background:#fff;border:1px solid #eef0f3}.mf-col--good{background:linear-gradient(180deg,#f0fdf4,#fff 80%);border-color:#bbf7d0}.mf-col--bad{background:linear-gradient(180deg,#fef2f2,#fff 80%);border-color:#fecaca}.mf-col-title{display:flex;align-items:center;gap:8px;margin:0 0 10px;font-size:14px;font-weight:800;color:var(--text);letter-spacing:.01em}.mf-dot{width:22px;height:22px;border-radius:50%;display:inline-grid;place-items:center;color:#fff;flex-shrink:0;font-size:11px}.mf-dot i{font-size:10px}.mf-dot.good{background:#10b981;box-shadow:0 2px 6px #10b9814d}.mf-dot.bad{background:#ef4444;box-shadow:0 2px 6px #ef44444d}.mf-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}.mf-item{display:flex;align-items:flex-start;gap:10px;padding:8px 10px;border-radius:10px;background:#ffffffb3;transition:background .15s ease,transform .15s ease}.mf-item:hover{background:#fff;transform:translate(2px)}.mf-item--bad .mf-name{color:#7f1d1d}.mf-item--good .mf-name{color:#064e3b}.mf-emoji{width:28px;height:28px;border-radius:8px;background:#fff;display:inline-grid;place-items:center;font-size:16px;flex-shrink:0;box-shadow:0 1px 2px #0f172a0f}.mf-emoji--x{background:#fef2f2;color:#ef4444}.mf-emoji--x i{font-size:12px}.mf-item-body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.mf-name{font-size:13px;font-weight:700;color:var(--text);line-height:1.3}.mf-note{font-size:11.5px;color:var(--muted);line-height:1.35}.mf-tip{display:flex;align-items:flex-start;gap:8px;padding:10px 14px;border-radius:12px;background:var(--mf-soft);border:1px solid rgba(var(--mf-tone),.22);font-size:12.5px;color:var(--text);line-height:1.5}.mf-tip i{color:var(--mf-strong);font-size:15px;margin-top:1px;flex-shrink:0}.mom-tab .card{padding:12px 14px;margin-bottom:10px;border-radius:14px}.mom-tab .mom-wellness-section,.mom-tab .mom-tips-week{margin-bottom:10px}.mom-tab .mom-food-card{padding:12px 14px;margin-top:10px}.mom-tab .mf-head{margin-bottom:8px}.mom-tab .mf-head h2{font-size:16px}.mom-tab .mf-desc{margin-bottom:10px;font-size:12px;line-height:1.45;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.mom-tab .mf-columns{gap:8px;margin-bottom:8px}.mom-tab .mf-col{padding:8px 10px}.mom-tab .mf-list{gap:6px}.mom-tab .mf-item{padding:6px 8px}.mom-tab .mf-tip{padding:8px 10px;font-size:12px}.mom-hero{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;margin-bottom:14px;background:linear-gradient(135deg,#fdf2f8,#faf5ff,#eef2ff);border:1px solid #f9a8d4;border-radius:16px}.mom-hero .mom-hero__icon{font-size:36px;line-height:1;flex-shrink:0}.mom-hero h2{margin:0 0 6px;font-size:19px;font-weight:800;color:var(--text);letter-spacing:-.02em}.mom-hero .mom-hero__sub{margin:0;font-size:13px;line-height:1.5;color:var(--muted)}.mom-hero .mom-hero__sub strong{color:var(--text)}.mom-hero .mom-hero__sub .muted-inline{display:block;margin-top:4px;font-size:12.5px;opacity:.92}.mom-hero--compact{align-items:center;padding:10px 12px;margin-bottom:10px;border-radius:14px;gap:10px}.mom-hero--compact .mom-hero__icon{font-size:26px}.mom-hero--compact h2{margin:0;font-size:16px;letter-spacing:-.01em}.mom-hero--compact .mom-hero__title-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px}.mom-hero--compact .mom-hero__baby{font-size:12px;font-weight:700;color:#be185d;padding:2px 8px;border-radius:999px;background:#ffffffbf;border:1px solid rgba(244,114,182,.35)}.mom-hero--compact .mom-hero__sub{margin:4px 0 0;font-size:11.5px;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.mom-hero--compact .mom-hero__sub .muted-inline{display:inline;margin-top:0;font-size:11.5px}.section-head--tight{margin-bottom:8px}.section-head--tight h3{margin:0}.mom-disclaimer--compact{font-size:11px;line-height:1.4;padding:8px 10px;margin-top:4px;margin-bottom:6px}.section-head{margin-bottom:14px}.section-head h3{margin:0 0 6px;font-size:16px;font-weight:800;display:flex;align-items:center;gap:8px;color:var(--text)}.section-head h3 i{color:#db2777;font-size:15px}.section-head .section-sub{margin:0;font-size:12.5px;color:var(--muted);line-height:1.45}.mom-wellness-section{margin-bottom:16px}.mom-tab .mom-wellness-grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:8px}.mom-wellness-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px}.mom-w-card{padding:14px 14px 12px;border-radius:14px;border:1px solid var(--border);background:#fafafa;transition:border-color .15s,box-shadow .15s}.mom-w-card:hover{border-color:#f472b6;box-shadow:0 6px 18px -12px #db277759}.mom-w-card .mom-w-card__icon{width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,#fce7f3,#ede9fe);display:flex;align-items:center;justify-content:center;margin-bottom:10px}.mom-w-card .mom-w-card__icon i{font-size:16px;color:#be185d}.mom-w-card h4{margin:0 0 8px;font-size:13.5px;font-weight:800;color:var(--text);line-height:1.3}.mom-w-card p{margin:0;font-size:12.5px;line-height:1.5;color:var(--muted)}.mom-tips-week{margin-bottom:16px}.mom-tab .mom-tips-list{gap:6px}.mom-tab .mom-tips-list li{padding:8px 10px;border-radius:10px}.mom-tab .mom-tips-list li strong{margin-bottom:2px;font-size:12px}.mom-tab .mom-tips-list li span{font-size:11.5px;line-height:1.4}.mom-tips-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px}.mom-tips-list li{display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border-radius:12px;background:#fefce8;border:1px solid #fde047}.mom-tips-list li>i{color:#ca8a04;margin-top:2px;flex-shrink:0}.mom-tips-list li strong{display:block;font-size:13px;font-weight:800;color:var(--text);margin-bottom:4px}.mom-tips-list li span{font-size:12.5px;line-height:1.5;color:var(--muted)}.mom-disclaimer{margin-top:8px;margin-bottom:8px}.mom-empty-profile{max-width:520px;margin:24px auto 40px;text-align:center}.mom-empty-profile__inner{padding:28px 22px}.mom-empty-profile__inner .mom-empty-emoji{font-size:48px;display:block;margin-bottom:12px}.mom-empty-profile__inner h2{margin:0 0 10px;font-size:17px;font-weight:800;color:var(--text)}.mom-empty-profile__inner p{margin:0 0 18px;font-size:14px;line-height:1.55;color:var(--muted)}.event-reminder-dialog{max-width:min(520px,100vw - 28px);padding-bottom:8px}.event-reminder-dialog__head{align-items:flex-start;margin-bottom:4px}.event-reminder-dialog__title{margin:0;padding-right:40px;font-size:20px;font-weight:800;line-height:1.3;color:var(--text, #0f172a);display:flex;align-items:center;gap:10px;letter-spacing:-.02em}.event-reminder-dialog__title .pi-bell{color:#f59e0b;font-size:18px;flex-shrink:0}.event-reminder-list{list-style:none;margin:12px 0 0;padding:0;max-height:min(52vh,400px);overflow:auto;display:flex;flex-direction:column;gap:10px}.event-reminder-card{padding:14px 16px;background:linear-gradient(180deg,#fafbff,#fff);border:1px solid #e2e8f0;border-radius:14px;box-shadow:0 2px 8px #0f172a0d}.event-reminder-card__title{margin:0;font-size:16px;font-weight:800;color:var(--text, #0f172a);line-height:1.35}.event-reminder-card__datetime{margin:5px 0 0;font-size:12.5px;font-weight:500;color:#64748b;line-height:1.4}.event-reminder-card__date{color:#475569;font-weight:600}.event-reminder-card__sep{color:#94a3b8}.event-reminder-card__hour{color:#dc2626;font-weight:700;font-variant-numeric:tabular-nums}.event-reminder-card__place{margin:6px 0 0;display:flex;align-items:flex-start;gap:6px;font-size:13px;color:#475569;line-height:1.4}.event-reminder-card__place .pi-map-marker{margin-top:2px;flex-shrink:0;font-size:13px;color:var(--primary, #5b6cff)}.event-reminder-card__content-wrap{margin-top:10px;padding-top:10px;border-top:1px solid #eef1f6}.event-reminder-card__content-label{display:block;margin-bottom:4px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:#94a3b8}.event-reminder-card__content{margin:0;font-size:13.5px;color:#334155;line-height:1.5;white-space:pre-wrap}.event-reminder-actions{display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:12px;margin-top:16px;padding-top:14px;border-top:1px solid var(--border, #e5e7eb)}.event-reminder-actions__link{flex:0 1 auto;min-width:0;padding:6px 4px;border:none;background:transparent;color:#64748b;font-size:13px;font-weight:600;font-family:inherit;text-decoration:underline;text-underline-offset:3px;cursor:pointer}.event-reminder-actions__link:hover:not(:disabled){color:#334155}.event-reminder-actions__link:disabled{opacity:.5;cursor:not-allowed}.event-reminder-actions__primary{flex:1 1 auto;display:inline-flex;align-items:center;justify-content:center;min-height:48px;padding:10px 18px;font-size:15px;font-weight:700;text-align:center}\n"] }]
15848
17137
  }], ctorParameters: () => [], propDecorators: { feedingPageRef: [{
15849
17138
  type: ViewChild,
15850
17139
  args: ['feedingPage', { static: true }]
@@ -15876,5 +17165,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
15876
17165
  * Generated bundle index. Do not edit.
15877
17166
  */
15878
17167
 
15879
- export { ACTIVITY_EVENT, APP_INFO_TOKEN, ActivityLogComponent, ActivityLogService, BABY_TIMELINE, BABY_TIMELINE_CARE_GUIDES, DEFAULT_FEEDING_CONFIG, DocumentsComponent, EventLogService, ExplorerService, FEEDING_CONFIG_TOKEN, FeedingComponent, FeedingDailyComponent, FeedingLogService, FeedingMomComponent, FeedingNutritionComponent, FeedingScheduleComponent, GoogleSheetsService, MedicalHistoryComponent, MedicalHistoryService, NotificationLogService, WeightComponent, WeightLogService, buildActivityLogMessageHtml, createFeedingConfig, evaluateWeightForAge, formatLogContent, getCurrentMilestone, getDailySummaries, getMilestoneState, getNutritionTarget, getTimelineCareGuide, groupLogsByProximity, parseFeedingSettingsFromRows, predictNextFeeding, provideFeedingConfig, resolveAppsScriptUrl };
17168
+ export { ACTIVITY_EVENT, APP_INFO_TOKEN, ActivityLogComponent, ActivityLogService, BABY_TIMELINE, BABY_TIMELINE_CARE_GUIDES, ChatComposerComponent, ChatMessageComponent, ChatShellComponent, DEFAULT_FEEDING_CONFIG, DocumentsComponent, EventLogService, ExplorerService, FEEDING_CONFIG_TOKEN, FeedingComponent, FeedingDailyComponent, FeedingLogService, FeedingMomComponent, FeedingNutritionComponent, FeedingScheduleComponent, GoogleSheetsService, HfAssistantService, MedicalHistoryComponent, MedicalHistoryService, NotificationLogService, TOOL_NAMES, ToolArgs, ToolRegistry, WeightComponent, WeightLogService, buildActivityLogMessageHtml, createFeedingConfig, evaluateWeightForAge, formatLogContent, getCurrentMilestone, getDailySummaries, getMilestoneState, getNutritionTarget, getTimelineCareGuide, groupLogsByProximity, isToolName, parseFeedingSettingsFromRows, parseHfReply, predictNextFeeding, provideFeedingConfig, resolveAppsScriptUrl };
15880
17169
  //# sourceMappingURL=hbslovely-baby-feeding.mjs.map