.form-row { flex: 1; }


/* ========== BUTTONS & LABELS ========== */
:root {
    --toolbar-btn-radius: .3rem;
}

.btn, .label {
    border: none;
    border-radius: var(--toolbar-btn-radius);
    box-sizing: border-box;
    color: #f3f3f3;
    font-family: "Inter var", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    font-size: 0.75rem !important;
    font-weight: 500;
    line-height: 1.35rem;
    margin: 0;
    padding: .25rem .6rem;
    text-align: center;
    text-decoration: none;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.06);
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .3rem;
    transition: background-color .2s ease, box-shadow .2s ease, transform .1s ease;
    -webkit-tap-highlight-color: transparent;
}

.label { background-color: #888; }
.btn { background-color: #9f9f9f; }
/* :not([disabled]) — nút đang khoá không được đổi nền khi rê chuột. Bộ
   admin/controls.css nạp SAU cũng chặn y hệt; thiếu chặn ở đây thì nút khoá
   rơi về đúng màu xanh nhạt này. */
.btn:hover:not([disabled]) {
    background-color: rgb(114, 184, 253);
    box-shadow: 0 2px 6px rgba(114, 184, 253, 0.35);
}
.btn:focus {
    outline: 2px solid transparent;
    outline-offset: 2px;
}
.btn:focus-visible {
    box-shadow: 0 0 0 2px rgba(114, 184, 253, 0.5);
}
.btn:active {
    transform: scale(0.97);
}

@media only screen and (max-width: 860px) { .btn { font-size: 0.8rem; } }

@media only screen and (max-width: 600px) {
    .btn,
    .label {
        font-size: min(calc(12 * 100vw / 380), 12px) !important;
        line-height: min(calc(21.6 * 100vw / 380), 21.6px);
        padding: min(calc(5 * 100vw / 380), 5px) min(calc(9.6 * 100vw / 380), 9.6px) min(calc(4 * 100vw / 380), 4px) min(calc(9.6 * 100vw / 380), 9.6px);
        min-height: min(calc(29.6 * 100vw / 380), 29.6px);
    }
}

@media only screen and (min-width: 381px) and (max-width: 600px) {
    .btn,
    .label {
        padding: min(calc(4 * 100vw / 380), 4px) min(calc(9.6 * 100vw / 380), 9.6px) min(calc(4 * 100vw / 380), 4px) min(calc(9.6 * 100vw / 380), 9.6px);
    }
}

@media only screen and (max-width: 380px) {
    .btn,
    .label {
        font-size: min(calc(12 * 0.85 * 100vw / 380), 10.2px) !important;
        line-height: min(calc(21.6 * 0.85 * 100vw / 380), 18.36px);
        padding: min(calc(5 * 0.85 * 100vw / 380), 4.25px) min(calc(9.6 * 0.85 * 100vw / 380), 8.16px) min(calc(4 * 0.85 * 100vw / 380), 3.4px) min(calc(9.6 * 0.85 * 100vw / 380), 8.16px);
        min-height: min(calc(29.6 * 0.85 * 100vw / 380), 25.16px);
    }
}

.btn-white { background: #FFF; color: #333; }
.btn-green { background-color: #43a047; color: #FFF; }
.btn-red { background: #ef4444; color: #FFF; }
.btn-orange { background: #f97316; color: #FFF; }
.btn-blue { background-color: #3b82f6; color: #FFF; }
.btn-blue-light { background-color: #bfdbfe !important; color: #1e40af !important; }
.btn-gray { background: #6b7280; color: #FFF; }

/* Nút nhỏ hơn .btn — dùng trong list/card (hành động phụ) */
.btn-sm {
    border: none;
    border-radius: .2rem;
    box-sizing: border-box;
    color: #f3f3f3;
    font-family: "Inter var", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    font-size: 0.6875rem !important;
    font-weight: 500;
    line-height: 1;
    height: 24px;
    min-height: 24px;
    margin: 0;
    padding: 0 .5rem;
    text-align: center;
    text-decoration: none;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
    cursor: pointer;
    user-select: none;
    touch-action: manipulation;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: #9f9f9f;
    transition: background-color .2s ease, box-shadow .2s ease, transform .1s ease;
    -webkit-tap-highlight-color: transparent;
}

.btn-sm:hover {
    background-color: rgb(114, 184, 253);
    box-shadow: 0 2px 5px rgba(114, 184, 253, 0.3);
}

.btn-sm:active {
    transform: scale(0.97);
}

@media only screen and (max-width: 600px) {
    .btn-sm {
        height: min(calc(24 * 100vw / 400), 24px);
        min-height: min(calc(24 * 100vw / 400), 24px);
        font-size: min(calc(11 * 100vw / 400), 11px) !important;
        padding: 0 min(calc(8 * 100vw / 400), 8px);
    }
}

@media only screen and (max-width: 380px) {
    .btn-sm {
        height: min(calc(20 * 100vw / 400), 20px);
        min-height: min(calc(20 * 100vw / 400), 20px);
        font-size: min(calc(10 * 100vw / 400), 10px) !important;
        padding: 0 min(calc(7 * 100vw / 400), 7px);
    }
}

/* ========== FORM ELEMENTS ========== */
.form-select {
    width: 100%;
    max-width: 100%;
    overflow-x: hidden;
    display: block;
    font-size: 0.85rem;
    font-family: inherit;
    font-weight: 500;
    color: #333;
    line-height: 1.4;
    box-sizing: border-box;
    margin: 0;
    border: none;
    border-bottom: 1px solid #e3e3e3;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    outline: none;
    box-shadow: none;
    background-color: transparent;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0 center;
    background-size: .65rem auto;
    padding-left: 0;
    padding-right: 1.25rem;
    transition: border-color .2s ease, color .2s ease;
}

.form-select::-ms-expand { display: none; }
.form-select:hover { border-bottom-color: #888; }
.form-select:focus {
    border-bottom-color: #3b82f6;
    box-shadow: none;
    color: #222;
    outline: none;
}
.form-select option { font-weight: normal; }

option { color: black; font-size: 0.875rem; }

.form-input {
    width: 100%;
    background-color: transparent;
    color: #333;
    padding: 0 0 2px 0;
    font-weight: 400;
    font-size: 0.875rem;
    line-height: 1.5;
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, Helvetica, sans-serif;
    display: flex;
    outline: none;
    border: none;
    border-radius: 0;
    appearance: none;
    border-bottom: 1px solid #e3e3e3;
    resize: none;
    transition: border-color .2s ease;
}

.form-input:focus {
    border-bottom-color: #3b82f6;
}

@media only screen and (min-width: 381px) {
    .form-input { font-size: 0.8125rem; }
}

/* Wrapper .form-input (div) — đồng bộ chiều cao với input.form-input / select trong grid */
div.form-input {
    align-items: center;
    box-sizing: border-box;
    min-height: calc(0.8125rem * 1.5 + 3px);
}

div.form-input:focus-within {
    border-bottom-color: #3b82f6;
}

div.form-input .input-money,
div.form-input .input-plain {
    height: auto;
    line-height: 1.5;
    flex: 1;
    min-width: 0;
    width: auto;
    margin-left: 0;
}

.money-label,
div.form-input > span {
    float: none;
    flex-shrink: 0;
    line-height: 1.5;
    height: auto;
    text-align: right !important;
}

.money-label {
    width: 20px;
    min-width: 20px;
}

.money-label::after {
    content: '₫';
    text-align: right !important;
}

.input-money {
    border: none;
    outline: none;
    margin: 0;
    padding: 0;
    background-color: transparent;
    width: calc(100% - 20px);
    height: 100%;
    transition: border-color .2s ease;
}

.editor {
    width: 100%;
    background-color: transparent;
    resize: none;
    font-size: 0.85rem;
    line-height: 1.5;
    padding: 0 0 3px 0;
    color: #333;
    outline: none;
    border: none;
    border-radius: 0;
    appearance: none;
    border-bottom: 1px solid #e3e3e3;
    transition: border-color .2s ease;
}

.editor:focus {
    border-bottom-color: #3b82f6;
}

.editor img { max-width: 100%; }
.editor p img { max-width: 100%; }


.form-group { margin-bottom: 1rem }

/* Icon lịch vẽ bằng CSS, đặt BÊN TRÁI ô.

   Vì sao phải tự vẽ: iOS Safari KHÔNG bao giờ hiện icon cho input[type=date] —
   nó chỉ in giá trị rồi mở bánh xe chọn ngày khi chạm. Chrome máy tính thì có
   icon, nhưng nằm bên PHẢI và do trình duyệt vẽ (::-webkit-calendar-picker-
   indicator). Nên nếu không tự vẽ thì iOS trống trơn, mà mỗi nền tảng lại một
   kiểu. Tự vẽ là cách duy nhất để bảy site trông giống nhau ở mọi máy.

   ⚠ Đã gỡ `appearance: textfield`. Trên WebKit nó bỏ trang trí gốc của ô ngày;
   .form-input ngay trên đã khai `appearance: none` rồi nên dòng đó vừa thừa
   vừa làm ô ngày lệch kiểu so với các ô khác.

   Ô này là kiểu gạch chân (nền trong suốt, chỉ có border-bottom), nên icon nằm
   sát mép trái, chữ lùi vào 18px. KHÔNG đặt background-color ở đây — để
   .form-input giữ quyền, nếu không là mất nền trong suốt.

   ⚠ Khe hở giữa icon và chữ KHÔNG bằng (padding-left − background-size).
   Icon là SVG viewBox 24 nhưng hình chỉ vẽ từ x=3 đến x=21, tức mỗi bên còn
   ~12,5% trống; ở cỡ 15px là thêm ~1,9px trắng bên phải. Nên 18px cho khe tính
   toán 3px nhưng nhìn ra ~5px. Bản đầu để 22px (khe 7px, nhìn ra ~9px) bị chê
   là xa quá. Muốn chỉnh nữa thì so bằng mắt trên trang thử, đừng tính nhẩm.

   Selector input[type="date"] có độ đặc hiệu (0,1,1), thắng .form-input (0,1,0),
   nên không phụ thuộc thứ tự nạp file. */
input[type="date"] {
    display: block;
    min-height: 1.2rem;
    padding-left: 18px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23666666' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M3 10h18'/%3E%3Cpath d='M8 3v4'/%3E%3Cpath d='M16 3v4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: left center;
    background-size: 15px 15px;
}

/* Chrome/Edge vẫn vẽ icon riêng bên phải -> hai icon một ô. Cho nó trong suốt
   chứ KHÔNG `display: none`: ẩn hẳn là mất luôn vùng bấm mở lịch trên máy tính.
   Trên iOS không có phần tử giả này nên dòng dưới là vô hại. */
input[type="date"]::-webkit-calendar-picker-indicator {
    opacity: 0;
}

/* ⚠ CHỈ iOS mới cần khối này, và KHÔNG máy tính nào tái hiện được.

   iOS Safari gói giá trị ngày trong ::-webkit-date-and-time-value, và phần tử
   đó CĂN GIỮA theo bề ngang ô. Ô rộng bao nhiêu thì chữ dạt ra giữa bấy nhiêu:
   ảnh chụp iPhone ở ô rộng ~465px cho khe icon–chữ khoảng 110px, trong khi
   padding-left chỉ có 18px. Nhìn trên Chrome/Edge thì chữ đã sát trái sẵn nên
   KHÔNG thấy lỗi này — đừng kết luận "đã sửa xong" chỉ vì máy tính trông ổn.

   text-align trên chính thẻ input không đủ: nó không truyền vào phần tử giả kia.
   Phải khai thẳng vào pseudo. Khai cả hai cho chắc, cái trên vô hại ở mọi nơi. */
input[type="date"] {
    text-align: left;
}

input[type="date"]::-webkit-date-and-time-value {
    text-align: left;
}

/* ========== SPACING - MARGIN ========== */
.mr-auto { margin-right: auto; }

.ml-0 { margin-left: 0;}
.ml-5px { margin-left: 5px;}
.ml-10px { margin-left: 10px;}
.ml-15px { margin-left: 15px;}
.ml-20px { margin-left: 20px;}
.ml-25px { margin-left: 25px;}
.ml-30px { margin-left: 30px;}
.ml-1-percent { margin-left: 1%;}
.ml-2-percent { margin-left: 2%;}

.mr-0 { margin-right: 0; }
.mr-5px { margin-right: 5px; }
.mr-10px { margin-right: 10px; }
.mr-15px { margin-right: 15px; }
.mr-20px { margin-right: 20px; }
.mr-25px { margin-right: 25px; }
.mr-30px { margin-right: 30px; }
.mr-1-percent { margin-right: 1%;}
.mr-2-percent { margin-right: 2%;}


.mt-0 { margin-top: 0; }
.mt-1px { margin-top: 1px; }
.mt-2px { margin-top: 2px; }
.mt-3px { margin-top: 3px; }
.mt-4px { margin-top: 4px; }
.mt-5px { margin-top: 5px; }
.mt-10px { margin-top: 10px; }
.mt-20px { margin-top: 20px; }
.mt-30px { margin-top: 30px; }

.mb-0 { margin-bottom: 0; }
.mb-5px { margin-bottom: 5px; }
.mb-10px { margin-bottom: 10px; }
.mb-20px { margin-bottom: 20px; }
.mb-30px { margin-bottom: 30px; }
.mb-40px { margin-bottom: 40px; }
.mb-50px { margin-bottom: 50px; }
.mb-60px { margin-bottom: 60px; }
.mb-70px { margin-bottom: 70px; }
.mb-80px { margin-bottom: 80px; }
.mb-90px { margin-bottom: 90px; }
.mb-100px { margin-bottom: 100px; }

/* mt-scale / mb-scale: trước đây khai clamp() ở đây rồi style.css nạp sau lại
   đè bằng số cứng, nên giá trị clamp không bao giờ có tác dụng. Gom về một chỗ. */
.mt-scale { margin-top: 20px; }
.mb-scale { margin-bottom: 15px; }
.ml-scale { margin-left: clamp(6px, 1.5vw, 10px); }
.mr-scale { margin-right: clamp(6px, 1.5vw, 10px); }

.mt-scale-neg { margin-top: calc(-1 * clamp(6px, 1.5vw, 10px)) !important; }
.mb-scale-neg { margin-bottom: calc(-1 * clamp(6px, 1.5vw, 10px)) !important; }
.ml-scale-neg { margin-left: calc(-1 * clamp(6px, 1.5vw, 10px)) !important; }
.mr-scale-neg { margin-right: calc(-1 * clamp(6px, 1.5vw, 10px)) !important; }

/* ========== SPACING - PADDING ========== */
.padding-auto { padding: auto !important; }
.padding-5px { padding: 5px; } .padding-10px { padding: 10px; } .padding-15px { padding: 15px; } .padding-20px { padding: 20px; } .padding-25px { padding: 25px; } .padding-30px { padding: 30px; }
.padding-top-1px { padding-top: 1px; } .padding-top-2px { padding-top: 2px; } .padding-top-3px { padding-top: 3px; } .padding-top-4px { padding-top: 4px; }.padding-top-5px { padding-top: 5px; }
.padding-top-10px { padding-top: 10px; } .padding-top-20px { padding-top: 20px; } .padding-top-30px { padding-top: 30px; } .padding-top-40px { padding-top: 40px; }.padding-top-50px { padding-top: 50px; }
.padding-top-60px { padding-top: 60px; } .padding-top-70px { padding-top: 70px; } .padding-top-80px { padding-top: 80px; } .padding-top-90px { padding-top: 90px; }.padding-top-100px { padding-top: 100px; }
.padding-bottom-1px { padding-bottom: 1px; } .padding-bottom-2px { padding-bottom: 2px; } .padding-bottom-3px { padding-bottom: 3px; } .padding-bottom-4px { padding-bottom: 4px; } .padding-bottom-5px { padding-bottom: 5px; }
.padding-bottom-10px { padding-bottom: 10px; } .padding-bottom-20px { padding-bottom: 20px; } .padding-bottom-30px { padding-bottom: 30px; } .padding-bottom-40px { padding-bottom: 40px; } .padding-bottom-50px { padding-bottom: 50px; }
.padding-bottom-60px { padding-bottom: 60px; } .padding-bottom-70px { padding-bottom: 70px; } .padding-bottom-80px { padding-bottom: 80px; } .padding-bottom-90px { padding-bottom: 90px; } .padding-bottom-100px { padding-bottom: 100px; }

/* ========== SIZING - WIDTH ========== */
.w10 { width: 10%; } .w20 { width: 20%; } .w30 { width: 30%; } .w40 { width: 40%; } .w50 { width: 50%; }
.w15 { width: 15%; } .w25 { width: 25%; } .w35 { width: 35%; } .w45 { width: 45%; } .w55 { width: 55%; }
.w60 { width: 60%; } .w70 { width: 70%; } .w80 { width: 80%; } .w90 { width: 90%; } .w98 { width: 98%; }
.w65 { width: 65%; } .w75 { width: 75%; } .w85 { width: 85%; } .w95 { width: 95%; } .w100 { width: 100%; }

.width-auto { width: auto; }
.width-10px { width: 10px; } .width-20px { width: 20px; } .width-30px { width: 30px; } .width-40px { width: 40px; } .width-50px { width: 50px; }
.width-60px { width: 60px; } .width-70px { width: 70px; } .width-80px { width: 80px; } .width-90px { width: 90px; } .width-100px { width: 100px; }
.width-110px { width: 110px; } .width-120px { width: 120px; } .width-130px { width: 130px; } .width-140px { width: 140px; } .width-150px { width: 150px; }
.width-160px { width: 160px; } .width-170px { width: 170px; } .width-180px { width: 180px; } .width-190px { width: 190px; } .width-200px { width: 200px; }
.width-210px { width: 210px; } .width-220px { width: 220px; } .width-230px { width: 230px; } .width-240px { width: 240px; } .width-250px { width: 250px; }
.width-260px { width: 260px; } .width-270px { width: 270px; } .width-280px { width: 280px; } .width-290px { width: 290px; } .width-300px { width: 300px; }
.width-350px { width: 350px; } .width-400px { width: 400px; } .width-450px { width: 450px; } .width-500px { width: 500px; } .width-550px { width: 550px; }
.width-600px { width: 600px; }

/* ========== SIZING - HEIGHT ========== */
.height-auto { height: auto; }
.height-10px { height: 10px; } .height-15px { height: 15px; } .height-20px { height: 20px; } .height-25px { height: 25px; } .height-30px { height: 30px; }
.height-50px { height: 50px; } .height-100px { height: 100px; } .height-150px { height: 150px; }
.height-200px { height: 200px; } .height-250px { height: 250px; } .height-300px { height: 300px; }
.height-350px { height: 350px; } .height-400px { height: 400px; } .height-500px { height: 500px; }
.height-800px { height: 800px; } .height-1000px { height: 1000px; } .height-1500px { height: 1500px; }
.height-2000px { height: 2000px; } .height-2500px { height: 2500px; } .height-3000px { height: 3000px; }

/* ========== TYPOGRAPHY ========== */
.font-size-inherit { font-size: inherit; }
.font-size-90 { font-size: 0.9rem; }
.font-size-80 { font-size: 0.8rem; }

.font-weight-300 { font-weight: 300; }
.font-weight-400 { font-weight: 400; }
.font-weight-500 { font-weight: 500; }
.font-weight-bold { font-weight: bold; }

.font-style-italic { font-style: italic; }
.font-style-normal { font-style: normal; }
.font-style-inherit { font-style: inherit; }

.text-left { text-align: left; }
.text-center { text-align: center !important; }
.text-right { text-align: right; }

.text-decoration-none { text-decoration: none !important; }
.text-decoration-line-through { text-decoration: line-through !important; }
.text-decoration-underline { text-decoration: underline; }

.line-height-1-3 { line-height: 1.3; }
.line-height-1-5 { line-height: 1.5; }

.uppercase { text-transform: uppercase; }
.lowercase { text-transform: lowercase; }
.capitalize { text-transform: capitalize; }

/* ========== COLORS ========== */
.bg-red { background-color: #d71f32 !important; }
.bg-orange { background-color: #ff6600 !important; }
.bg-green { background-color: #728540 !important; }
.bg-medium-sea-green { background-color: #3CB371 !important; }
.bg-grey { background-color: #555 !important; }
.bg-silver { background-color: #999 !important; }
.bg-white { background-color: #FFF !important; }
.bg-ash { background-color: #eaeaeb !important; }
.bg-black { background-color: #333 !important; }
.bg-turquoise { background-color: #189c86 !important; }
.bg-smoke { background-color: #d7d7d7 !important; }
.bg-light-red { background-color: #f9be9c !important; }
.bg-sage { background-color: #e8ecdd !important; }

.color-red { color: #d71f32 !important; }
.color-orange { color: #ff6600 !important; }
.color-green { color: #506d15 !important; }
.color-blue { color: #234cc5 !important; }
.color-grey { color: #555 !important; }
.color-white { color: #FFF !important; }
.color-black { color: #111 !important; }
.color-turquoise { color: #098974 !important; }

/* ========== BORDERS ========== */
.border { border: 1px solid #e3e3e3; }
.border-none { border: none !important; }
.border-top { border-top: 1px solid #e3e3e3; }
.border-bottom { border-bottom: 1px solid #e3e3e3; }
.border-left { border-left: 1px solid #e3e3e3; }
.border-right { border-right: 1px solid #e3e3e3; }

.rounded-0 { border-radius: 0; }
.rounded-3px { border-radius: 3px; }
.rounded-5px { border-radius: 5px; }
.rounded-8px { border-radius: 8px; }
.rounded-10px { border-radius: 10px; }
.rounded-12px { border-radius: 12px; }
.rounded-15px { border-radius: 15px; }
.rounded-20px { border-radius: 20px; }
.rounded-full { border-radius: 50%; }

.horizontal-line { width: 100%; height: 1px; background-color: #e3e3e3; }

/* ========== EFFECTS - SHADOWS ========== */
.shadow-none { box-shadow: none !important; }
.shadow-sm { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); }
.shadow { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); }
.shadow-md { box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }
.shadow-lg { box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1); }
.shadow-xl { box-shadow: 0 20px 25px rgba(0, 0, 0, 0.15); }

/* ========== EFFECTS - OPACITY ========== */
.opacity-0 { opacity: 0 !important; }
.opacity-25 { opacity: 0.25 !important; }
.opacity-50 { opacity: 0.5 !important; }
.opacity-75 { opacity: 0.75 !important; }
.opacity-100 { opacity: 1 !important; }

/* ========== LAYOUT - POSITION ========== */
.position-relative { position: relative !important; }
.position-static { position: static; }
.position-sticky { position: sticky; }
.position-absolute { position: absolute; }
.position-fixed { position: fixed; }

.top-0 { top: 0; } .top-5px { top: 5px; } .top--5px { top: -5px; } .top-10px { top: 10px; } .top--10px { top: -10px; } .top-20px { top: 20px; } .top--20px { top: -20px; }
.top-25px { top: 25px; } .top--25px { top: -25px; } .top--30px { top: -30px; }

.bottom-0 { bottom: 0; } .bottom-5px { bottom: 5px; } .bottom--5px { bottom: -5px; } .bottom-10px { bottom: 10px; } .bottom--10px { bottom: -10px; } .bottom-20px { bottom: 20px; } .bottom--20px { bottom: -20px; }
.bottom-25px { bottom: 25px; } .bottom--25px { bottom: -25px; } .bottom--30px { bottom: -30px; }

.left-0 { left: 0; } .left-5px { left: 5px; } .left--5px { left: -5px; } .left-10px { left: 10px; } .left--10px { left: -10px; } .left-20px { left: 20px; } .left--20px { left: -20px; }
.left-25px { left: 25px; } .left--25px { left: -25px; } .left--30px { left: -30px; }

.right-0 { right: 0; } .right-5px { right: 5px; } .right--5px { right: -5px; } .right-10px { right: 10px; } .right--10px { right: -10px; } .right-20px { right: 20px; } .right--20px { right: -20px; }
.right-25px { right: 25px; } .right--25px { right: -25px; } .right--30px { right: -30px; }

/* Position scale — 5px…10px theo width (cùng mốc mt-scale / 400) */
.top-scale { top: clamp(5px, calc(10 * 100vw / 400), 10px); }
.right-scale { right: clamp(5px, calc(10 * 100vw / 400), 10px); }
.bottom-scale { bottom: clamp(5px, calc(10 * 100vw / 400), 10px); }
.left-scale { left: clamp(5px, calc(10 * 100vw / 400), 10px); }

.z-index-999 { z-index: 999; } .z-index-888 { z-index: 888; } .z-index-777 { z-index: 777; } .z-index-666 { z-index: 666; } .z-index-555 { z-index: 555; } .z-index-444 { z-index: 444; } .z-index-333 { z-index: 333; } .z-index-222 { z-index: 222; } .z-index-111 { z-index: 111; }

/* ========== LAYOUT - DISPLAY ========== */
.display-none { display: none !important; }
.display-inline-block { display: inline-block !important; }
.display-block { display: block !important; }
.display-flex-row { display: flex; flex-direction: row; }
.display-flex-column { display: flex; flex-direction: column; }
.display-grid { display: grid; }

.float-left { float: left !important; }
.float-right { float: right !important; }
.flex { display: flex !important; }

.clearfix { width:100%; clear: both; }

.overflow-hidden { overflow: hidden; }
.overflow-auto { overflow: auto; }
.overflow-visible { overflow: visible; }
.overflow-scroll { overflow: scroll; }

/* ========== LAYOUT - FLEXBOX ========== */
.flex-1 { flex: 1; }
.flex-auto { flex: auto; }
.flex-none { flex: none; }

.flex-row { flex-direction: row; }
.flex-column { flex-direction: column; }

.flex-wrap { flex-wrap: wrap; }
.flex-nowrap { flex-wrap: nowrap; }

.items-start { align-items: flex-start; }
.items-center { align-items: center; }
.items-end { align-items: flex-end; }
.items-stretch { align-items: stretch; }
.items-baseline { align-items: baseline; }

.justify-start { justify-content: flex-start; }
.justify-center { justify-content: center; }
.justify-end { justify-content: flex-end; }
.justify-between { justify-content: space-between; }
.justify-around { justify-content: space-around; }
.justify-evenly { justify-content: space-evenly; }

.gap-0 { gap: 0; }
.gap-5px { gap: 5px; }
.gap-10px { gap: 10px; }
.gap-15px { gap: 15px; }
.gap-20px { gap: 20px; }
.gap-25px { gap: 25px; }
.gap-30px { gap: 30px; }

/* ========== LAYOUT - GRID ========== */
.grid-cols-1 { grid-template-columns: repeat(1, 1fr); }
.grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
.grid-cols-5 { grid-template-columns: repeat(5, 1fr); }
.grid-cols-6 { grid-template-columns: repeat(6, 1fr); }



/* ========== UTILITIES - CURSOR ========== */
.cursor-pointer { cursor: pointer; }
.cursor-default { cursor: default; }
.cursor-not-allowed { cursor: not-allowed; }
.cursor-move { cursor: move; }
.cursor-grab { cursor: grab; }
.cursor-text { cursor: text; }

/* ========== UTILITIES - OBJECT FIT ========== */
.object-cover { object-fit: cover; }
.object-contain { object-fit: contain; }
.object-fill { object-fit: fill; }
.object-none { object-fit: none; }
.object-scale-down { object-fit: scale-down; }

/* ========== UTILITIES - MISC ========== */
.img-fluid { max-width: 100%; }
video { max-width: 100%; }
strong { font-weight: bold; }
p { font-size: 0.875rem; }
span { font-size: 0.875rem; }

/* Mặc định là lỗi (đỏ). View nào báo thành công thì thêm .success —
   trước đây không có quy tắc này nên class="message success" vẫn ra màu đỏ. */
/* Hộp thông báo. Mặc định đỏ (báo lỗi); view báo thành công thì thêm .success —
   trước đây không có quy tắc đó nên class="message success" vẫn hiện màu đỏ. */
.message {
    color: Crimson;
    font-size: 0.9rem;
    font-style: normal;
    font-family: Arial, Helvetica, sans-serif;
}

.message--success { color: #2e7d32; }
.message--error   { color: Crimson; }

#alert-copy {
    width: 100px;
    height: 30px;
    padding: 5px 10px;
    border-radius: 18px;
    font-weight: normal;
    color: #FFF;
    font-size: 0.8125rem;
    background-color: #222;
    opacity: .8;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    text-align: center;
    display: none;
}

/* ========== COMPONENTS - CHECKBOX SWITCH ========== */
.switch {
    position: relative;
    display: inline-block;
    width: 55px;
    height: 16px;
    margin-bottom: 20px;
}

.switch input {
    opacity: 0;
    width: 0;
    height: 0;
}

.switch-track {
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: #ccc;
    -webkit-transition: .4s;
    transition: .4s;
    border-radius: 5px;
}

.switch-track:before {
    position: absolute;
    content: "";
    height: 12px;
    width: 24px;
    left: 2px;
    bottom: 2px;
    border-radius: 5px;
    background-color: white;
    -webkit-transition: .4s;
    transition: .4s;
}

input:checked + .switch-track {
    background-color: #454545;
}

input:focus + .switch-track {
    box-shadow: 0 0 1px #2196F3;
}

input:checked + .switch-track:before {
    -webkit-transform: translateX(26px);
    -ms-transform: translateX(26px);
    transform: translateX(26px);
}

.notification-error {
    background-color: #f8d7da;
    color: #721c24;
    padding: 10px 15px;
    border: 1px solid #f5c6cb;
    border-radius: 4px;
    font-size: 0.875rem;
}

/* MỘT kiểu duy nhất cho mọi báo thành công.
   .alert-success là bản sinh đôi của class này ở thongke (13 trang xoá dữ
   liệu) — cùng #d4edda / #c3e6cb / #155724, chỉ khác tên. Gộp selector ở đây
   thay vì nhân đôi quy tắc; bản khai riêng trong thongke/admin/data-deletion.css
   đã gỡ, nếu không nó nạp sau và giành lại. */
.notification-success,
.alert-success {
    background-color: #d4edda;
    color: #155724;
    padding: 10px 15px;
    border: 1px solid #c3e6cb;
    border-radius: 4px;
    font-size: 0.875rem;
    /* Báo thành công nổi lên giữa trên rồi tự tắt sau khoảng 1 giây, thay vì
       nằm lì trong luồng trang.

       Làm bằng animation chứ không bằng JS: thẻ này do session('success') in
       ra lúc render, không có mã nào đụng tới nó nên thêm JS là phải bịa ra
       một file mới rồi đồng bộ sang sáu site. `forwards` giữ trạng thái cuối
       (trong suốt + visibility:hidden) nên tắt xong nó không chiếm chỗ và
       không chắn chuột.

       z-index 10052: nằm trên khay popup (10050/10051) nhưng dưới lớp trên
       cùng 10053, để nó không đè mất nút xác nhận nào.

       Chỉ .notification-success mới tự tắt. .notification-error ngay trên vẫn
       nằm im trong luồng — báo lỗi mà biến mất sau 1 giây thì người dùng chưa
       kịp đọc đã mất. */
    /* Căn giữa trang bằng inset:0 + margin:auto, KHÔNG dùng top/left 50% +
       translate(-50%,-50%): thẻ fixed co theo nội dung, mà với left:50% thì
       chỗ trống nó được tính chỉ còn nửa màn bên phải — đo ở 375px ra popup
       rộng 187.5px, chữ bị ép xuống ba dòng. left/right 0 cho chỗ trống là
       trọn bề ngang màn hình nên nội dung được rộng đúng cỡ nó cần.
       Chiều dọc: đỉnh popup cách mép trên 40% chiều cao màn hình — cao hơn
       giữa trang một chút, đúng tầm mắt. transform để trống cho animation. */
    position: fixed;
    top: 40%;
    left: 0;
    right: 0;
    bottom: auto;
    width: fit-content;
    height: fit-content;
    margin-left: auto;
    margin-right: auto;
    z-index: 10052;
    max-width: min(92vw, 420px);
    /* Bóng toả rộng và mềm: cái này nổi giữa trang, ngay trên nội dung, không
       có lớp phủ nào tách nó khỏi nền — nên cần bóng đủ rộng thì mới thấy nó
       tách ra. Đi theo hướng TOẢ RỘNG chứ không phải đậm màu: bán kính nhoè
       lớn với độ đục thấp cho ra vệt mềm, còn đục cao thì thành viền xám cứng
       quanh hộp.
       Ba lớp: viền sát mép cho rõ hình, lớp giữa nhấc hộp lên, lớp ngoài toả
       xa xuống nền. */
    box-shadow: 0 0 0 1px rgba(16, 24, 40, .05),
                0 8px 26px rgba(16, 24, 40, .10),
                0 26px 70px -10px rgba(16, 24, 40, .22);
    pointer-events: none;
    animation: notification-success-pop 1.3s ease forwards;
}

@keyframes notification-success-pop {
    0%   { opacity: 0; visibility: visible; transform: scale(.94); }
    12%  { opacity: 1; visibility: visible; transform: scale(1); }
    88%  { opacity: 1; visibility: visible; transform: scale(1); }
    100% { opacity: 0; visibility: hidden;  transform: scale(.98); }
}

/* Ai tắt hiệu ứng trong hệ điều hành thì không cho nó trượt: hiện ngay, giữ
   nguyên 1 giây rồi tắt. */
@media (prefers-reduced-motion: reduce) {
    .notification-success,
    .alert-success { animation-name: notification-success-fade; }

    @keyframes notification-success-fade {
        0%, 88% { opacity: 1; visibility: visible; }
        100%    { opacity: 0; visibility: hidden; }
    }
}
/* Ô chờ khi lazy-load — vẽ hoàn toàn bằng CSS, không còn file ảnh nào.
   Trước đây src khởi tạo của MỌI ảnh trên site là public/images/loading.webp:
   vòng tròn xoay dạng WebP động 30 frame, 91.738 byte (sau rút còn 1 frame tĩnh
   2.508 byte). Nay src khởi tạo là 1 pixel trong suốt dạng data URI
   (LazyImage::PLACEHOLDER) — không request, không byte ảnh, không giải mã — còn
   toàn bộ phần nhìn thấy là mấy lớp gradient bên dưới.
   Ảnh trong suốt 1x1 giữ nguyên tỉ lệ 1:1 như loading.webp 96x96 cũ, nên các
   ảnh chỉ đặt width trong CSS (product-list) không bị đổi chiều cao lúc chờ.

   BA SITE, BA KIỂU, CHUNG MỘT HTML:
   shopsieuthi, shopyeu365 và shop123yeu chạy chung mã nguồn nên không thể phân
   biệt bằng markup. Kiểu chờ chọn qua thuộc tính data-lazy trên thẻ <html> —
   layout in ra từ config('lazy.style') (biến LAZY_LOADING_STYLE trong .env của
   từng site), còn màu lấy từ settings.color_theme trong DB. Blade và file CSS
   giữ nguyên cho cả ba.
       (mặc định)      spinner  — vòng tròn xoay, đuôi mờ dần
       data-lazy=blocks         — thanh chạy sọc dọc
       data-lazy=stripes        — thanh chạy sọc xiên
   Mọi kiểu đều vẽ trong một ô vuông/chữ nhật cố định tính bằng px, đặt giữa ảnh,
   nên vòng tròn không bị bóp thành bầu dục ở banner 200x100 và thanh chạy không
   dài ngoằng ở ảnh sản phẩm — thứ mà gradient căng theo % chắc chắn bị.

   Selector bám vào [data-src]: lazy-loading.js xoá thuộc tính này ngay khi ảnh
   thật được gán vào, nên cả nền lẫn hiệu ứng tự tắt đúng lúc. */

/* Góc quay và mức đầy phải khai báo kiểu thì mới chuyển động mượt được: biến CSS
   thường bị coi là chuỗi, animation sẽ nhảy cóc giữa 2 mốc thay vì nội suy. */
@property --lazy-angle {
    syntax: "<angle>";
    inherits: false;
    initial-value: 0deg;
}
@property --lazy-fill {
    syntax: "<percentage>";
    inherits: false;
    initial-value: 0%;
}

:root {
    --lazy-bg: #fff;           /* nền ô chờ. PHẢI đục chứ không được trong suốt:
                                  lớp trên cùng dùng đúng màu này để khoét lỗ
                                  giữa vòng tròn và che 4 góc ô vuông của
                                  conic-gradient. Để trắng cho liền với thẻ sản
                                  phẩm — chỉ nét vẽ mang màu thương hiệu. */
    --lazy-ink: 96, 102, 112;  /* màu nét vẽ, để dạng r,g,b cho rgba() dùng lại */
    --lazy-speed: 1s;
    --lazy-ring: 40px;         /* đường kính vòng xoay */
    --lazy-bar-w: min(96px, 62%);
    --lazy-bar-h: 12px;
    --lazy-stripe: 90deg;      /* hướng sọc của thanh chạy */
    --lazy-stripe-w: 7px;
}

/* Chọn img[data-src][src] (2 thuộc tính) chứ không phải img[data-src] là có chủ ý:
   ô chờ phải thắng các quy tắc nền theo trang như `.home-categories li img
   { background-color: #fff5f7 }` (1 class + 2 tag). Thuộc tính [src] luôn có mặt
   vì mọi ảnh lazy đều mang PLACEHOLDER. */
img[data-src][src] {
    background-color: var(--lazy-bg);
    background-repeat: no-repeat;
    background-position: center;
    /* Lớp trên: đổ màu nền vào lỗ giữa VÀ 4 góc ô vuông của conic-gradient, chỉ
       chừa lại đúng cái vành. Rẻ hơn mask (mask cắt cả background-color, mất
       luôn nền ô) và không cần thêm phần tử nào. */
    background-image:
        radial-gradient(closest-side,
            var(--lazy-bg) 0 56%,
            transparent 59% 95%,
            var(--lazy-bg) 98%),
        conic-gradient(from var(--lazy-angle),
            rgba(var(--lazy-ink), 0) 0turn,
            rgba(var(--lazy-ink), .9) 1turn);
    background-size: var(--lazy-ring) var(--lazy-ring);
    animation: lazy-spin var(--lazy-speed) linear infinite;
}
@keyframes lazy-spin {
    to { --lazy-angle: 360deg; }
}

/* Thanh chạy. Ba lớp đều cùng kích thước và cùng đặt giữa nên không phải tính
   toạ độ mép trái — phần đầy lớn dần bằng cách lớp che thu hẹp lại, chứ không
   phải bằng cách phóng to lớp sọc (phóng to thì mép trái tự dịch theo). */
:root[data-lazy="blocks"] img[data-src][src],
:root[data-lazy="stripes"] img[data-src][src] {
    background-image:
        linear-gradient(90deg,
            transparent 0 var(--lazy-fill),
            rgba(var(--lazy-ink), .14) var(--lazy-fill) 100%),
        repeating-linear-gradient(var(--lazy-stripe),
            rgba(var(--lazy-ink), .85) 0 var(--lazy-stripe-w),
            transparent var(--lazy-stripe-w) calc(var(--lazy-stripe-w) * 1.75)),
        linear-gradient(rgba(var(--lazy-ink), .14) 0 0);
    background-size: var(--lazy-bar-w) var(--lazy-bar-h);
    animation: lazy-fill calc(var(--lazy-speed) * 1.6) ease-in-out infinite;
}
/* Đầy trong 80% thời lượng rồi giữ 20%: có nhịp nghỉ thì mắt mới bắt được là nó
   chạy hết một lượt, chứ không phải giật cục. */
@keyframes lazy-fill {
    0%        { --lazy-fill: 0%; }
    80%, 100% { --lazy-fill: 100%; }
}

:root[data-lazy="stripes"] img[data-src][src] {
    --lazy-stripe: 115deg;
    --lazy-stripe-w: 5px;
}

/* Tắt chuyển động: giữ lại hình tĩnh (vòng tròn / thanh đầy một nửa) để ô vẫn
   nói được là "đang tải", chỉ bỏ phần quay và chạy. */
@media (prefers-reduced-motion: reduce) {
    img[data-src][src] {
        animation: none;
        --lazy-fill: 55%;
    }
}

/* ==========================================================================
   Utility đời cũ — giữ vì view ccg/manhhap/thongke còn dùng (18 class).
   Trái luật 1.5 (mã hoá giá trị vào tên) nên ĐỪNG dùng cho markup mới; sửa
   phải đi kèm bộ token, xem shopsieuthi/docs/DAT-TEN.md §3. Gom vào lib.css
   dùng chung ngày 2026-09-12; 29 class cùng khối không site nào dùng đã bỏ.
   ========================================================================== */
.select-css::-ms-expand { display: none; }
.select-css:hover { border-color: #888; }
.select-css:focus { border-color: #aaa; box-shadow: 0 0 0 3px -moz-mac-focusring; color: #222; outline: none; }
.select-css option { font-weight: normal; }
.font-family { font-family: Arial, Helvetica, sans-serif; }
.margin-auto { margin-right: auto; }
.margin-top-space { margin-top: 18px; }
.margin-bottom-space { margin-bottom: 15px; }
.margin-left-10px { margin-left: 10px; }
.margin-right-0 { margin-right: 0; }
.margin-right-5px { margin-right: 5px; }
.margin-right-10px { margin-right: 10px; }
.margin-right-20px { margin-right: 20px; }
.margin-top-5px { margin-top: 5px; }
.margin-top-10px { margin-top: 10px; }
.margin-top-20px { margin-top: 20px; }
.margin-bottom-10px { margin-bottom: 10px; }
.margin-bottom-20px { margin-bottom: 20px; }
.margin-bottom-30px { margin-bottom: 30px; }
.margin-bottom-40px { margin-bottom: 40px; }
.font-size-14px { font-size: 14px !important; }
.font-size-15px { font-size: 15px !important; }
.font-size-20px { font-size: 20px !important; }
