/* Modal positioning & layout */
#base-modal {
    position: fixed;
    inset: 0;
    z-index: 9999;
}

#base-modal-level-1 {
    position: fixed;
    inset: 0;
    z-index: 19999;
}

#base-modal > .modal-underlay {
    position: absolute;
    inset: 0;
    cursor: pointer;
    z-index: 9999;
}

#base-modal-level-1 > .modal-underlay {
    position: absolute;
    inset: 0;
    cursor: pointer;
    z-index: 19999;
}

.modal-overlay {
    position: absolute;
    inset: 0;
    background: rgb(0 0 0 / 0.5);
    /* Fades on its own rather than relying on the #base-modal shell fade
       below: edge drawers zero out that shell animation (see
       #base-modal:has(.phoxtail-modal-drawer)) so backdrop-filter on the
       drawer itself isn't flattened by an ancestor opacity animation. The
       scrim has no backdrop-filter, so it can safely keep fading on its
       own regardless of which content is in the placeholder. */
    animation: fadeIn 0.3s ease-out;
}

#base-modal.closing .modal-overlay,
#base-modal-level-1.closing .modal-overlay {
    animation: fadeOut 0.3s ease-out forwards;
}

.modal-overlay-transparent {
    position: absolute;
    inset: 0;
    background: transparent;
}

#core-modal-placeholder {
    position: relative;
    z-index: 10000;
}

#core-modal-level-1-placeholder {
    position: relative;
    z-index: 20000;
}

/* Base modal overlay animations */
#base-modal,
#base-modal-level-1 {
    animation: fadeIn 0.3s ease-out;
}

#base-modal.closing,
#base-modal-level-1.closing {
    animation: fadeOut 0.3s ease-out forwards;
}

/* Edge-drawer primitive: any slide-left/slide-right modal whose visible box
   is a narrow fixed-width panel (not the full placeholder) opts in with
   .phoxtail-modal-drawer instead of hand-rolling position/width/height in
   its own stylesheet. Consumers may still override width/background/etc;
   this only owns geometry + the edge it anchors to. */
.phoxtail-modal-drawer {
    position: fixed;
    top: 0;
    height: 100vh;
    height: 100dvh;
    width: var(--phoxtail-drawer-width, 27.5rem);
    max-width: 100vw;
}
[data-animation-type="slide-left"] .phoxtail-modal-drawer { left: 0; }
[data-animation-type="slide-right"] .phoxtail-modal-drawer { right: 0; }

/* Glass drawer skin: an opt-in surface + chrome layer for .phoxtail-modal-drawer,
   pulled out of the various hand-rolled per-app copies (rga-*, evta-*, tka-*, ...)
   that were all reproducing the phoxtail-chatbot-drawer glassmorphism look. Add
   this class alongside .phoxtail-modal-drawer to get it; width stays a per-consumer
   override (set --phoxtail-drawer-width on the element) since content drives it. */
.phoxtail-modal-overlay {
    height: 100vh;
    display: flex;
    align-items: stretch;
    justify-content: flex-end;
}

.phoxtail-drawer--glass {
    z-index: 50;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background-color: rgb(var(--color-surface-50, 255 255 255) / 0.88);
    backdrop-filter: blur(28px) saturate(1.6);
    -webkit-backdrop-filter: blur(28px) saturate(1.6);
    border-left: 1px solid rgb(0 0 0 / 0.07);
    box-shadow: -8px 0 48px rgba(0, 0, 0, 0.1), inset 0.5px 0 0 rgb(255 255 255 / 0.6);
    font-family: var(--font-ui, system-ui, -apple-system, sans-serif);
}

/* Left-anchored drawers: flip the edge the border/shadow read from, same
   attribute this element's own position (left: 0 vs right: 0) already reads. */
[data-animation-type="slide-left"] .phoxtail-drawer--glass {
    border-left: none;
    border-right: 1px solid rgb(0 0 0 / 0.07);
    box-shadow: 8px 0 48px rgba(0, 0, 0, 0.1), inset -0.5px 0 0 rgb(255 255 255 / 0.6);
}

.phoxtail-drawer__scroll {
    display: flex;
    flex-direction: column;
    flex: 1;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: rgb(0 0 0 / 0.12) transparent;
}

.phoxtail-drawer__scroll::-webkit-scrollbar {
    width: 4px;
}

.phoxtail-drawer__scroll::-webkit-scrollbar-track {
    background: transparent;
}

.phoxtail-drawer__scroll::-webkit-scrollbar-thumb {
    background-color: rgb(0 0 0 / 0.12);
    border-radius: 100px;
}

.phoxtail-drawer__scroll::-webkit-scrollbar-thumb:hover {
    background-color: rgb(0 0 0 / 0.2);
}

.phoxtail-drawer__header {
    flex-shrink: 0;
    padding: 1.5rem;
    border-bottom: 1px solid rgb(0 0 0 / 0.06);
}

.phoxtail-drawer__title-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.phoxtail-drawer__title {
    margin: 0;
    font-size: 1.125rem;
    font-weight: 700;
    color: rgb(var(--color-surface-900));
    line-height: 1.3;
}

.phoxtail-drawer__body {
    flex: 1;
    padding: 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
}

.phoxtail-drawer__footer {
    flex-shrink: 0;
    padding: 1rem 1.5rem;
    border-top: 1px solid rgb(0 0 0 / 0.06);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 0.75rem;
}

.phoxtail-close-btn {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    min-width: 1.75rem;
    border-radius: 50%;
    border: 1px solid rgb(0 0 0 / 0.08);
    background-color: rgb(var(--color-surface-50, 255 255 255) / 0.7);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: rgb(var(--color-surface-400, 161 161 170));
    cursor: pointer;
    padding: 0;
    font-family: inherit;
    line-height: 1;
    transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}

.phoxtail-close-btn:hover {
    background-color: rgb(0 0 0 / 0.06);
    border-color: rgb(0 0 0 / 0.14);
    color: rgb(var(--color-surface-700, 63 63 70));
}

.phoxtail-close-btn:focus-visible {
    outline: 2px solid rgb(var(--color-surface-400) / 0.5);
    outline-offset: 2px;
}

.phoxtail-close-btn svg {
    width: 0.875rem;
    height: 0.875rem;
    display: block;
}

.phoxtail-form-stack {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
}

.phoxtail-danger-section {
    width: 100%;
    box-sizing: border-box;
    border-radius: 1rem;
    padding: 1.25rem;
    background-color: rgb(255 255 255 / 0.3);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgb(0 0 0 / 0.06);
}

.phoxtail-danger-section__header {
    display: flex;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.phoxtail-danger-section__icon-wrap {
    flex-shrink: 0;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    background-color: rgb(var(--color-destructive-100, 254 226 226));
    color: rgb(var(--color-destructive-600, 220 38 38));
    display: flex;
    align-items: center;
    justify-content: center;
}

.phoxtail-danger-section__icon-wrap svg {
    width: 1.25rem;
    height: 1.25rem;
    display: block;
}

.phoxtail-danger-section__title {
    font-size: 1rem;
    font-weight: 700;
    color: rgb(var(--color-surface-900));
    margin: 0 0 0.25rem;
}

.phoxtail-danger-section__text {
    font-size: 0.8125rem;
    color: rgb(var(--color-surface-500));
    line-height: 1.5;
    margin: 0;
}

/* Modal footer buttons: same discover-as-needed approach as the drawer skin
   above — types ported here are exactly the ones the reference modal
   (Edit/Connect/Disconnect Remote) already uses. Add a new .phoxtail-btn--*
   type only when a modal actually needs one that isn't here yet. */
.phoxtail-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    padding: 0.5rem 1.25rem;
    border-radius: 999px;
    border: 1px solid transparent;
    font-size: 0.875rem;
    font-weight: 600;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease, transform 100ms ease;
}

.phoxtail-btn:active {
    transform: scale(0.98);
}

.phoxtail-btn--primary {
    border-color: rgb(var(--color-surface-900, 9 9 11));
    background: rgb(var(--color-surface-900, 9 9 11));
    color: #fff;
}

.phoxtail-btn--primary:hover {
    background: rgb(var(--color-surface-800, 39 39 42));
    border-color: rgb(var(--color-surface-800, 39 39 42));
    color: #fff;
}

.phoxtail-btn--secondary {
    border-color: rgb(var(--color-surface-200, 228 228 231));
    background: rgb(var(--color-surface-100, 244 244 245));
    color: rgb(var(--color-surface-600, 82 82 91));
}

.phoxtail-btn--secondary:hover {
    background: rgb(var(--color-surface-200, 228 228 231));
    border-color: rgb(var(--color-surface-300, 212 212 216));
}

.phoxtail-btn--danger {
    border-color: rgba(220, 38, 38, 0.2);
    background-color: rgba(220, 38, 38, 0.08);
    color: rgb(220, 38, 38);
}

.phoxtail-btn--danger:hover {
    background-color: rgb(220 38 38);
    color: #fff;
    border-color: rgb(220 38 38);
}

.phoxtail-btn--full {
    width: 100%;
}

@media (prefers-color-scheme: dark) {
    .phoxtail-btn--primary {
        background: rgb(var(--color-surface-800, 39 39 42));
        border-color: rgb(var(--color-surface-700, 63 63 70));
        color: #fff;
    }

    .phoxtail-btn--primary:hover {
        background: rgb(var(--color-surface-700, 63 63 70));
        border-color: rgb(var(--color-surface-600, 82 82 91));
        color: #fff;
    }

    .phoxtail-btn--secondary {
        background: rgb(var(--color-surface-900, 24 24 27) / 0.6);
        border-color: rgb(var(--color-surface-700, 63 63 70));
        color: rgb(var(--color-surface-300, 212 212 216));
    }

    .phoxtail-btn--secondary:hover {
        background: rgb(var(--color-surface-800, 39 39 42) / 0.7);
        border-color: rgb(var(--color-surface-600, 82 82 91));
    }

    .phoxtail-btn--danger {
        background-color: rgba(220, 38, 38, 0.15);
        border-color: rgba(220, 38, 38, 0.25);
        color: #fca5a5;
    }

    .phoxtail-btn--danger:hover {
        background-color: rgb(220 38 38);
        border-color: rgb(220 38 38);
        color: white;
    }
}

/* Same glass surface as .phoxtail-drawer--glass, adapted for a centered dialog
   (border all around instead of left-edge-only, symmetric shadow instead of
   a cast-to-one-side one). Add alongside a consumer's own geometry class
   (radius, max-width, overflow) the same way .phoxtail-drawer--glass adds
   onto .phoxtail-modal-drawer. */
.phoxtail-dialog--glass {
    background-color: rgb(var(--color-surface-50, 255 255 255) / 0.88);
    backdrop-filter: blur(28px) saturate(1.6);
    -webkit-backdrop-filter: blur(28px) saturate(1.6);
    border: 1px solid rgb(0 0 0 / 0.07);
    box-shadow: 0 20px 60px -10px rgb(0 0 0 / 0.25), inset 0 0.5px 0 rgb(255 255 255 / 0.6);
}

@media (prefers-color-scheme: dark) {
    .phoxtail-dialog--glass {
        background-color: rgb(var(--color-surface-950, 12 12 16) / 0.88);
        border-color: rgb(255 255 255 / 0.08);
        box-shadow: 0 20px 60px -10px rgb(0 0 0 / 0.6), inset 0 0.5px 0 rgb(255 255 255 / 0.06);
    }
}

/* The --color-surface-* scale is a fixed light->dark ramp (50=near-white,
   950=near-black); it is NOT redefined per color-scheme. Each component
   using it for a themed surface must swap which end of the scale it reads
   here, same as every other dark-mode block in this codebase. */
@media (prefers-color-scheme: dark) {
    .phoxtail-drawer--glass {
        background-color: rgb(var(--color-surface-950, 12 12 16) / 0.88);
        border-left-color: rgb(255 255 255 / 0.08);
        box-shadow: -8px 0 48px rgba(0, 0, 0, 0.5), inset 0.5px 0 0 rgb(255 255 255 / 0.06);
    }

    [data-animation-type="slide-left"] .phoxtail-drawer--glass {
        border-right-color: rgb(255 255 255 / 0.08);
        box-shadow: 8px 0 48px rgba(0, 0, 0, 0.5), inset -0.5px 0 0 rgb(255 255 255 / 0.06);
    }

    .phoxtail-drawer__scroll {
        scrollbar-color: rgb(255 255 255 / 0.12) transparent;
    }

    .phoxtail-drawer__scroll::-webkit-scrollbar-thumb {
        background-color: rgb(255 255 255 / 0.12);
    }

    .phoxtail-drawer__scroll::-webkit-scrollbar-thumb:hover {
        background-color: rgb(255 255 255 / 0.2);
    }

    .phoxtail-drawer__header {
        border-bottom-color: rgb(255 255 255 / 0.07);
    }

    .phoxtail-drawer__title {
        color: rgb(var(--color-surface-100));
    }

    .phoxtail-drawer__footer {
        border-top-color: rgb(255 255 255 / 0.07);
    }

    .phoxtail-close-btn {
        background-color: rgb(var(--color-surface-950, 12 12 16) / 0.7);
        border-color: rgb(255 255 255 / 0.1);
        color: rgb(var(--color-surface-500, 113 113 122));
    }

    .phoxtail-close-btn:hover {
        background-color: rgb(255 255 255 / 0.08);
        border-color: rgb(255 255 255 / 0.2);
        color: white;
    }

    .phoxtail-danger-section {
        background-color: rgb(0 0 0 / 0.2);
        border-color: rgb(255 255 255 / 0.07);
    }

    .phoxtail-danger-section__title {
        color: rgb(var(--color-surface-100));
    }

    .phoxtail-danger-section__text {
        color: rgb(var(--color-surface-400));
    }

    .phoxtail-danger-section__icon-wrap {
        background-color: rgb(var(--color-destructive-900, 127 29 29) / 0.5);
        color: rgb(248 113 113);
    }
}

/* Side-drawer modals using the primitive move like the chatbot drawer: an
   OPAQUE slide, no fade. The shell must not fade either — the placeholder
   lives inside it, so a shell fade would stack on the drawer. On close the
   shell runs a visually inert "hold" animation purely so animationend fires
   at the drawer's 0.5s mark (removal is keyed to the shell's own animation
   ending). Keyed off .phoxtail-modal-drawer itself (not the animation-type
   value) so it covers both edges uniformly. */
#base-modal:has(.phoxtail-modal-drawer),
#base-modal-level-1:has(.phoxtail-modal-drawer) {
    animation: none;
}

#base-modal.closing:has(.phoxtail-modal-drawer),
#base-modal-level-1.closing:has(.phoxtail-modal-drawer) {
    animation: modalHold 0.5s linear forwards;
}

/* Content animation types */
#core-modal-placeholder[data-animation-type="slide-down"],
#core-modal-level-1-placeholder[data-animation-type="slide-down"] {
    animation: slideDownIn 0.3s ease-out;
}

#base-modal.closing #core-modal-placeholder[data-animation-type="slide-down"],
#base-modal-level-1.closing #core-modal-level-1-placeholder[data-animation-type="slide-down"] {
    animation: slideDownOut 0.3s ease-out;
}

#core-modal-placeholder[data-animation-type="slide-up"],
#core-modal-level-1-placeholder[data-animation-type="slide-up"] {
    animation: slideUpIn 0.3s ease-out;
}

#base-modal.closing #core-modal-placeholder[data-animation-type="slide-up"],
#base-modal-level-1.closing #core-modal-level-1-placeholder[data-animation-type="slide-up"] {
    animation: slideUpOut 0.3s ease-out;
}

/* :not(:has(.phoxtail-modal-drawer)) excludes edge drawers using the
   primitive — those get their transform from the drawer-scoped rules below
   instead (see the comment there for why placeholder-level and drawer-level
   transforms can't both apply). */
#core-modal-placeholder[data-animation-type="slide-right"]:not(:has(.phoxtail-modal-drawer)),
#core-modal-level-1-placeholder[data-animation-type="slide-right"]:not(:has(.phoxtail-modal-drawer)) {
    animation: slideRightIn 0.3s ease-out;
}

#base-modal.closing #core-modal-placeholder[data-animation-type="slide-right"]:not(:has(.phoxtail-modal-drawer)),
#base-modal-level-1.closing #core-modal-level-1-placeholder[data-animation-type="slide-right"]:not(:has(.phoxtail-modal-drawer)) {
    animation: slideRightOut 0.32s ease-in;
}

#core-modal-placeholder[data-animation-type="fade"],
#core-modal-level-1-placeholder[data-animation-type="fade"] {
    animation: fadeIn 0.3s ease-out;
}

#base-modal.closing #core-modal-placeholder[data-animation-type="fade"],
#base-modal-level-1.closing #core-modal-level-1-placeholder[data-animation-type="fade"] {
    animation: fadeOut 0.3s ease-out;
}

/* Edge drawers using the primitive: same motion signature as the chatbot
   drawer's slide — opaque, no fade. The transform runs on the drawer's own
   fixed-width box (.phoxtail-modal-drawer), not on the placeholder: the
   placeholder is a position:fixed; inset:0 (full-viewport) wrapper, so a
   transform applied there travels the viewport's width while the visible
   drawer is only 27.5rem — it would sit off-screen for most of the eased
   timeline and only enter/exit view in a sliver of it, same as the chatbot
   drawer, whose transform lives on its own 27.5rem element. */
[data-animation-type="slide-left"] .phoxtail-modal-drawer {
    animation: drawerSlideLeftIn 0.5s cubic-bezier(0.45, 0, 0.2, 1);
}

#base-modal.closing [data-animation-type="slide-left"] .phoxtail-modal-drawer,
#base-modal-level-1.closing [data-animation-type="slide-left"] .phoxtail-modal-drawer {
    animation: drawerSlideLeftOut 0.5s cubic-bezier(0.45, 0, 0.2, 1) forwards;
}

[data-animation-type="slide-right"] .phoxtail-modal-drawer {
    animation: drawerSlideRightIn 0.5s cubic-bezier(0.45, 0, 0.2, 1);
}

#base-modal.closing [data-animation-type="slide-right"] .phoxtail-modal-drawer,
#base-modal-level-1.closing [data-animation-type="slide-right"] .phoxtail-modal-drawer {
    animation: drawerSlideRightOut 0.5s cubic-bezier(0.45, 0, 0.2, 1) forwards;
}

#core-modal-placeholder[data-animation-type="none"],
#core-modal-level-1-placeholder[data-animation-type="none"] {
    animation: none;
}

/* Keyframes (shared by all modals) */
@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

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

@keyframes slideDownIn {
    from {
        opacity: 0;
        transform: translateY(-100%);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes slideDownOut {
    from {
        opacity: 1;
        transform: translateY(0);
    }
    to {
        opacity: 0;
        transform: translateY(-100%);
    }
}

@keyframes slideUpIn {
    from {
        opacity: 0;
        transform: translateY(100%);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes slideUpOut {
    from {
        opacity: 1;
        transform: translateY(0);
    }
    to {
        opacity: 0;
        transform: translateY(100%);
    }
}

@keyframes slideRightIn {
    from {
        opacity: 0;
        transform: translateX(100%);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes slideRightOut {
    from {
        opacity: 1;
        transform: translateX(0);
    }
    to {
        opacity: 0;
        transform: translateX(100%);
    }
}

/* Opaque drawer slide (no opacity coupling) + a visually inert hold used to
   time the shell's animationend on drawer close. */
@keyframes drawerSlideLeftIn {
    from { transform: translateX(-100%); }
    to { transform: translateX(0); }
}

@keyframes drawerSlideLeftOut {
    from { transform: translateX(0); }
    to { transform: translateX(-100%); }
}

@keyframes drawerSlideRightIn {
    from { transform: translateX(100%); }
    to { transform: translateX(0); }
}

@keyframes drawerSlideRightOut {
    from { transform: translateX(0); }
    to { transform: translateX(100%); }
}

/* Deliberately NOT opacity: animating opacity (even a 1->1 no-op) promotes
   the shell to an isolated compositing layer for the animation's duration,
   which cuts off the drawer's backdrop-filter from sampling real page
   content behind it — the glassmorphism blur goes flat for the whole close
   slide. background-color is inert here (the shell has no visible fill)
   but still fires animationend at the same 0.5s mark. */
@keyframes modalHold {
    from { background-color: transparent; }
    to { background-color: transparent; }
}

@keyframes slideLeftIn {
    from {
        opacity: 0;
        transform: translateX(-100%);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

@keyframes slideLeftOut {
    from {
        opacity: 1;
        transform: translateX(0);
    }
    to {
        opacity: 0;
        transform: translateX(-100%);
    }
}
