/*
 * Modules\WindowManager — client-side chrome for every admin dialog
 * (`.modal-backdrop > .modal`, see resources/views/components/
 * confirm-dialog.blade.php's own docblock for that shared shape).
 * Loaded only while the Module is enabled — see admin.layout's
 * $windowManagerEnabled gate around this <link>. Paired 1:1 with
 * public/admin-assets/js/window-manager.js, which is the thing that
 * actually attaches these classes/elements at runtime.
 */

/* --- Always-on: stacking like OS windows --------------------------- */
/* `.modal-backdrop` normally dims+blocks the whole viewport (see
   admin.css's own rule) — one dialog at a time, closable by clicking
   anywhere outside it. Once this Module is enabled that stops making
   sense: several dialogs can be open and dragged around at once, so
   EVERY backdrop goes transparent and click-through (pointer-events:
   none), and only the dialog box itself stays clickable/draggable —
   exactly like separate floating OS windows with no shared overlay
   behind them. window-manager.js gives each dialog's backdrop its own
   z-index and raises it on interaction (bringToFront()), which is what
   actually makes them stackable instead of just all sharing one z.
   Losing click-outside-to-close is intentional here, but window-
   manager.js compensates with a capturing Escape handler that closes
   just the frontmost window instead (see its own docblock), so every
   dialog still has a keyboard-only way to close besides its header
   ✕ button. */
html.wm-enabled .modal-backdrop { background: transparent; pointer-events: none; }
html.wm-enabled .modal-backdrop > .wm-modal {
    position: relative; /* anchors the resize handles below even before a dialog has ever been dragged */
    pointer-events: auto;
    box-shadow: 0 24px 64px rgba(2, 6, 23, 0.45), 0 2px 8px rgba(2, 6, 23, 0.25);
}

/* --- Drag handle -------------------------------------------------- */
/* Preferred case: the dialog already has a `.modal__header` (title +
   ✕ close button row — the convention every dialog in this panel
   follows, see admin.css's `.modal__header` rule) — that whole row
   becomes the drag handle (`.wm-draggable-header`), no extra markup
   needed. Only dialogs with no such header (e.g. the centered
   confirm-dialog) fall back to an injected `.wm-titlebar` strip. */
/* `z-index: 4` here (one above `.wm-resize-handle`'s `3` below) is
   the actual fix, not the `position: relative` that makes it apply —
   without it, the resize-e handle's own thin, nearly full-height
   strip along the dialog's right edge (see its own comment) sits
   close enough to a header's ✕/− buttons that in real rendering
   (control-height rounding, etc.) it can genuinely overlap their
   rightmost sliver and win hit-testing there — a fixed, per-dialog
   dead zone on the buttons that has nothing to do with which window
   is on top or where it's been dragged, and looks identical every
   time because it's the SAME two elements overlapping regardless. */
.wm-draggable-header { cursor: move; user-select: none; position: relative; z-index: 4; }
.wm-draggable-header:active { cursor: grabbing; }

.wm-titlebar {
    position: absolute; inset-inline: 0; top: 0; height: 2.1rem; z-index: 4;
    cursor: move; user-select: none;
    border-start-start-radius: inherit; border-start-end-radius: inherit;
}
.wm-titlebar:active { cursor: grabbing; }
.wm-modal--headerless { position: relative; padding-top: 2.35rem !important; }

/* Actively dragging a dialog IS having focus on it — its glass
   translucency (`.glass-panel`'s `background`/`backdrop-filter`, see
   admin.css) makes sense for a window just sitting there, but while
   you're moving the focused one around it should read as solid/opaque
   instead, not show whatever's behind it bleeding through as it slides
   across the screen. `!important` because it needs to beat
   `.glass-panel`'s own declarations regardless of which stylesheet
   happens to cascade last. */
.wm-modal--dragging {
    transition: none !important;
    background: var(--surface) !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
}

/* Once a dialog has been dragged at least once it's taken out of the
   backdrop's centering flex flow and pinned with inset styles set
   inline by window-manager.js (left/top in px) — this class only
   turns off the flex auto-margins .modal-backdrop would otherwise
   still apply via `align-items`. */
.wm-modal--positioned { position: fixed !important; margin: 0 !important; }

/* --- Resize handles --------------------------------------------------
   Deliberately PHYSICAL (right/bottom), not logical inline-end — a
   resize grip stays where the pointer expects it (bottom-right
   corner) regardless of RTL/LTR, unlike the taskbar/minimize corner
   above which deliberately DOES flip with direction. Only added once
   a dialog has actually been dragged/resized at least once (position:
   fixed with an explicit width/height — see window-manager.js's
   makeResizable()); `.wm-modal--resized` lifts the dialog's own
   max-width/max-height so the explicit size set by dragging one of
   these handles always applies, and its content scrolls once it no
   longer fits (same non-Alpine-owned, opacity/pointer-events-safe
   pattern as `.wm-minimized` above — plain CSS, nothing here is ever
   touched by Alpine's reactivity). */
.wm-resize-handle { position: absolute; z-index: 3; }
.wm-resize-e { top: 0.5rem; bottom: 0.5rem; right: -4px; width: 8px; cursor: ew-resize; }
.wm-resize-s { left: 0.5rem; right: 0.5rem; bottom: -4px; height: 8px; cursor: ns-resize; }
.wm-resize-se { bottom: -4px; right: -4px; width: 16px; height: 16px; cursor: nwse-resize; }
.wm-modal--resized { max-width: none !important; max-height: none !important; overflow: auto; }

/* --- Minimize button ------------------------------------------------ */
/* Reuses `.glass-icon-button` (same class the panel's own ✕ close
   buttons use) so it renders as an identical circle, same size, right
   next to the close button — `.wm-header-actions` is the small flex
   wrapper window-manager.js inserts around [minimize, close] so the
   two sit in one row with a small gap, instead of `.modal__header`'s
   own `justify-content: space-between` spreading them apart. */
/* `position: relative` + a z-index above `.wm-draggable-header`'s own
   `4` (see that rule's docblock on why the resize-e handle needed
   beating in the first place) keeps this whole row hit-testing above
   BOTH the resize handle and the header's own drag area reliably,
   however many buttons (lock/minimize/close) end up packed into it —
   belt-and-suspenders alongside the per-button pointerdown guard in
   window-manager.js that stops a button's own pointerdown from ever
   reaching the header's drag handler in the first place. */
.wm-header-actions { display: flex; align-items: center; gap: 0.35rem; position: relative; z-index: 5; pointer-events: auto; }
.wm-minimize-btn { font-size: 1rem; font-weight: 700; }

/* Headerless fallback (see .wm-titlebar above) — no row to reuse, so
   the button floats at the dialog's own top-inline-end corner. */
.wm-titlebar .wm-minimize-btn { position: absolute; top: 0.4rem; inset-inline-end: 0.4rem; pointer-events: auto; }

/* --- Lock (pin) button ------------------------------------------------
   Sits right next to the minimize button (see `.wm-header-actions`
   above) — toggling it freezes this ONE dialog in place: no drag, no
   resize, no minimize, no close (✕/Escape), and its stacking level
   never changes again (window-manager.js's bringToFront() skips a
   `.wm-locked` backdrop entirely, and the frontmost-window Escape scan
   skips it too) — every OTHER window can still reorder freely above/
   below it, it just never moves from its own slot. */
.wm-lock-btn { font-size: 0.95rem; }
.wm-lock-btn.is-active { color: var(--primary, #6366f1); }
.wm-titlebar .wm-lock-btn { position: absolute; top: 0.4rem; inset-inline-end: 2.4rem; pointer-events: auto; }

/* A locked dialog can't be dragged/resized — the resize handles and
   the drag-handle cursor read as inert (not-allowed) instead of the
   normal move/resize cursors, so the "why won't this move" is visible
   before the admin even tries. */
.wm-modal--locked .wm-draggable-header,
.wm-modal--locked .wm-titlebar { cursor: not-allowed; }
.wm-modal--locked .wm-resize-handle { cursor: not-allowed; pointer-events: none; }
.wm-modal--locked .wm-minimize-btn { opacity: 0.4; pointer-events: none; }
/* The header's own ✕ close button — always the LAST child of
   `.wm-header-actions` (see window-manager.js's insertion order:
   lock, minimize, close) — visually disabled the same way while
   locked, on top of the click-interception in window-manager.js's
   document-level listener that already blocks it functionally. */
.wm-modal--locked .wm-header-actions > button:last-child { opacity: 0.4; pointer-events: none; }

/* --- Minimized state -------------------------------------------------
   Deliberately never touches `display` — Alpine's `x-show` owns that
   inline style on every dialog here (see window-manager.js's own
   docblock) and would clobber a plain `display:none` the next time
   its reactive state re-evaluates. Opacity + pointer-events achieves
   the same "fully hidden, fully unclickable" result without Alpine
   ever noticing. */
.wm-minimized {
    opacity: 0 !important;
    pointer-events: none !important;
    transform: scale(0.85) translateY(2rem);
    transition: opacity 160ms ease, transform 160ms ease;
}

/* --- Taskbar (macOS-dock style) ---------------------------------------
   Redesigned as one glassy dock bar hugging the bottom edge — icons
   only, centered, with the same rounded-top / square-bottom silhouette
   and springy hover-magnify a real macOS Dock has. Anchored full-width
   with the bar itself centered via `margin-inline: auto` rather than
   `inset-inline-end`, so it reads the same in RTL and LTR (a dock never
   sits in a page-direction-relative corner). `flex-wrap: wrap-reverse`
   still protects against overflow on very small viewports, growing a
   second row upward instead of spilling sideways. */
.wm-taskbar {
    position: fixed; bottom: 0; inset-inline: 0; z-index: 9000;
    display: flex; flex-direction: row-reverse; flex-wrap: wrap-reverse;
    justify-content: center; align-items: flex-end; gap: 0.6rem;
    width: fit-content; max-width: calc(100vw - 1.5rem);
    margin-inline: auto; pointer-events: none;
    padding: 0.55rem 0.9rem 0.6rem;
    border-radius: 1.4rem 1.4rem 0 0;
    /* Themed glass, same recipe as `.glass-panel`/`.stat-card`: the
       page's own --surface tinted with a touch of --primary so the
       dock always matches whichever color preset is active, instead
       of a fixed slate-dark regardless of theme. */
    background: color-mix(in srgb, var(--surface) 82%, var(--primary) 10%);
    backdrop-filter: blur(20px) saturate(1.4);
    -webkit-backdrop-filter: blur(20px) saturate(1.4);
    border: var(--glass-border);
    border-bottom: none;
    box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.08);
    transition: padding 200ms ease;
}
.wm-taskbar:empty { display: none; padding: 0; border: none; box-shadow: none; }

/* --- Folders ----------------------------------------------------------
   One per `data-wm-group` (e.g. one page/section), mac-dock style: a
   round icon "tile" (label/count reserved for the hover popup, not the
   dock face itself — a real dock shows icons, not text) that pops in
   with a springy bounce and magnifies + lifts on hover/focus, with a
   popup listing that group's individual minimized windows revealed on
   hover (desktop) or click/tap (`.wm-folder--open`, toggled in JS —
   needed for touch, where there is no hover). */
.wm-folder { position: relative; pointer-events: auto; }
.wm-folder__btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 0.3rem;
    width: 2.9rem; height: 2.9rem; padding: 0 0.4rem;
    border-radius: 0.85rem; border: none;
    cursor: pointer; font-size: 0.82rem; white-space: nowrap;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
    /* A soft --primary→--secondary gradient (the same pairing used
       around the panel — see admin.css's own docblock on that
       contract) instead of a fixed slate tile, so each color preset
       gives the dock its own accent rather than always reading dark
       gray. */
    background: linear-gradient(160deg,
        color-mix(in srgb, var(--primary) 55%, var(--surface)),
        color-mix(in srgb, var(--secondary) 55%, var(--surface)));
    color: var(--text);
    transform-origin: bottom center;
    transition: transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1),
        box-shadow 180ms ease, filter 150ms ease;
    animation: wm-dock-pop 320ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.wm-folder__btn:hover,
.wm-folder__btn:focus-visible {
    filter: brightness(1.12) saturate(1.15);
    transform: translateY(-0.55rem) scale(1.22);
    box-shadow: 0 14px 28px rgba(0, 0, 0, 0.35), 0 0 0 3px color-mix(in srgb, var(--primary) 35%, transparent);
}
.wm-folder--open .wm-folder__btn {
    transform: translateY(-0.4rem) scale(1.12);
}
/* Fixed-size relative box the two icon glyphs both sit inside,
   absolutely stacked on top of one another — needed so swapping which
   one is "on" can cross-fade (opacity + a small scale/rotate) instead
   of an instant `display` snap; a plain inline-flex row can't animate
   between one child disappearing and another appearing. */
.wm-folder__icon-stack { position: relative; display: inline-block; width: 1.4rem; height: 1.4rem; }
.wm-folder__icon {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 1.4rem; line-height: 1; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35));
    opacity: 0; transform: scale(0.7) rotate(-8deg);
    transition: opacity 200ms ease, transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Whichever trigger reveals the popup (hover on desktop, the
   `.wm-folder--open` class from click/tap — see `.wm-folder__popup`'s
   own display rule below, which this mirrors) swaps the dock face to
   the open-folder glyph, same as the popup itself appearing/hiding. */
.wm-folder__icon--closed { opacity: 1; transform: scale(1) rotate(0deg); }
.wm-folder:hover .wm-folder__icon--closed,
.wm-folder--open .wm-folder__icon--closed { opacity: 0; transform: scale(0.7) rotate(8deg); }
.wm-folder:hover .wm-folder__icon--open,
.wm-folder--open .wm-folder__icon--open { opacity: 1; transform: scale(1) rotate(0deg); }
.wm-folder__count {
    position: absolute; top: -0.25rem; inset-inline-end: -0.25rem;
    min-width: 1.15rem; padding: 0 0.3rem; border-radius: 999px; text-align: center;
    font-size: 0.68rem; line-height: 1.15rem; font-weight: 700;
    background: var(--secondary); color: #fff;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--surface) 70%, transparent);
    opacity: 1; transform: scale(1); transition: opacity 200ms ease, transform 200ms ease;
}
.wm-folder__count:empty { display: none; }
/* Hidden while the popup is showing (same trigger as the icon swap
   above) — the popup's own header + row list already say how many/
   which windows are inside, so the badge would be redundant right
   next to an already-open list. */
.wm-folder:hover .wm-folder__count,
.wm-folder--open .wm-folder__count { opacity: 0; transform: scale(0.5); }

@keyframes wm-dock-pop {
    0% { transform: translateY(1.1rem) scale(0.4); opacity: 0; }
    60% { transform: translateY(-0.3rem) scale(1.08); opacity: 1; }
    100% { transform: translateY(0) scale(1); opacity: 1; }
}

.wm-folder__popup {
    /* Centered above the dock icon (was end-aligned to the folder's
       edge) — `inset-inline-start: 50%` + `translateX(-50%)` keeps it
       centered on the `.wm-folder__btn` regardless of RTL/LTR. */
    position: absolute; bottom: calc(100% + 0rem); inset-inline-start: -150%; 
    display: none; flex-direction: column; align-items: center; gap: 0.35rem;
    max-width: min(280px, calc(100vw - 2rem));
    /* Caps the list at `folder_max_visible` (Modules\WindowManager's
       own setting — see window-manager.js's own `--wm-folder-max-items`
       assignment) rows tall, scrolling internally past that, instead
       of the old flat 60vh viewport-relative cap — ~2.3rem covers one
       `.wm-taskbar__item` row (icon + label + pin button) plus its
       `gap` below. The header row below sits on top of that budget,
       not inside it — it's excluded from `--wm-folder-max-items`. */
    max-height: calc(0.5rem * 2 + var(--wm-folder-max-items, 10) * 2.3rem);
    overflow-y: auto;
    padding: 0.5rem; border-radius: 0.7rem;
    box-shadow: var(--shadow-listbox); border: var(--glass-border);
    backdrop-filter: blur(14px);
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    animation: glass-scale-in 140ms ease both;
}
.wm-folder:hover .wm-folder__popup,
.wm-folder--open .wm-folder__popup { display: flex; }

/* The group's title — moved INSIDE the popup as its own header row
   (was a separate floating tooltip beside the dock icon, shown only
   on hover — see folderFor()'s own docblock for why that changed):
   sits above the list of that group's minimized windows every time
   the popup itself is open, sticky so it stays visible while the
   list scrolls past `--wm-folder-max-items` rows. */
.wm-folder__popup-header {
    flex-shrink: 0; align-self: stretch; position: sticky; top: -0.5rem; margin: -0.5rem -0.5rem 0.15rem;
    padding: 0.5rem 0.6rem 0.35rem; font-size: 0.78rem; font-weight: 700; text-align: center;
    color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    border-bottom: var(--glass-border);
    background: color-mix(in srgb, var(--surface) 92%, transparent);
}

/* A row is now a plain container (was itself a `<button>`) holding TWO
   sibling buttons — the main clickable label and a separate pin
   toggle (see renderChip()) — nesting a `<button>` inside a `<button>`
   is invalid HTML and browsers handle the click-through inconsistently. */
.wm-taskbar__item {
    display: flex; align-items: center; gap: 0.15rem;
    max-width: 260px; padding: 0.15rem; border-radius: 0.5rem;
    background: color-mix(in srgb, var(--text) 6%, transparent); color: var(--text);
}
.wm-taskbar__item:hover { background: color-mix(in srgb, var(--primary) 18%, transparent); }
.wm-taskbar__item-main {
    display: inline-flex; align-items: center; gap: 0.4rem; flex: 1 1 auto; min-width: 0;
    padding: 0.25rem 0.5rem; border-radius: 0.4rem; border: none; background: transparent;
    color: inherit; font: inherit; cursor: pointer; text-align: start;
}
.wm-taskbar__item-icon { font-size: 0.95rem; flex-shrink: 0; }
.wm-taskbar__item-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Pinning (see renderChip()'s own `pinned` toggle and enhance()'s
   close-button interception) keeps a window docked here even through
   its own ✕/Escape — `--secondary` reads clearly against the themed
   popup background across every color preset, unlike a fixed accent. */
.wm-taskbar__item-pin {
    flex-shrink: 0; border: none; background: transparent; color: inherit; cursor: pointer;
    font-size: 0.85rem; line-height: 1; padding: 0.3rem; border-radius: 0.4rem; opacity: 0.45;
}
.wm-taskbar__item-pin:hover { opacity: 0.85; background: color-mix(in srgb, var(--text) 10%, transparent); }
.wm-taskbar__item-pin.is-active { opacity: 1; color: var(--secondary); }

/* --- "max_open_dialogs" limit banner --------------------------------
   Shown by window-manager.js's own showLimitToast() when opening one
   more dialog would exceed the Module's configured cap — plain DOM/
   CSS, not the panel's Alpine `Alpine.store('toast')`, to keep this
   file dependency-free (see its own docblock). */
.wm-limit-toast {
    position: fixed; top: 1rem; inset-inline: 0; margin-inline: auto;
    width: fit-content; max-width: min(480px, calc(100vw - 2rem));
    z-index: 9500; padding: 0.6rem 1rem; border-radius: 0.6rem;
    font-size: 0.85rem; text-align: center; color: #f8fafc;
    background: rgba(127, 29, 29, 0.94); box-shadow: 0 12px 32px rgba(2, 6, 23, 0.35);
    backdrop-filter: blur(10px); pointer-events: none;
    opacity: 0; transform: translateY(-0.5rem);
    transition: opacity 180ms ease, transform 180ms ease;
}
.wm-limit-toast--visible { opacity: 1; transform: translateY(0); }

/* --- Folder "بستن همه" confirm overlay -------------------------------
   Deliberately its own classes, NOT `.modal-backdrop`/`.modal` — this
   module's own scan() would otherwise try to enhance/count/cascade it
   like a real page dialog (see showConfirm()'s own comment). Reuses
   the panel's plain `.btn` button classes for the two actions. */
.wm-confirm-overlay {
    position: fixed; inset: 0; z-index: 9600;
    display: flex; align-items: center; justify-content: center;
    background: rgba(2, 6, 23, 0.55);
    animation: glass-fade-in 150ms ease both;
}
.wm-confirm-box {
    width: min(360px, calc(100vw - 2rem));
    padding: 1.25rem; border-radius: 12px;
    background: var(--surface); border: var(--glass-border);
    box-shadow: var(--shadow-listbox);
    animation: glass-scale-in 150ms ease both;
}
.wm-confirm-message { margin: 0 0 1rem; font-size: 0.9rem; color: var(--text); }
.wm-confirm-actions { display: flex; justify-content: flex-end; gap: 0.5rem; }

/* --- Responsive shrink (opt-in: responsive_resize_enabled) --------- */
/* Below the configured min-width breakpoint the dialog shrinks with
   the viewport from both edges instead of holding a fixed max-width;
   once it hits --wm-min-width it stops shrinking and its own content
   scrolls instead (max-height + overflow-y here, same as the plain
   `.modal-backdrop { overflow-y: auto }` rule already does for the
   backdrop as a whole). */
.wm-responsive .modal-backdrop > .wm-modal {
    width: calc(100vw - 2rem);
    min-width: min(var(--wm-min-width, 320px), calc(100vw - 1rem));
    max-height: calc(100vh - 4rem);
    overflow-y: auto;
}
