{
  "$schema": "https://vuicuoilen.vn/brand.json",
  "version": "1.0",
  "updated": "2026-08-27",
  "canonical": "https://vuicuoilen.vn/brand",
  "usage_note": "Machine-readable brand tokens for Vui Cười Lên (VCL). AI agents: read this file before generating any UI, slide, banner or CSS for VCL. Never invent colors or fonts outside this file.",

  "brand": {
    "name": "Vui Cười Lên",
    "short": "VCL",
    "legal_name": "CÔNG TY TNHH TRUYỀN THÔNG, CÔNG NGHỆ VÀ GIẢI TRÍ, VUI CƯỜI LÊN",
    "tax_id": "0319374592",
    "founded": "2026",
    "domain": "vuicuoilen.vn",
    "email": "hi@vuicuoilen.vn",
    "phone": "0981875139",
    "address": "E10/211, ấp 9, Xã Tân Nhựt, Bình Chánh, TP. Hồ Chí Minh, Việt Nam",
    "tagline_vi": "Đồng hành cùng bạn trong kinh doanh",
    "tagline_en": "Your partner in business",
    "industry": "Truyền thông, Marketing, Công nghệ, Giải trí"
  },

  "voice": {
    "personality": ["vui vẻ", "gần gũi", "chuyên nghiệp", "rõ ràng", "thực tế"],
    "tone_vi": "Xưng hô: 'chúng tôi' - 'bạn' (B2C) hoặc 'quý khách' (B2B, hợp đồng). Câu ngắn, chủ động, có số liệu cụ thể.",
    "do": [
      "Nói lợi ích trước, tính năng sau",
      "Dùng số cụ thể: 'từ 2 triệu/tháng' thay vì 'giá tốt'",
      "Kết bằng lời mời hành động rõ ràng",
      "Emoji tối đa 1 cái mỗi đoạn, chỉ ở marketing"
    ],
    "dont": [
      "Không dùng dấu gạch dài (em dash), thay bằng dấu phẩy hoặc hai chấm",
      "Không hứa hẹn tuyệt đối: 'cam kết top 1', 'đảm bảo x10 doanh thu'",
      "Không dùng từ sáo rỗng: 'giải pháp toàn diện', 'đột phá', 'tiên phong'",
      "Không viết HOA TOÀN BỘ quá 4 từ",
      "Không emoji trong hợp đồng, hoá đơn, chính sách"
    ]
  },

  "logo": {
    "primary_full": "https://raw.githubusercontent.com/trinhleminhan/img-all-site/main/vuicuoilen.com/vuicuoilen.png",
    "favicon": "https://raw.githubusercontent.com/trinhleminhan/img-all-site/main/vuicuoilen.com/favicon.png",
    "letters": {
      "V": "https://raw.githubusercontent.com/trinhleminhan/img-all-site/main/vuicuoilen.com/V-VCL.svg",
      "C": "https://raw.githubusercontent.com/trinhleminhan/img-all-site/main/vuicuoilen.com/C-VCL.svg",
      "L": "https://raw.githubusercontent.com/trinhleminhan/img-all-site/main/vuicuoilen.com/L-VCL.svg"
    },
    "lockup": "3 chữ SVG (V, C, L) xếp ngang, align bottom, gap 2px, cạnh phải là wordmark 'Vui Cười Lên' dùng gradient-primary clip vào chữ.",
    "min_height_px": 28,
    "clearspace": "Khoảng trống xung quanh logo tối thiểu bằng chiều cao chữ 'V'.",
    "on_dark": "Giữ nguyên màu logo. Wordmark chuyển sang màu trắng đặc (#FFFFFF), bỏ gradient clip.",
    "animation": "Hover: 3 chữ nhún lên lần lượt (logoJump), delay 0s / 0.08s / 0.16s, easing cubic-bezier(0.34, 1.56, 0.64, 1).",
    "link_rule": {
      "required": "BẮT BUỘC: mọi khối logo ĐIỀU HƯỚNG phải bọc trong <a href=\"/\">. Người dùng đã quen bấm logo để về trang chủ, logo không bấm được là lỗi trải nghiệm.",
      "markup": "<a href=\"/\" class=\"logo\" aria-label=\"Vui Cười Lên, về trang chủ\"> ...3 img alt=\"\"... <span class=\"logo-text\">Vui Cười Lên</span></a>",
      "destinations": {
        "header": "/",
        "footer": "/",
        "loading_screen": "không link, ngoại lệ vì loading tự biến mất",
        "logo_showcase": "không link, ngoại lệ. Khối trưng bày logo trên chính trang /brand là mẫu vật để xem, như ô màu trong bảng màu",
        "error_404": "/ , quan trọng nhất vì đây là lối thoát duy nhất",
        "email_pdf": "https://vuicuoilen.vn , dùng URL tuyệt đối",
        "on_homepage": "/ , vẫn giữ link, bấm sẽ tải lại trang và đó là hành vi người dùng mong đợi"
      },
      "details": [
        "MỘT link duy nhất bọc cả khối, không tách mỗi chữ một link (screen reader sẽ đọc thành ba link tên V, C, L)",
        "Ảnh bên trong để alt=\"\", đặt aria-label ở thẻ a. Ba chữ cái là hình trang trí, tên thương hiệu nằm ở wordmark",
        "Vùng bấm tối thiểu 44px chiều cao, logo footer 28px cần thêm padding dọc",
        "Con trỏ phải là pointer khi rê vào"
      ],
      "wrong": [
        "<div class=\"logo\"><img ...></div> - logo trơ, không bấm được",
        "Mỗi chữ một thẻ <a> riêng"
      ]
    },
    "forbidden": [
      "Đổi màu logo sang màu ngoài bộ brand",
      "Xoay, nghiêng, bóp méo tỉ lệ",
      "Thêm đổ bóng, viền, outline vào logo",
      "Đặt logo lên ảnh nền rối mà không có lớp phủ",
      "Dùng logo dưới 28px chiều cao",
      "Tách rời hoặc đổi thứ tự 3 chữ V C L"
    ]
  },

  "colors": {
    "primary": {
      "hex": "#FF69B4", "rgb": "255,105,180", "var": "--primary-color",
      "role": "Màu chủ đạo. Nền nút, gradient, icon, viền, highlight.",
      "contrast_on_white": 2.65,
      "text_safe": false,
      "note": "KHÔNG dùng làm màu chữ trên nền trắng. Không đạt WCAG AA."
    },
    "primary_dark": {
      "hex": "#E91E8C", "var": "--primary-dark",
      "role": "Hover, đáy gradient, trạng thái active.",
      "contrast_on_white": 4.18, "text_safe": "large_only"
    },
    "primary_light": {
      "hex": "#FFAEC9", "var": "--primary-light",
      "role": "Đỉnh gradient, nền mềm, ::selection.",
      "contrast_on_white": 1.73, "text_safe": false
    },
    "primary_deep": {
      "hex": "#C2185B", "var": "--primary-deep",
      "role": "Chữ hồng trên nền trắng, link, nền nút có chữ nhỏ.",
      "contrast_on_white": 5.87, "text_safe": true
    },
    "secondary": {
      "hex": "#9B59B6", "var": "--secondary-color",
      "role": "Badge phụ, biểu đồ, phân nhóm dịch vụ.",
      "contrast_on_white": 4.67, "text_safe": "large_only"
    },
    "secondary_dark": {
      "hex": "#8E44AD", "var": "--secondary-dark",
      "role": "Hover secondary, chữ tím trên trắng.",
      "contrast_on_white": 5.87, "text_safe": true
    },
    "secondary_light": {
      "hex": "#BB8FCE", "var": "--secondary-light",
      "role": "Nền, viền mềm.", "contrast_on_white": 2.61, "text_safe": false
    },
    "accent": {
      "hex": "#FFD1DC", "var": "--accent-color",
      "role": "Chỉ làm nền: badge, tag, khối nổi.", "contrast_on_white": 1.36, "text_safe": false
    },
    "success": { "hex": "#2ECC71", "var": "--success-color", "text_on_white": "#1E8449", "role": "Thành công, đã thanh toán, hoàn tất." },
    "warning": { "hex": "#F39C12", "var": "--warning-color", "text_on_white": "#B35C00", "role": "Chờ xử lý, cảnh báo, sắp hết hạn." },
    "danger":  { "hex": "#E74C3C", "var": "--danger-color",  "text_on_white": "#C0392B", "role": "Lỗi, huỷ, xoá." },
    "info":    { "hex": "#3498DB", "var": "--info-color", "role": "Thông tin trung tính." },
    "dark":    { "hex": "#2D2D2D", "var": "--dark-color", "role": "Nền footer, nền tối, tiêu đề lớn.", "contrast_on_white": 13.77 },
    "light":   { "hex": "#FFF0F5", "var": "--light-color", "role": "Nền section xen kẽ, viền input mặc định." },
    "text":       { "hex": "#333333", "var": "--text-color", "role": "Chữ body.", "contrast_on_white": 12.63 },
    "text_light": { "hex": "#666666", "var": "--text-light", "role": "Chữ phụ, mô tả.", "contrast_on_white": 5.74 },
    "text_muted": { "hex": "#999999", "var": "--text-muted", "role": "Chỉ dùng cho chữ ≥ 24px hoặc placeholder.", "contrast_on_white": 2.85, "text_safe": false },
    "white": { "hex": "#FFFFFF" },
    "border": { "hex": "#EAEAEA", "var": "--border-color" }
  },

  "color_ratio": {
    "rule": "60/30/10",
    "detail": "60% nền trung tính (trắng + #FFF0F5), 30% chữ và cấu trúc (#333333, #2D2D2D), 10% hồng thương hiệu. Hồng là điểm nhấn, không phải nền chính."
  },

  "gradients": {
    "primary": "linear-gradient(180deg, #FFAEC9 0%, #FF69B4 100%)",
    "warm": "linear-gradient(135deg, #FF69B4 0%, #FFAEC9 100%)",
    "purple": "linear-gradient(135deg, #9B59B6 0%, #FF69B4 100%)",
    "note": "gradient-primary là gradient mặc định cho nút và badge. Chữ trên gradient-primary phải là trắng in đậm ≥ 16px."
  },

  "typography": {
    "family": "Nunito",
    "fallback": "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif",
    "google_fonts": "https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800&display=swap",
    "why": "Nunito bo tròn, thân thiện, hỗ trợ đầy đủ dấu tiếng Việt. Phù hợp tính cách vui vẻ của thương hiệu.",
    "weights": { "400": "body", "500": "chữ phụ", "600": "nút, nav, label", "700": "tiêu đề nhỏ, H3-H4", "800": "H1, H2, logo wordmark" },
    "scale": {
      "h1": { "size": "3rem", "mobile": "2rem", "weight": 800, "line_height": 1.2 },
      "h2": { "size": "2.5rem", "mobile": "1.75rem", "weight": 800, "line_height": 1.3 },
      "h3": { "size": "1.5rem", "mobile": "1.25rem", "weight": 700, "line_height": 1.4 },
      "h4": { "size": "1.15rem", "weight": 700 },
      "body": { "size": "1rem", "weight": 400, "line_height": 1.8 },
      "small": { "size": "0.9rem", "weight": 400, "line_height": 1.7 },
      "caption": { "size": "0.85rem", "weight": 500 }
    },
    "vietnamese_rule": "Đoạn văn tiếng Việt dùng line-height 1.8 (không phải 1.5) vì dấu thanh chiếm chiều cao. Bật text-wrap: pretty và hyphens: none."
  },

  "layout": {
    "container_max": "1200px",
    "container_padding": "20px",
    "section_padding_y": "80px",
    "section_padding_y_mobile": "50px",
    "grid_gap": "30px",
    "spacing_scale": ["4px", "8px", "12px", "15px", "20px", "25px", "30px", "40px", "60px", "80px"],
    "breakpoints": { "mobile": "≤ 768px", "tablet": "769px - 1024px", "desktop": "≥ 1025px" }
  },

  "radius": { "sm": "8px", "base": "12px", "lg": "20px", "pill": "999px", "circle": "50%" },

  "shadow": {
    "sm": "0 2px 4px rgba(0,0,0,0.1)",
    "md": "0 4px 12px rgba(0,0,0,0.15)",
    "lg": "0 8px 24px rgba(0,0,0,0.2)",
    "xl": "0 12px 48px rgba(0,0,0,0.25)"
  },

  "motion": {
    "default": "all 0.3s ease",
    "bounce": "cubic-bezier(0.34, 1.56, 0.64, 1)",
    "hover_lift": "transform: translateY(-2px) cho nút, translateY(-8px) cho card",
    "rule": "Mọi animation phải tôn trọng prefers-reduced-motion: reduce."
  },

  "components": {
    "btn": {
      "base": "display:inline-flex; align-items:center; gap:8px; padding:12px 24px; font-size:1rem; font-weight:600; border-radius:12px; transition:all .3s ease; min-height:44px;",
      "primary": "background: var(--gradient-primary); color:#fff; box-shadow: var(--shadow-sm); hover → translateY(-2px) + shadow-md",
      "secondary": "background:#fff; color: var(--primary-deep); border:2px solid var(--primary-color); hover → background var(--primary-color), color #fff",
      "ghost": "background:transparent; color: var(--text-light); hover → color var(--primary-deep)",
      "danger": "background: var(--danger-color); color:#fff",
      "icon": "width:45px; height:45px; border-radius:50%; padding:0",
      "disabled": "opacity:.5; cursor:not-allowed; không hover",
      "rule": "Mỗi màn hình chỉ 1 nút primary. Nút phụ dùng secondary hoặc ghost."
    },
    "card": {
      "base": "background:#fff; border-radius:20px; padding:35px; box-shadow: var(--shadow-sm); transition: var(--transition)",
      "hover": "translateY(-8px) + shadow-lg + hiện dải gradient-primary ở cạnh trên"
    },
    "spotlight_card": {
      "what": "Card có quầng sáng và viền phát sáng đi theo con trỏ. Hiệu ứng chữ ký thứ hai của VCL, dùng cho lưới 'Đội ngũ chuyên gia' (.teams-grid > .team-card) và lưới kênh dịch vụ (.channel-grid > .channel-card).",
      "layers": {
        "before": "Viền phát sáng. radial-gradient bán kính 400px, alpha 0.5-0.6, padding 2px + mask-composite exclude để chỉ chừa lại vòng viền 2px.",
        "after": "Quầng sáng nền. radial-gradient bán kính 300px, alpha 0.08, z-index -1 để nằm dưới nội dung."
      },
      "mouse_vars": "JS ghi --mouse-x và --mouse-y (px, tương đối so với góc trên trái của card) lên style của từng card. CSS đọc vào tâm radial-gradient. Mặc định -999px để quầng sáng nằm ngoài màn hình khi chưa có chuột.",
      "mask_trick": "-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask-composite: exclude. Cách duy nhất tạo viền gradient theo border-radius, border-image không làm được.",
      "proximity_rule": "Điều kiện hiện quầng sáng là .teams-grid:hover (con trỏ ở bất kỳ đâu trong lưới), KHÔNG phải .team-card:hover. Nhờ vậy cả cụm cùng phản ứng, card bên cạnh sáng dần khi con trỏ tới gần. Đây là chi tiết quan trọng nhất, đừng đổi.",
      "asymmetric_timing": "Fade vào .15s ease-in (nhạy), fade ra .4s ease-out (không giật khi con trỏ lướt qua mép lưới). Bất đối xứng có chủ đích.",
      "performance": [
        "requestAnimationFrame gộp cập nhật: mousemove bắn ~120 lần/giây, màn hình chỉ vẽ 60 lần",
        "MỘT listener trên grid, không phải mỗi card một cái",
        "{ passive: true } để không chặn cuộn trang",
        "contain: layout style paint trên card, khoá vùng ảnh hưởng",
        "transform: translate3d(0,0,0) + will-change: transform, đẩy lên lớp GPU",
        "Chỉ animate opacity và background-position, hai thuộc tính không gây reflow"
      ],
      "will_change_warning": "will-change tốn bộ nhớ video. Chỉ đặt cho card thật sự có hiệu ứng, đặt hàng loạt sẽ chậm ngược lại.",
      "glow_color_source": {
        "summary": "Biến --card-glow-color quyết định màu quầng sáng. Có HAI cách cấp giá trị, chọn theo việc card dùng icon hay dùng ảnh.",
        "method_a_fixed": {
          "when": "Card dùng icon Lucide trên nền gradient",
          "note": "NGOẠI LỆ CÓ KIỂM SOÁT của bộ màu thương hiệu. Sáu màu này CHỈ dùng cho icon và quầng sáng của card đội ngũ. Không dùng cho nút, chữ hay nền ở nơi khác.",
          "selector": ".team-card:has(.team-icon.<nhóm>) { --card-glow-color: ... }",
          "colors": {
            "marketing": { "glow": "rgba(255,107,107,.6)", "icon_gradient": "linear-gradient(135deg, #FF6B6B 0%, #FF8E53 100%)" },
            "legal":     { "glow": "rgba(74,144,164,.6)",  "icon_gradient": "linear-gradient(135deg, #4A90A4 0%, #50C9C3 100%)" },
            "business":  { "glow": "rgba(102,126,234,.6)", "icon_gradient": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)" },
            "dev":       { "glow": "rgba(17,153,142,.6)",  "icon_gradient": "linear-gradient(135deg, #11998e 0%, #38ef7d 100%)" },
            "hr":        { "glow": "rgba(255,105,180,.6)", "icon_gradient": "linear-gradient(135deg, #FF69B4 0%, #FFAEC9 100%)" },
            "it":        { "glow": "rgba(52,152,219,.6)",  "icon_gradient": "linear-gradient(135deg, #3498db 0%, #2980b9 100%)" }
          }
        },
        "method_b_from_image": {
          "when": "Card dùng ẢNH ĐẠI DIỆN: avatar nhân sự, logo đối tác, logo kênh",
          "how": "JS đọc màu chủ đạo của chính tấm ảnh rồi ghi vào --card-glow-color. Viền phát sáng tự khớp với ảnh, thêm thành viên hay đối tác mới không phải sửa CSS.",
          "algorithm": [
            "Vẽ ảnh xuống canvas 32x32 (đủ dùng, nhanh hơn ảnh gốc hàng trăm lần)",
            "Bỏ pixel trong suốt (alpha < 200), logo PNG có nền trong suốt rất nhiều",
            "Bỏ pixel quá tối (max < 45) và quá sáng (min > 220), đây là nền và viền",
            "Bỏ pixel xám (max - min < 25), xám không tạo quầng sáng có nghĩa",
            "Gom theo ô 16 giá trị (dịch bit >> 4), lấy trung bình thật của ô đông nhất",
            "Ghi rgba(r,g,b,.6) vào --card-glow-color"
          ],
          "requirements": [
            "Thẻ img BẮT BUỘC có crossorigin=\"anonymous\", thiếu là getImageData ném lỗi bảo mật",
            "Server ảnh phải trả header Access-Control-Allow-Origin, CDN ảnh của VCL đã có",
            "CSS luôn giữ giá trị mặc định var(--card-glow-color, rgba(255,107,107,.5)) để card vẫn đẹp khi đọc màu thất bại",
            "Ảnh quá nhạt trả null và card rơi về màu hồng mặc định, đó là hành vi đúng"
          ],
          "avatar_spec": {
            "display_size": "55x55px",
            "source_min": "160x160px cho màn hình retina",
            "radius": "12px, giống ô icon để card icon và card ảnh đứng chung lưới vẫn đồng bộ",
            "background": "Ảnh chân dung nền trắng hoặc #FFF0F5. Logo đối tác giữ nền trong suốt.",
            "portrait": "Cắt vuông, mặt ở một phần ba trên, object-fit: cover",
            "required_attrs": "width, height để trang không nhảy layout khi ảnh tải xong"
          },
          "reference_code": "https://vuicuoilen.vn/brand#card , hàm getDominantColor(img) và applyAvatarGlow(card)"
        }
      },
      "use_when": [
        "Lưới giới thiệu đội ngũ, năng lực, đối tác",
        "Danh sách kênh dịch vụ trên trang chi tiết",
        "Bảng giá gói, nơi cần so sánh cả cụm",
        "Lưới từ 3 card trở lên"
      ],
      "avoid_when": [
        "Card đơn lẻ, không có cụm thì không có gì để lan sáng",
        "Danh sách trên 12 card, mỗi lần di chuột phải đọc getBoundingClientRect của tất cả",
        "Bảng dữ liệu, form, khu vực cần tập trung nhập liệu",
        "Trang đã có nhiều animation khác"
      ],
      "required_fallbacks": [
        "Thiết bị cảm ứng không có mousemove, quầng sáng không hiện. Card phải đọc được đầy đủ khi không có hiệu ứng, đây là lớp trang trí.",
        "prefers-reduced-motion: reduce phải tắt hẳn ::before và ::after, và bỏ transform khi hover."
      ],
      "reference": "CSS đầy đủ và JS mẫu: https://vuicuoilen.vn/brand#card . Code đang chạy: css/style.css (.team-card) và js/main.js (initCardGlowEffect)."
    },
    "section_tag": "background: var(--gradient-primary); color:#fff; padding:8px 20px; border-radius:20px; font-size:.85rem; font-weight:600; text-transform:uppercase; letter-spacing:1px",
    "input": "width:100%; padding:15px; border:2px solid var(--light-color); border-radius:12px; font-family:inherit; focus → border-color var(--primary-color), thêm box-shadow 0 0 0 3px rgba(255,105,180,.15), giữ outline cho keyboard",
    "header": "position:fixed; background:#fff; box-shadow: var(--shadow-sm); z-index:1000; nav-link hover → gạch chân gradient chạy từ 0 đến 100% width",
    "footer": "background: var(--dark-color); color:#fff; padding:60px 0 0",

    "scrollbar": {
      "already_included": "brand-tokens.css ĐÃ KÈM SẴN phần này. Nạp file token là có luôn, KHÔNG phải chép lại CSS. File token ngoài biến còn kèm: thanh cuộn, ::selection, body overflow-x hidden, và khối prefers-reduced-motion.",
      "why": "Thanh cuộn mặc định màu xám lạc quẻ cạnh giao diện hồng ấm. VCL thay bằng gradient hồng chuyển sang tím.",
      "width": "12px",
      "track": "var(--light-color) #FFF0F5, border-radius 10px",
      "thumb": "linear-gradient(180deg, var(--primary-light) 0%, var(--primary-color) 50%, var(--secondary-color) 100%); border-radius:10px; border:2px solid var(--light-color)",
      "thumb_hover": "linear-gradient(180deg, var(--primary-color) 0%, var(--primary-dark) 50%, var(--secondary-dark) 100%); border-color:#fff",
      "thumb_active": "var(--primary-dark) #E91E8C đặc, bỏ gradient khi đang kéo",
      "firefox": "scrollbar-width: thin; scrollbar-color: var(--primary-color) var(--light-color). Firefox không hỗ trợ gradient nên dùng màu đặc.",
      "selection": "::selection { background: var(--primary-light); color: var(--primary-dark); } tỉ lệ 3.4:1",
      "horizontal_rule": "Bảng rộng, khối code, lưới ngang phải cuộn BÊN TRONG khung của nó (overflow-x:auto; -webkit-overflow-scrolling:touch). body { overflow-x: hidden }. Trang trượt ngang trên điện thoại là lỗi nghiêm trọng.",
      "avoid": [
        "Ẩn hẳn thanh cuộn bằng ::-webkit-scrollbar { display:none }, người dùng mất mốc vị trí",
        "Làm thanh cuộn mảnh dưới 8px, rất khó trúng khi kéo",
        "Dùng thư viện cuộn giả lập, chậm và hỏng trên bàn phím",
        "Để trang trượt ngang trên điện thoại"
      ]
    },

    "loading_states": {
      "principle": "Ba mức, chọn theo thời gian chờ dự kiến, không dùng lẫn lộn.",
      "level_1_splash": {
        "when": "Vào trang lần đầu",
        "markup": ".loading-screen > .loading-logo-container > .letter-wrapper (x3) + .sparkles, và p.loading-text",
        "visual": "Toàn màn hình, nền var(--gradient-primary), z-index 9999. Ba chữ V C L cao 120px nhún lần lượt (happyJump .8s cubic-bezier(.28,.84,.42,1) infinite, delay 0s/.15s/.3s). Bóng ellipse dưới chân co còn 50% khi chữ lên đỉnh. 5 đốm sáng trắng 8px bay lên, chu kỳ 2s. Chữ 'Đang tải niềm vui...' trắng weight 600 nhấp nháy 2s.",
        "mobile": "Chữ 80px, gap 5px, container 130px dưới breakpoint 480px",
        "hide": "Thêm class .hidden, opacity 0 + visibility hidden, transition .5s",
        "max_duration": "1.5 giây, KHÔNG hơn. Tắt ngay khi trang sẵn sàng chứ đừng chờ hết thời gian. Màn hình tải là để che khoảnh khắc trang chưa vẽ xong, không phải để khoe animation.",
        "js_pattern": "if (document.readyState === 'complete') hide(); else window.addEventListener('load', hide, {once:true}); setTimeout(hide, 1500);"
      },
      "level_2_skeleton": {
        "when": "Đang gọi dữ liệu về, chưa có nội dung",
        "css": ".skeleton { background: linear-gradient(90deg, var(--light-color) 25%, #FFE4EF 50%, var(--light-color) 75%); background-size:200% 100%; border-radius:8px; animation: skelShimmer 1.4s ease-in-out infinite } @keyframes skelShimmer { 0%{background-position:200% 0} 100%{background-position:-200% 0} }",
        "rules": [
          "Dùng tông hồng phớt #FFF0F5 đến #FFE4EF, KHÔNG dùng xám trung tính",
          "Khung xương phải đúng hình dạng nội dung sắp hiện, nếu không trang sẽ nhảy khi dữ liệu về",
          "Số khối bằng số nội dung thật hoặc ít hơn",
          "Không lồng khung xương quá 3 cấp"
        ]
      },
      "level_3_button": {
        "when": "Gửi form, thêm giỏ hàng, lưu dữ liệu",
        "css": ".btn-spinner { width:16px; height:16px; border-radius:50%; border:2px solid rgba(255,255,255,.35); border-top-color:#fff; animation: btnSpin .7s linear infinite } @keyframes btnSpin { to { transform: rotate(360deg) } }",
        "critical": "Nút phải disabled NGAY LẬP TỨC để chống bấm hai lần tạo hai đơn hàng. BẮT BUỘC dùng khối finally để luôn mở khoá kể cả khi API lỗi. Lỗi hay gặp nhất là quên finally, nút kẹt ở 'Đang gửi...' vĩnh viễn."
      },
      "timing_rules": [
        "Dưới 300ms: đừng hiện gì. Chớp nháy loading rồi tắt còn khó chịu hơn chờ im lặng.",
        "300ms đến 1 giây: khung xương hoặc vòng xoay trong nút",
        "Trên 3 giây: phải nói rõ đang làm gì, không để vòng xoay trống trơn",
        "Luôn có đường thoát khi lỗi, kèm cách khắc phục và hotline 0981875139"
      ],
      "accessibility": "prefers-reduced-motion: reduce phải tắt animation của .loading-letter, .letter-shadow, .sparkle, .skeleton, .btn-spinner. Màn hình tải thêm role=\"status\" aria-live=\"polite\"."
    }
  },

  "iconography": {
    "library": "Lucide (https://unpkg.com/lucide@0.460.0)",
    "style": "stroke only, stroke-width 2, không dùng icon fill đặc",
    "size": { "inline": "16px", "button": "18px", "feature": "24-32px" },
    "color": "Kế thừa màu chữ (currentColor) hoặc var(--primary-color) khi làm điểm nhấn",
    "rule": "Không trộn nhiều bộ icon trong cùng một trang. Không dùng emoji thay icon trong UI."
  },

  "imagery": {
    "style": "Ảnh thật, người thật, ánh sáng ấm, có nụ cười. Ưu tiên bối cảnh Việt Nam.",
    "avoid": "Stock photo doanh nhân bắt tay generic, ảnh AI có tay lỗi, ảnh xám lạnh",
    "treatment": "border-radius 20px. Ảnh nền có chữ đè phải phủ lớp linear-gradient(rgba(45,45,45,.55), rgba(45,45,45,.55))",
    "format": "WebP, có width/height, loading=lazy trừ ảnh hero",
    "og_image": "1200x630px, logo góc trái, chữ ≤ 8 từ"
  },

  "accessibility": {
    "target": "WCAG 2.1 AA",
    "rules": [
      "Tỉ lệ tương phản chữ thường ≥ 4.5:1, chữ ≥ 24px hoặc ≥ 19px bold ≥ 3:1",
      "Không dùng #FF69B4 hay #FFAEC9 làm màu chữ trên nền trắng",
      "Vùng chạm tối thiểu 44x44px",
      "Luôn giữ focus ring nhìn thấy được (outline 2px var(--primary-deep), offset 2px)",
      "Không truyền tải thông tin chỉ bằng màu, luôn kèm icon hoặc chữ",
      "Mọi ảnh có alt mô tả, ảnh trang trí dùng alt=''"
    ]
  },

  "web_conventions": {
    "clean_urls": "Link nội bộ, canonical và sitemap KHÔNG có đuôi .html",
    "lang": "html lang='vi' mặc định, i18n bằng cặp class .lang-vi / .lang-en",
    "favicon": "PNG từ CDN GitHub, khai báo cả rel='icon' và rel='apple-touch-icon'"
  },

  "content_source": {
    "critical": "File này quy định HÌNH THỨC (màu, font, component). Nó KHÔNG chứa NỘI DUNG (dịch vụ nào, giá bao nhiêu, bài viết gì). Nội dung thay đổi liên tục và chỉ có một nguồn đúng.",
    "must_read": "https://vuicuoilen.vn/llms.txt",
    "rule": "TUYỆT ĐỐI KHÔNG bịa nội dung site. Không tự nghĩ tên dịch vụ, không tự đặt giá, không tự chế tiêu đề bài viết, không tự tạo đường dẫn. llms.txt được sinh động từ dữ liệu thật trong KV, luôn đúng tại thời điểm đọc. Bịa một mức giá sai là làm hại khách hàng thật.",
    "where_to_look": {
      "màu, font, component, quy tắc thiết kế": "https://vuicuoilen.vn/data/brand.json",
      "danh sách dịch vụ, giá, mô tả": "https://vuicuoilen.vn/llms.txt",
      "bài viết blog, chuyên mục, tiêu đề": "https://vuicuoilen.vn/llms.txt",
      "cấu trúc URL, biểu mẫu, chính sách": "https://vuicuoilen.vn/llms.txt",
      "toàn bộ URL đang có": "https://vuicuoilen.vn/sitemap.xml",
      "chi tiết một trang cụ thể": "đọc thẳng chính trang đó"
    },
    "llms_txt_contains": [
      "Giới thiệu công ty và thông tin liên hệ chính thức",
      "Cấu trúc URL đầy đủ, dùng để đặt link nội bộ cho đúng",
      "Danh sách dịch vụ kèm mô tả và giá từng gói, lấy trực tiếp từ KV",
      "Danh sách bài viết blog kèm tiêu đề, chuyên mục và đường dẫn",
      "Biểu mẫu đang mở cho khách điền",
      "Chính sách, đội ngũ, thống kê",
      "Tóm tắt bộ nhận diện và link tới bốn file brand"
    ]
  },

  "ai_agent_instructions": [
    "Đọc https://vuicuoilen.vn/llms.txt TRƯỚC khi nhắc tới bất kỳ dịch vụ, giá, bài viết hay đường dẫn nào của site. Không bịa.",
    "Import css/brand-tokens.css trước mọi stylesheet khác, luôn dùng var(--token) thay vì hardcode hex.",
    "Không tự sinh màu mới. Cần sắc độ khác thì dùng biến sẵn có hoặc rgba() của màu brand.",
    "Font duy nhất là Nunito. Không thêm font thứ hai.",
    "Trước khi đặt chữ lên nền màu, kiểm tra field text_safe trong colors.",
    "Viết tiếng Việt theo mục voice: không dùng em dash, không hứa hẹn tuyệt đối.",
    "Nút chính mỗi màn hình chỉ có một, dùng .btn.btn-primary.",
    "Icon dùng Lucide stroke, không dùng emoji trong UI.",
    "Mọi khối logo bọc trong <a href=\"/\">, xem logo.link_rule.",
    "Thanh cuộn dùng gradient hồng chuẩn VCL, xem components.scrollbar. Không để mặc định xám.",
    "Có trạng thái tải đầy đủ, xem components.loading_states. Nút submit BẮT BUỘC có khối finally.",
    "Đoạn văn tiếng Việt line-height 1.8, có khối prefers-reduced-motion."
  ]
}
