/* ==========================================================================
   Model Library Component Styles
   ========================================================================== */

/* --------------------------------------------------------------------------
   CSS Variables - Model Library Theme
   -------------------------------------------------------------------------- */
:root {
    /* Category Sidebar */
    --ml-sidebar-width: 180px;
    --ml-sidebar-bg: #ffffff;
    --ml-category-height: var(--ctl-h);
    --ml-category-gap: var(--sp-1);
    --ml-category-radius: var(--r-sm);
    --ml-category-padding: var(--sp-3) var(--sp-5);

    /* Category Colors */
    --ml-category-bg: transparent;
    --ml-category-bg-hover: rgba(0, 122, 255, 0.08);
    --ml-category-bg-selected: #007AFF;
    --ml-category-text: #1d1d1f;
    --ml-category-text-selected: #ffffff;
    --ml-category-icon-size: var(--icon-lg);

    /* Search Bar */
    --ml-search-height: var(--ctl-h);
    --ml-search-bg: #f5f5f7;
    --ml-search-radius: var(--r-md);
    --ml-search-border: 1px solid #d2d2d7;

    /* Model Grid */
    --ml-grid-gap: var(--sp-5);
    --ml-item-size: 120px;
    --ml-item-radius: var(--r-md);
    --ml-item-bg: #f5f5f7;
    --ml-item-border: 1px solid #e5e5ea;
    --ml-item-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

/* --------------------------------------------------------------------------
   Model Library Container
   -------------------------------------------------------------------------- */
.model-library {
    display: flex;
    width: 100%;
    height: 100%;
    background: var(--ml-sidebar-bg);
    font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif;
}

/* --------------------------------------------------------------------------
   Categories Sidebar
   -------------------------------------------------------------------------- */
.ml-sidebar {
    display: flex;
    flex-direction: column;
    width: var(--ml-sidebar-width);
    min-width: var(--ml-sidebar-width);
    height: 100%;
    background: var(--ml-sidebar-bg);
    border-right: 1px solid var(--ui-border-color);
    overflow-y: auto;
    overflow-x: hidden;
    /* Match the search bar's safe-area top inset so the first category isn't under the notch. */
    padding: calc(var(--sp-3) + env(safe-area-inset-top, 0px)) var(--sp-3) var(--sp-3);
}

.ml-categories {
    display: flex;
    flex-direction: column;
    gap: var(--ml-category-gap);
}

/* Category Button */
.ml-category-btn {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    width: 100%;
    min-height: var(--ml-category-height);
    padding: var(--ml-category-padding);
    background: var(--ml-category-bg);
    border: none;
    border-radius: var(--ml-category-radius);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    text-align: left;
}

.ml-category-btn:hover {
    background: var(--ml-category-bg-hover);
}

.ml-category-btn.selected {
    background: var(--ml-category-bg-selected);
    color: var(--ml-category-text-selected);
}

/* Selected category - keep icons white (remove the invert filter) */
.ml-category-btn.selected .ml-category-icon {
    filter: none;
}

/* Category icon - make white icons appear black, maintain aspect ratio */
.ml-category-icon {
    width: var(--icon-md);
    height: var(--icon-md);
    object-fit: contain;
    flex-shrink: 0;
    /* Invert white icons to black */
    filter: brightness(0);
}

.ml-category-name {
    font-size: var(--fs-label);
    font-weight: 500;
    color: var(--ml-category-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.ml-category-btn.selected .ml-category-name {
    color: var(--ml-category-text-selected);
}

/* --------------------------------------------------------------------------
   Main Content Area (Search + Grid)
   -------------------------------------------------------------------------- */
.ml-content {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    height: 100%;
    overflow: hidden;
}

/* --------------------------------------------------------------------------
   Search Bar
   -------------------------------------------------------------------------- */
.ml-search-bar {
    display: flex;
    align-items: center;
    gap: var(--sp-4);
    /* Top inset keeps the search bar + settings gear clear of the device status bar / notch on
       native mobile (env() is 0 on desktop / WebGL, so this is a no-op there). */
    padding: calc(var(--sp-4) + env(safe-area-inset-top, 0px)) var(--sp-5) var(--sp-4);
    background: var(--ml-sidebar-bg);
    border-bottom: 1px solid var(--ui-border-color);
    flex-shrink: 0;
}

.ml-search-input-wrapper {
    display: flex;
    align-items: center;
    flex: 1;
    /* Allow the input to shrink below its intrinsic width so the search row (and the settings
       gear after it) always fits — without this, min-width:auto pushes the gear past the
       overflow:hidden edge of .ml-content and it's clipped off-screen on narrow/native layouts. */
    min-width: 0;
    background: var(--ml-search-bg);
    border: var(--ml-search-border);
    border-radius: var(--ml-search-radius);
    padding: 0 var(--sp-5);
    height: var(--ml-search-height);
}

.ml-search-input {
    flex: 1;
    min-width: 0;
    border: none;
    background: transparent;
    font-size: var(--fs-input);
    color: var(--ml-category-text);
    outline: none;
    pointer-events: auto;
    cursor: text;
}

.ml-search-input::placeholder {
    color: #86868b;
}

.ml-search-clear {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: none;
    background: transparent;
    cursor: pointer;
    opacity: 0.6;
    transition: opacity 0.15s;
    padding: 0;
}

.ml-search-clear:hover {
    opacity: 1;
}

.ml-search-clear svg {
    width: var(--icon-md);
    height: var(--icon-md);
    fill: #ff3b30;
}

.ml-search-clear.hidden {
    display: none;
}

/* --------------------------------------------------------------------------
   Model Grid
   -------------------------------------------------------------------------- */
.ml-grid-wrapper {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: var(--sp-5);
}

.ml-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--ml-item-size), 1fr));
    gap: var(--ml-grid-gap);
}

/* Model Item Wrapper (contains image box + name) */
.ml-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    cursor: pointer;
    transition: transform 0.15s;
    position: relative;
    /* Skip layout/paint/image-decode for tiles scrolled out of the grid viewport (the grid can
       hold hundreds, but only ~6-12 are visible). Width is fixed by the grid track so size
       containment can't change columns; contain-intrinsic-size:auto remembers each tile's real
       height after first paint (no scroll jump). Unknown→ignored on old Chromium WebViews. */
    content-visibility: auto;
    contain-intrinsic-size: auto 160px;
}

.ml-item:hover {
    transform: translateY(-2px);
}

.ml-item:hover .ml-item-icon-container {
    box-shadow: var(--ml-item-shadow), 0 4px 12px rgba(0, 0, 0, 0.12);
}

.ml-item:active {
    transform: scale(0.98);
}

/* Image container - 1:1 aspect ratio */
.ml-item-icon-container {
    width: 100%;
    aspect-ratio: 1;
    background: transparent;
    border: none;
    border-radius: var(--ml-item-radius);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: box-shadow 0.15s; /* border-color is dead (element is border:none, never set) */
}

.ml-item-icon {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.ml-item-placeholder {
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #f5f5f7 0%, #e5e5ea 100%);
    display: flex;
    align-items: center;
    justify-content: center;
}

.ml-item-letter {
    font-size: 28px;
    font-weight: 600;
    color: #86868b;
    text-transform: uppercase;
}

/* Item name below the image box */
.ml-item-name {
    width: 100%;
    font-size: var(--fs-caption);
    font-weight: 500;
    color: #333;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: var(--sp-2);
    padding: 0 2px;
}

.ml-item-badge-2d {
    position: absolute;
    top: 6px;
    left: 6px;            /* top-left, so it doesn't collide with the ❤ (now top-right) */
    min-width: 26px;
    height: 18px;
    border-radius: 9px;
    background: var(--ml-category-bg-selected);
    color: var(--ml-category-text-selected);
    font-size: 10px;
    font-weight: 700;
    line-height: 18px;
    text-align: center;
    padding: 0 6px;
    pointer-events: none;
}

/* Favorite ❤ (account-linked) — top-right of each item; black outline by default, solid red
   (no outline) when favorited. */
.ml-item-fav {
    position: absolute;
    top: 6px;
    right: 6px;          /* top-RIGHT per request */
    width: 26px;
    height: 26px;
    padding: 5px;
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 50%;
    /* Opaque white disc — NO backdrop-filter. The blur was an expensive per-scroll-frame GPU
       op (re-sampling the backdrop behind every visible heart) on cheap devices; a solid white
       disc costs nothing and the black-outlined ❤ reads cleanly on it. (Window panels keep
       their frosted blur — only this per-item heart drops it.) */
    background: #ffffff;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.1s, background 0.15s;
    z-index: 3;
}
.ml-item-fav svg { width: 100%; height: 100%; display: block; }
.ml-item-fav svg path { fill: none; stroke: #000000; stroke-width: 2; transition: fill 0.12s, stroke 0.12s; }
.ml-item-fav:hover { transform: scale(1.12); }
.ml-item-fav:hover svg path { stroke: #ff3b30; }
/* Favorited: filled red, no outline — just a red heart. */
.ml-item-fav.on svg path { fill: #ff3b30; stroke: none; }

/* Glyph for the virtual "Most Popular" / "Favorites" category buttons (text, not an <img>) */
.ml-category-glyph {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    line-height: 1;
    filter: none;
    color: #ff9f0a;
}
.ml-category-special[data-special="favorites"] .ml-category-glyph { color: #ff3b30; }
.ml-category-btn.selected .ml-category-glyph { color: #fff; }

/* --------------------------------------------------------------------------
   Empty State
   -------------------------------------------------------------------------- */
.ml-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: #86868b;
    text-align: center;
    padding: var(--sp-9);
}

.ml-empty-icon {
    font-size: 48px;
    margin-bottom: var(--sp-5);
    opacity: 0.5;
}

.ml-empty-text {
    font-size: var(--fs-body);
}

/* --------------------------------------------------------------------------
   Responsive Adjustments
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
    :root {
        --ml-sidebar-width: 132px;
    }

    .ml-category-btn {
        justify-content: flex-start;
        padding: var(--sp-3) var(--sp-4);
    }

    .ml-category-icon {
        width: var(--icon-md);
        height: var(--icon-md);
    }

    .ml-category-name {
        display: block;
    }

    /* Phones: smaller min so auto-fill yields 2 models/row on normal phones (~360px+);
       drops to 1/row only on very narrow (Z-Fold cover ~280px) screens. Overrides the
       --ml-item-size grid so it's independent of the C# setMinItemSize value. */
    .ml-grid {
        grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
    }
}

/* Compact layout: icon-only sidebar when width is tight (applied dynamically by JS) */
.model-library.ml-compact .ml-sidebar {
    width: auto;
    min-width: auto;
    padding: var(--sp-3) var(--sp-1);
}

.model-library.ml-compact .ml-category-btn {
    justify-content: center;
    padding: var(--sp-3);
    gap: 0;
}

.model-library.ml-compact .ml-category-name {
    display: none;
}

.model-library.ml-compact .ml-category-icon {
    width: var(--icon-lg);
    height: var(--icon-lg);
}

/* --------------------------------------------------------------------------
   Model Switch Confirmation Dialog
   -------------------------------------------------------------------------- */
.ml-confirm-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 12000;
    padding: var(--sp-9);
}

.ml-confirm-dialog {
    width: min(420px, calc(100vw - 40px));
    background: #ffffff;
    border: 1px solid #e5e5ea;
    border-radius: var(--r-lg);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
    padding: var(--sp-8);
}

.ml-confirm-title {
    margin: 0;
    font-size: var(--fs-title);
    font-weight: 600;
    color: #1d1d1f;
}

.ml-confirm-text {
    margin: 10px 0 0;
    font-size: var(--fs-body);
    line-height: 1.45;
    color: #3a3a3c;
}

.ml-confirm-actions {
    margin-top: var(--sp-7);
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-3);
}

.ml-confirm-btn {
    border: 1px solid #d2d2d7;
    border-radius: var(--r-md);
    min-height: var(--ctl-h-sm);
    padding: 0 var(--sp-6);
    font-size: var(--fs-label);
    font-weight: 600;
    cursor: pointer;
    background: #f5f5f7;
    color: #1d1d1f;
}

.ml-confirm-btn.ml-confirm-continue {
    background: #007AFF;
    border-color: #007AFF;
    color: #ffffff;
}

/* --------------------------------------------------------------------------
   "Get the app" chooser — reuses the confirm overlay/dialog shell; adds a
   close X and two store option rows (App Store / Google Play).
   -------------------------------------------------------------------------- */
.ml-getapp-dialog { position: relative; }

.ml-getapp-close {
    position: absolute;
    top: var(--sp-3);
    right: var(--sp-4);
    width: 30px;
    height: 30px;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.05);
    color: #555;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}
.ml-getapp-close:hover { background: rgba(0, 0, 0, 0.1); }

.ml-getapp-options {
    margin-top: var(--sp-7);
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
}

.ml-getapp-option {
    display: flex;
    align-items: center;
    gap: var(--sp-5);
    width: 100%;
    padding: var(--sp-4) var(--sp-6);
    border: 1.5px solid #e5e5ea;
    border-radius: var(--r-md);
    background: #ffffff;
    color: #1d1d1f;
    cursor: pointer;
    text-align: left;
    transition: border-color 0.15s, background 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.ml-getapp-option:hover { border-color: #007AFF; background: #f7faff; }
.ml-getapp-option:active { transform: scale(0.985); }

.ml-getapp-option svg { flex-shrink: 0; width: var(--icon-lg); height: var(--icon-lg); color: #1d1d1f; }
.ml-getapp-opt-txt { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.ml-getapp-opt-title { font-size: var(--fs-body); font-weight: 600; }
.ml-getapp-opt-sub { font-size: var(--fs-caption); color: #6e6e73; }
.ml-getapp-arrow { color: #c7c7cc; font-size: 20px; line-height: 1; }
/* --------------------------------------------------------------------------
   Loading skeleton — shimmer placeholders shown from library open until the
   first real data render (the Unity bridge takes ~1-2s on native). The real
   render wholesale-replaces these; .ml-loaded fades the real content in.
   -------------------------------------------------------------------------- */
.ml-skel {
    background: linear-gradient(90deg, #ececf0 25%, #e0e0e6 50%, #ececf0 75%);
    background-size: 200% 100%;
    animation: mlShimmer 1.2s linear infinite;
    border-radius: var(--r-sm);
    pointer-events: none;
}

.ml-skel-item {
    pointer-events: none;
}

.ml-skel-line {
    height: 12px;
    width: 70%;
    margin: var(--sp-2) auto 0;
}

.ml-category-btn.ml-skel {
    height: var(--ml-category-height);
    border: none;
}

@keyframes mlShimmer {
    to { background-position: -200% 0; }
}

/* One-shot fade-in of the real content replacing the skeleton. */
.ml-loaded > * {
    animation: mlFadeIn 0.25s ease both;
}

@keyframes mlFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
