/*
File: ui-kit.css — QUY CHUẨN THIẾT KẾ "MODERN MINIMAL SAAS" của panel (task-52, phần 1; Owner 2026-10-09 21:30) + các thành phần dùng chung. Nạp ở layouts/head-style.php SAU apps.css, TRƯỚC motion.css
(mọi trang). Màu KHÔNG khai ở đây (bảng màu "Tím đêm": theme.css) — file này chỉ thêm token KHOẢNG CÁCH / BO GÓC / CỠ CHỮ / BÓNG + vài màu phụ (khối :root + [data-bs-theme="dark"]) và kiểu thành phần.
Luật dùng: .claude\rules\design-system.md. Quy tắc nhanh: khoảng cách chỉ lấy từ --kp-s-*; bo góc --kp-r-*; cỡ chữ --kp-fs-* (ít cấp), độ đậm 400 / 500 / 600; màu chỉ qua biến; icon chỉ khi giúp nhận diện thao tác.
*/

/* ================= 1. token ================= */
:root, [data-bs-theme="light"] {
    /* khoảng cách: 4 · 8 · 12 · 16 · 20 · 24 · 32 */
    --kp-s-1: 4px; --kp-s-2: 8px; --kp-s-3: 12px; --kp-s-4: 16px; --kp-s-5: 20px; --kp-s-6: 24px; --kp-s-7: 32px;
    /* bo góc: nút / ô nhập 8 · thẻ / hộp thoại 12 · huy hiệu tròn */
    --kp-r-sm: 6px; --kp-r-md: 8px; --kp-r-lg: 12px; --kp-r-pill: 999px;
    /* cỡ chữ: chú thích / huy hiệu 12 · phụ 13 · thân 14 · tiêu đề thẻ 16 · tiêu đề trang 20 · số liệu 24 (nổi bật 28) */
    --kp-fs-cap: 12px; --kp-fs-sm: 13px; --kp-fs-body: 14px; --kp-fs-title: 16px; --kp-fs-h: 20px; --kp-fs-num: 24px; --kp-fs-hero: 28px;
    --kp-fw-regular: 400; --kp-fw-medium: 500; --kp-fw-strong: 600;
    --kp-ctl-h: 40px; --kp-ctl-h-sm: 32px;
    --bs-font-sans-serif: "Be Vietnam Pro", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    --bs-body-font-family: var(--bs-font-sans-serif);
    /* bóng nhẹ (thẻ) / bóng rõ hơn (menu xổ, hộp thoại dùng --kp-dlg-shadow của theme.css) */
    --kp-sh-1: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .05);
    --kp-card-shadow: var(--kp-sh-1);
    --kp-btn-glow: 0 1px 2px rgba(79, 84, 201, .35);
    /* khối nền nhạt màu nhấn (ví, xem trước, ô được chọn) */
    --kp-tint-bg: #f4f5ff; --kp-tint-border: #dfe1fb;
    /* chấm màu trạng thái (ô số liệu) */
    --kp-dot-total: #4f54c9; --kp-dot-inactive: #8d91b3; --kp-dot-valid: #2e9e5b; --kp-dot-paused: #3b82f6; --kp-dot-expired: #e0951a; --kp-dot-blocked: #d1362b;
    /* thông báo nổi sau khi copy */
    --kp-toast-bg: #1b1d2e; --kp-toast-fg: #ffffff; --kp-toast-line: rgba(255, 255, 255, .72); --kp-toast-ok: #4ade80; --kp-toast-info: #93c5fd; --kp-toast-warn: #fbbf24; --kp-toast-err: #f87171;
}
[data-bs-theme="dark"] {
    --kp-sh-1: 0 1px 0 rgba(255, 255, 255, .04) inset;
    --kp-card-shadow: var(--kp-sh-1);
    --kp-btn-glow: 0 0 0 1px #7479ff inset, 0 2px 8px -2px rgba(93, 98, 224, .55);
    --kp-tint-bg: #171b3d; --kp-tint-border: #2c326a;
    --kp-dot-total: #aeb1ff; --kp-dot-inactive: #7d82a8; --kp-dot-valid: #4ade80; --kp-dot-paused: #60a5fa; --kp-dot-expired: #fbbf24; --kp-dot-blocked: #f87171;
    --kp-toast-bg: #2b3052; --kp-toast-fg: #ffffff; --kp-toast-line: rgba(255, 255, 255, .72); --kp-toast-ok: #4ade80; --kp-toast-info: #93c5fd; --kp-toast-warn: #fbbf24; --kp-toast-err: #f87171;
}

/* ================= 2. chữ + tiêu đề trang ================= */
body { font-family: var(--bs-font-sans-serif); }   /* cỡ chữ thân 14 px + dòng cao 1,5 của template (đã đo) */
.page-title-box { padding-bottom: var(--kp-s-4); }
.page-title-box h4 { font-size: var(--kp-fs-h) !important; font-weight: var(--kp-fw-strong); letter-spacing: -.005em; line-height: 1.3; margin-bottom: 0; }
.page-title-box .breadcrumb { font-size: var(--kp-fs-sm); }
@media (max-width: 991.98px), (pointer: coarse) { .page-title-box .breadcrumb-item > a { min-width: 44px; justify-content: center; } }   /* link ngắn ("Key list") vẫn đủ vùng chạm 44 px */
.page-title-box .breadcrumb-item > a { color: var(--bs-secondary-color); }
.page-title-box .breadcrumb-item > a:hover { color: var(--kp-link); }
.card-title, h5.card-title, h6.card-title { font-size: var(--kp-fs-title); font-weight: var(--kp-fw-strong); line-height: 1.35; }
.text-muted, .small, small { --kp-muted-fs: var(--kp-fs-sm); }
strong, b { font-weight: var(--kp-fw-strong); }

/* ================= 3. thẻ: 1 lớp, không lồng thẻ ================= */
.card { border: 1px solid var(--bs-border-color); border-radius: var(--kp-r-lg); box-shadow: var(--kp-sh-1); margin-bottom: var(--kp-s-4); }
.card .card { box-shadow: none; }                              /* thẻ lồng (nếu còn) phẳng: chỉ viền */
/* khoảng đệm thân thẻ giữ 20 px của template ở mọi khổ (đổi đệm làm đổi bề rộng chứa — Danh sách key đo ngưỡng bảng / thẻ theo nó, Sửa key ngắt dòng chuỗi key theo nó) */
/* khối nhạt nhấn (ví, xem trước): KHÔNG phải thẻ — nền tint, không bóng */
.kp-tint { background: var(--kp-tint-bg); border: 1px solid var(--kp-tint-border); border-radius: var(--kp-r-lg); }

/* ================= 4. nút ================= */
.btn { --bs-btn-border-radius: var(--kp-r-md); --bs-btn-padding-y: .5rem; --bs-btn-padding-x: 1rem; }   /* cỡ chữ + dòng cao của template (.btn 14 px / .btn-sm 12,25 px): icon căn theo nét vẽ đã đo ở các cỡ này */
.btn-sm { --bs-btn-border-radius: var(--kp-r-md); --bs-btn-padding-y: .25rem; --bs-btn-padding-x: .5rem; }   /* đệm + cỡ chữ của template (nút trong cột hẹp / thẻ vừa chữ English "Maintenance" ở 360 px) */

/* ================= 5. ô nhập, ô chọn, nhãn, radio / checkbox ================= */
.form-label { font-size: var(--kp-fs-body); font-weight: var(--kp-fw-medium); margin-bottom: 6px; }
.form-control, .form-select { border-radius: var(--kp-r-md); padding-top: .5625rem; padding-bottom: .5625rem; line-height: 1.4; }
.input-group > .form-control, .input-group > .form-select, .input-group > .input-group-text { line-height: 1.4; }
.input-group-text { color: var(--bs-secondary-color); font-weight: var(--kp-fw-medium); }
.form-text { font-size: var(--kp-fs-sm); color: var(--bs-secondary-color); margin-top: 6px; }
.invalid-feedback { font-size: var(--kp-fs-sm); }
.form-check-input { width: 1.125rem; height: 1.125rem; margin-top: .1875rem; }
.form-check-input[type="radio"] { border-width: 1.5px; }

/* ================= 6. huy hiệu (mềm, tròn) + thông báo trong trang ================= */
.badge { border-radius: var(--kp-r-pill); padding: .25em .45em; font-size: var(--kp-fs-cap); font-weight: var(--kp-fw-strong); letter-spacing: 0; }   /* dòng cao 1 của template: nhãn trong nút / hàng flex cân tâm với icon */
.alert { border-radius: var(--kp-r-md); padding: var(--kp-s-3) var(--kp-s-4); font-size: var(--kp-fs-body); border-width: 1px; }
.alert-heading { font-size: var(--kp-fs-body); font-weight: var(--kp-fw-strong); }

.btn .badge { top: 0; }   /* nhãn trong nút (vd. "đang lọc"): template nhấc nhãn lên 1 px — cân tâm với icon của nút */
.btn.noti-icon .badge { top: 12px; right: 4px; }   /* task-53: số đếm của chuông (position: absolute của template) đè góc trên-phải nét chuông — luật `.btn .badge { top: 0 }` ở trên cùng độ ưu tiên và đứng sau nên từng đẩy nó lên mép trên thanh (hồi quy task-52) */

/* ================= 7. bảng: chỉ kẻ ngang, đầu bảng nhạt ================= */
.table-bordered > :not(caption) > * > * { border-left-width: 0; border-right-width: 0; }
.table-bordered { border-left-width: 0; border-right-width: 0; }
.table-hover > tbody > tr:hover > * { --bs-table-bg-state: var(--bs-tertiary-bg); }

/* ================= 8. ô số liệu: nhãn nhỏ phía trên, số lớn phía dưới ================= */
.kp-stat { display: flex; flex-direction: column; gap: var(--kp-s-1); min-width: 0; }
.kp-stat-label { font-size: var(--kp-fs-sm); font-weight: var(--kp-fw-medium); line-height: 1.3; color: var(--bs-secondary-color); }
.kp-stat-value { font-size: var(--kp-fs-num); font-weight: var(--kp-fw-strong); line-height: 1.2; color: var(--bs-body-color); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.kp-stat-value.is-accent { color: var(--kp-accent); }
.kp-dot-label { display: inline-flex; align-items: center; gap: var(--kp-s-2); }
.kp-dot-label::before { content: ""; flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: var(--kp-dot, transparent); }
[data-kp-dot="total"] { --kp-dot: var(--kp-dot-total); }
[data-kp-dot="inactive"] { --kp-dot: var(--kp-dot-inactive); }
[data-kp-dot="valid"] { --kp-dot: var(--kp-dot-valid); }
[data-kp-dot="paused"] { --kp-dot: var(--kp-dot-paused); }
[data-kp-dot="expired"] { --kp-dot: var(--kp-dot-expired); }
[data-kp-dot="blocked"] { --kp-dot: var(--kp-dot-blocked); }

/* ================= 9. nút Copy dùng chung (assets/js/panel-copy.js) =================
   Thao tác phụ: CHỈ icon (36 px nhìn thấy, 44 px trên màn cảm ứng) + chú thích "Sao chép" (title / aria-label). Thao tác quan trọng: nút chính icon + chữ "Sao chép".
   Bấm xong: icon đổi thành dấu tick ngắn + thông báo nổi (mục 13) nói rõ đã sao chép gì. */
.kp-copy { flex: 0 0 auto; white-space: nowrap; display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; min-height: 0; padding: 0; }
.kp-copy.kp-copy-text { width: auto; padding-left: var(--kp-s-4); padding-right: var(--kp-s-4); }
@media (max-width: 991.98px), (pointer: coarse) {
    .kp-copy { width: 44px; height: 44px; min-height: 44px; }
    .kp-copy.kp-copy-text { width: auto; }
}
.kp-copy.is-copied { color: var(--kp-succ-fg); border-color: var(--kp-ctl-succ); background-color: var(--kp-succ-bg); }
/* thông báo nổi: xem mục 13 (Dynamic Island, panel-island.js) */
.kp-cmanual { position: fixed; left: var(--kp-s-3); right: var(--kp-s-3); bottom: var(--kp-s-3); z-index: 1090; padding: var(--kp-s-4); border: 1px solid var(--bs-border-color); border-radius: var(--kp-r-lg); background: var(--bs-secondary-bg); box-shadow: var(--kp-dlg-shadow); }
.kp-cmanual[hidden] { display: none !important; }
.kp-cmanual textarea { font-family: var(--bs-font-monospace); font-size: 16px; }
@media (min-width: 576px) { .kp-cmanual { left: 50%; right: auto; width: 32rem; transform: translateX(-50%); } }

/* ================= 10. ô số lượng − [ 1 ] + (assets/js/panel-ui.js: input[data-stepper]) ================= */
.kp-stepper { display: flex; align-items: stretch; width: 100%; max-width: 20rem; border: 1px solid var(--kp-input-border); border-radius: var(--kp-r-md); background: var(--kp-input-bg); overflow: hidden; }
.kp-stepper:focus-within { border-color: var(--kp-primary); box-shadow: 0 0 0 .2rem rgba(var(--bs-primary-rgb), .22); }
.kp-stepper > .form-control { flex: 1 1 auto; min-width: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; text-align: center; font-variant-numeric: tabular-nums; -moz-appearance: textfield; appearance: textfield; }
.kp-stepper > .form-control::-webkit-outer-spin-button, .kp-stepper > .form-control::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.kp-stepper > .form-control.is-invalid { background-image: none; }
.kp-stepper > button { flex: 0 0 44px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border: 0; background: transparent; color: var(--bs-body-color); }
.kp-stepper > button:first-child { box-shadow: inset -1px 0 0 var(--kp-input-border); }   /* vạch ngăn bằng bóng trong (không đệm) → icon − / + cân GIỮA nút */
.kp-stepper > button:last-child { box-shadow: inset 1px 0 0 var(--kp-input-border); }
.kp-stepper > button:hover:not(:disabled), .kp-stepper > button:focus-visible { background: var(--kp-sel-bg); color: var(--kp-sel-fg); }
.kp-stepper > button:disabled { opacity: .45; cursor: not-allowed; }
.kp-stepper.is-invalid { border-color: var(--bs-danger); }

/* ================= 11. menu trái + hộp thoại ================= */
#sidebar-menu ul li a { font-size: var(--kp-fs-body); font-weight: var(--kp-fw-medium); }
dialog.kp-dialog { border-radius: var(--kp-r-lg); }
.kp-dialog-title { font-size: var(--kp-fs-title); font-weight: var(--kp-fw-strong); }
.dropdown-menu { border-radius: var(--kp-r-md); }

/* ================= 12. Tạo key: gói dạng hàng (điện thoại) có ô tròn chọn, tóm tắt thiếu credit ================= */
@media (max-width: 575.98px) {
    .kp-packs .pack-option { justify-content: flex-start !important; gap: var(--kp-s-3); }
    .kp-packs .pack-option::before { content: ""; flex: 0 0 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--kp-check-border); background: var(--kp-input-bg); }
    .kp-packs .pack-option .kp-pack-price { margin-left: auto; }
    .btn-check:checked + .pack-option::before { border-color: var(--kp-primary); background: var(--kp-primary); box-shadow: inset 0 0 0 4px var(--kp-sel-bg); }
    .kp-packs .btn-check:disabled + .pack-option::before { border-style: dashed; border-color: var(--bs-border-color); background: transparent; }
}
.kc-summary:has(.text-danger) { max-width: none; padding: var(--kp-s-3) var(--kp-s-4); border: 0; border-radius: var(--kp-r-md); background: var(--kp-dang-bg); color: var(--kp-dang-fg); }
.kc-summary:has(.text-danger) .kc-cost { color: inherit; }

/* menu ngôn ngữ / tài khoản ở điện thoại hẹp: không tràn mép trái màn hình (320 px) */
@media (max-width: 600px) { #header-user > .dropdown-menu, #header-language > .dropdown-menu { min-width: 9rem; } }

/* ================= 13. thông báo nổi "Dynamic Island" (assets/js/panel-island.js) =================
   Viên thuốc tối ở GIỮA phía trên, dùng chung cho copy / báo xong / lỗi / "Nạp thành công" (nở ra nhiều dòng). Nằm trong top layer (popover="manual") — nổi cả trên hộp thoại <dialog>; trình duyệt không
   hỗ trợ popover thì fixed + z-index 1090 (ngoại lệ DUY NHẤT cùng hộp thoại — dialog.md). Máy tính ≥ 1200 px: sát mép trên (giữa thanh trên đang trống); hẹp hơn: ngay DƯỚI thanh trên (70 px) để không che
   nút ☰ / chuông / ngôn ngữ; chừa vùng an toàn trên cùng (tai thỏ) bằng env(safe-area-inset-top). Nền tối ở CẢ 2 chế độ (như đảo của điện thoại), màu icon theo loại. */
.kp-island {
    position: fixed; inset: auto; top: calc(env(safe-area-inset-top, 0px) + 78px); left: 50%; transform: translateX(-50%); z-index: 1090; margin: 0; padding: 0; border: 0; background: transparent; color: inherit; overflow: visible;
    display: flex; flex-direction: column; align-items: center; gap: var(--kp-s-2); width: max-content; max-width: min(560px, calc(100vw - 24px)); pointer-events: none;
}
@media (min-width: 1200px) { .kp-island { top: calc(env(safe-area-inset-top, 0px) + 12px); } }
.kp-island[hidden], .kp-island[popover]:not(:popover-open) { display: none; }
.kp-island-item {
    pointer-events: auto; display: flex; align-items: center; gap: var(--kp-s-3); max-width: 100%; min-height: 44px; padding: var(--kp-s-2) var(--kp-s-5) var(--kp-s-2) var(--kp-s-4); border-radius: var(--kp-r-pill);
    background: var(--kp-toast-bg); color: var(--kp-toast-fg); box-shadow: 0 8px 24px -8px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .08) inset; font-size: var(--kp-fs-body); font-weight: var(--kp-fw-medium); line-height: 1.4; cursor: default;
}
.kp-island-item:not(.is-closable) { cursor: pointer; }
.kp-island-item.is-closable { padding-right: var(--kp-s-1); }
.kp-island-item.is-open { align-items: flex-start; border-radius: var(--kp-r-lg); padding-top: var(--kp-s-3); padding-bottom: var(--kp-s-3); }
.kp-island-item.is-open .kp-island-ic { margin-top: -1px; }
.kp-island-ic { flex: 0 0 auto; --kp-i-size: 1.25rem; font-size: 1rem; color: var(--kp-toast-ok); }
.kp-island-item.is-info .kp-island-ic { color: var(--kp-toast-info); }
.kp-island-item.is-warning .kp-island-ic { color: var(--kp-toast-warn); }
.kp-island-item.is-danger .kp-island-ic { color: var(--kp-toast-err); }
.kp-island-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; overflow-wrap: anywhere; }
.kp-island-title { font-weight: var(--kp-fw-strong); }
.kp-island-line { font-weight: var(--kp-fw-regular); color: var(--kp-toast-line); font-size: var(--kp-fs-sm); }
.kp-island-x { flex: 0 0 44px; width: 44px; height: 44px; padding: 0; border: 0; border-radius: var(--kp-r-pill); background: transparent; color: var(--kp-toast-fg); display: inline-flex; align-items: center; justify-content: center; margin: calc(var(--kp-s-2) * -1) 0; }
.kp-island-x:hover, .kp-island-x:focus-visible { background: rgba(255, 255, 255, .14); }
@keyframes kp-island-in { from { opacity: 0; transform: translateY(-8px) scale(.96); } }
.kp-island-item { animation: kp-island-in var(--kp-dur, 180ms) var(--kp-ease, ease) backwards; }

.kc-type .btn { padding-left: var(--kp-s-2); padding-right: var(--kp-s-2); }
@media (max-width: 399.98px) { .kc-type .btn { padding-left: 4px; padding-right: 4px; font-size: var(--kp-fs-sm); } }   /* task-60: Be Vietnam Pro 600 rộng hơn — "6-hour test key" vừa 1 dòng ở 360 px */   /* "6-hour test key" / "Key test 6 giờ" vừa 1 dòng ở 360 px */

/* ================= 14. đầu thẻ app có thứ bậc (kc_app_head_html — Dashboard "Theo app", App của tôi) ================= */
.kp-apphead { display: flex; align-items: center; gap: var(--kp-s-3); min-width: 0; }
.kp-apphead > .app-icon { flex: 0 0 auto; }
.kp-apphead-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kp-apphead-name { font-size: var(--kp-fs-title); font-weight: var(--kp-fw-strong); line-height: 22px; overflow-wrap: anywhere; }   /* dòng cao số nguyên → logo nền tảng nằm trên điểm ảnh tròn (bài ink: Android = iOS ±1 px) */
.kp-apphead-plat { font-size: var(--kp-fs-body); line-height: 19px;   /* task-60: 19 px (trước 20) — dòng lẻ làm nửa-leading lẻ nên đường chân chữ rơi đúng điểm ảnh ở dpr 2 (ink_<n>: lệch logo 3 chỗ -0,5 … +0,75 → -0,5 … +0,25 px) */
    color: var(--bs-secondary-color); font-weight: var(--kp-fw-regular); }

/* ================= 15. icon TRÒN (task-53; Owner cho tải icon Lucide cho ô trạng thái / khối nạp tiền) =================
   Nền = màu của icon pha loãng 14 % (cùng công thức ở 2 chế độ; màu icon theo token --kp-dot-* nên mỗi chế độ có bộ riêng). Dùng khi icon GIÚP nhận biết (trạng thái key, ví, credit, lượt key test…) — không trang trí.
   Màu theo `data-kp-dot` của chính phần tử hoặc của phần tử cha (total / inactive / valid / paused / expired / blocked); không có thì màu nhấn. */
.kp-ic { --kp-ic-c: var(--kp-dot, var(--kp-dot-total)); flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 50%; color: var(--kp-ic-c); background: color-mix(in srgb, var(--kp-ic-c) 14%, transparent); }
.kp-ic > .kp-i { font-size: 1rem; }
.kp-ic.is-sm { width: 32px; height: 32px; }
.kp-ic.is-sm > .kp-i { font-size: .875rem; }

/* tiêu đề thẻ có icon tròn bên trái (Nạp tiền: Số tiền định nạp / Thưởng nạp / Thông tin chuyển khoản) */
.card-title.kp-title-ic { display: flex; align-items: center; gap: var(--kp-s-3); }

/* ================= 16. khối trống ("chưa có dữ liệu") — MỘT cách hiện cho mọi bảng (task-53) ================= */
td.sl-empty, td.dash-empty, td.maint-empty, td[colspan].text-center.text-muted { padding: var(--kp-s-6) var(--kp-s-4) !important; color: var(--bs-secondary-color) !important; font-size: var(--kp-fs-body); }

/* ================= 17. phân trang: nút rời, bo 8 (cùng ngôn ngữ với nút / ô nhập) ================= */
.pagination { gap: var(--kp-s-1); flex-wrap: wrap; }
.pagination .page-link { border-radius: var(--kp-r-md); margin-left: 0; }
.page-item:not(:first-child) .page-link { margin-left: 0; }

/* ================= 15. dòng "Link cài đặt" của app (task-88) ================= */
/* il_row_html() (layouts/install-link-lib.php): nhãn nhỏ phía trên + link 1 DÒNG rút giữa (kc_key_html — theme.css mục 13); nút "Chép link cài đặt" (.kp-copy) do chỗ dùng đặt ở hàng nút của nó. Màu chỉ qua biến. */
.kp-install { display: flex; flex-direction: column; align-items: flex-start; gap: var(--kp-s-1); min-width: 0; max-width: 100%; }
.kp-install-label { font-size: var(--kp-fs-sm); font-weight: 500; color: var(--bs-secondary-color); }
.kp-install-url { display: block; max-width: 100%; min-width: 0; color: var(--kp-link, var(--bs-link-color)); }
.kp-install-url .kp-key { max-width: 100%; }
@media (max-width: 991.98px), (pointer: coarse) { .kp-install { gap: 0; } .kp-install-url { display: flex; align-items: center; min-height: 44px; } }   /* link đứng riêng: vùng chạm >= 44 px (ui-mobile.md); đủ 44 px nên nhãn sát link */
/* Trong ô bảng ("App của tôi", ≥ 992 px): chuỗi nowrap làm cột phình theo link (255 ký tự = 1963 px) và đẩy các cột khác ra khỏi khung — khối link KHÔNG góp vào bề rộng ô (width 0), chỉ lấy đúng bề rộng ô (min-width 100%). */
.myapp-install .kp-install { width: 0; min-width: 100%; }
/* Hàng nút "Chép key" + "Chép link cài đặt" của kết quả Tạo key: ≥ 576 px nút ôm theo chữ; hẹp hơn thì vừa 1 hàng giãn đều, không vừa thì mỗi nút 1 hàng đủ rộng. */
.kp-install-actions { display: flex; flex-wrap: wrap; gap: var(--kp-s-2); }
.kp-install-actions > .btn { flex: 0 1 auto; }
@media (max-width: 575.98px) { .kp-install-actions > .btn { flex: 1 1 auto; } }
