/* AI Chat Side Panel */
:root {
    --chat-panel-width: 640px;
    /* Space reserved for the panel on the page. Diverges from the panel width once
       the content hits its floor: then the padding is pinned and the panel overlays. */
    --chat-panel-pad: 640px;
}

.fi-chat-panel {
    position: fixed;
    top: 0;
    right: 0;
    width: var(--chat-panel-width);
    height: 100vh;
    height: 100dvh;
    /* Above the app chrome (sidebar/topbar = 30) but below Filament modals
       (backdrop/window = 40, stacked = 50) so dialogs always render on top. */
    z-index: 39;
    background: white;
    border-left: 1px solid var(--color-gray-200);
}

:is(.dark .fi-chat-panel) {
    background: var(--color-gray-950);
    border-left-color: var(--color-gray-700);
}


.fi-chat-panel-inner {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}

.fi-chat-panel-resize {
    position: absolute;
    top: 0;
    left: -3px;
    bottom: 0;
    width: 6px;
    cursor: col-resize;
    z-index: 31;
}

.fi-chat-panel-resize:hover,
.fi-chat-panel-resize:active {
    background: var(--color-primary-500);
    opacity: 0.4;
}

/* Mobile-only scrim behind the panel. Tapping it (incl. the exposed strip the
   panel leaves on the left) closes the panel. Hidden on desktop, where the body
   is padded instead of overlaid. */
.fi-chat-panel-backdrop {
    position: fixed;
    inset: 0;
    z-index: 38;
    background-color: rgba(0, 0, 0, 0.4);
}

@media (min-width: 768px) {
    .fi-chat-panel-backdrop {
        display: none !important;
    }
}

/* When panel is open: lock body scroll, app content scrolls independently */
body.fi-chat-panel-open {
    overflow: hidden;
    height: 100vh;
    height: 100dvh;
    padding-right: var(--chat-panel-pad);
    transition: padding-right 300ms ease;
}

body:not(.fi-chat-panel-open) {
    transition: padding-right 200ms ease;
}

body.fi-chat-panel-open .fi-main-ctn {
    overflow-y: auto;
    height: calc(100vh - 4rem);
    height: calc(100dvh - 4rem);
}

/* Mobile: near-full overlay, leaving a strip of the page visible on the left */
@media (max-width: 767px) {
    .fi-chat-panel {
        width: calc(100% - 3rem) !important;
        border-left: none;
        box-shadow: -8px 0 24px rgba(0, 0, 0, 0.18);
        padding-bottom: env(safe-area-inset-bottom, 0px);
    }

    .fi-chat-panel-resize {
        display: none;
    }

    body.fi-chat-panel-open {
        padding-right: 0;
    }
}

/* Code block copy button */
.code-block-wrapper {
    position: relative;
    margin: 1em 0;
    max-width: 100%;
}

.code-block-wrapper pre {
    margin: 0 !important;
    border-top-left-radius: 0 !important;
    border-top-right-radius: 0 !important;
    max-width: 100%;
    /* Scroll long code lines instead of letting them expand the message and get
       clipped by the ancestor's overflow-x-hidden (cut off on narrow screens). */
    overflow-x: auto;
}

.code-block-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.35rem 0.75rem;
    background: rgba(0, 0, 0, 0.06);
    border-top-left-radius: 0.5rem;
    border-top-right-radius: 0.5rem;
    font-size: 0.7rem;
}

:is(.dark .code-block-header) {
    background: rgba(255, 255, 255, 0.06);
}

.code-block-lang {
    color: var(--color-gray-500);
    font-family: var(--font-mono);
    text-transform: lowercase;
}

.code-copy-btn {
    color: var(--color-gray-500);
    font-size: 0.7rem;
    font-family: var(--font-sans);
    cursor: pointer;
    padding: 0.1rem 0.4rem;
    border-radius: 0.25rem;
    transition: color 0.15s, background 0.15s;
    margin-left: auto;
}

.code-copy-btn:hover {
    color: var(--color-gray-800);
    background: rgba(0, 0, 0, 0.06);
}

:is(.dark .code-copy-btn:hover) {
    color: var(--color-gray-200);
    background: rgba(255, 255, 255, 0.08);
}

/* Minimal scrollbars */
.fi-main-ctn,
.fi-chat-panel-inner,
.fi-chat-panel-inner * {
    scrollbar-width: thin;
    scrollbar-color: rgba(0, 0, 0, 0.15) transparent;
}

:is(.dark .fi-main-ctn),
:is(.dark .fi-chat-panel-inner),
:is(.dark .fi-chat-panel-inner *) {
    scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
}

.fi-main-ctn::-webkit-scrollbar,
.fi-chat-panel-inner ::-webkit-scrollbar {
    width: 6px;
}

.fi-main-ctn::-webkit-scrollbar-track,
.fi-chat-panel-inner ::-webkit-scrollbar-track {
    background: transparent;
}

.fi-main-ctn::-webkit-scrollbar-thumb,
.fi-chat-panel-inner ::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.15);
    border-radius: 3px;
}

.fi-main-ctn::-webkit-scrollbar-thumb:hover,
.fi-chat-panel-inner ::-webkit-scrollbar-thumb:hover {
    background: rgba(0, 0, 0, 0.3);
}

:is(.dark .fi-main-ctn)::-webkit-scrollbar-thumb,
:is(.dark .fi-chat-panel-inner) ::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.15);
}

:is(.dark .fi-main-ctn)::-webkit-scrollbar-thumb:hover,
:is(.dark .fi-chat-panel-inner) ::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.3);
}

/* Photoshop-style transparency checkerboard, applied as the background of
   inline images so transparent regions of PNGs/SVGs read as transparent
   instead of blending into the dark chat surface. The image sits on top, so
   opaque formats (JPEG) simply cover the pattern. Light grey + white is the
   universal "transparent" signal across design tools, in both themes. */
.transparent-checkerboard {
    background-color: #ffffff;
    background-image:
        linear-gradient(45deg, #d4d4d8 25%, transparent 25%),
        linear-gradient(-45deg, #d4d4d8 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #d4d4d8 75%),
        linear-gradient(-45deg, transparent 75%, #d4d4d8 75%);
    background-size: 16px 16px;
    background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}

/* ARP loader: morphing square for the AI waiting state.
   Pure-CSS animation: corner radii flip in/out of round shapes while the fill
   cycles around the full HSL color wheel. The two animations run on different
   durations so the corner + color combos never repeat exactly. */

@keyframes arp-morph-corners {
    0%   { border-radius: 50% 50% 50% 50%; }
    12%  { border-radius:   0% 50% 50% 50%; }
    24%  { border-radius: 50%   0% 50% 50%; }
    36%  { border-radius: 50% 50%   0% 50%; }
    48%  { border-radius: 50% 50% 50%   0%; }
    60%  { border-radius:   0%   0% 50% 50%; }
    72%  { border-radius: 50%   0%   0% 50%; }
    84%  { border-radius: 50% 50%   0%   0%; }
    100% { border-radius:   0% 50% 50%   0%; }
}

@keyframes arp-morph-hue {
    0%   { background-color: hsl(  0 75% 55%); }
    16%  { background-color: hsl( 60 75% 55%); }
    33%  { background-color: hsl(120 75% 45%); }
    50%  { background-color: hsl(180 75% 45%); }
    66%  { background-color: hsl(240 70% 60%); }
    83%  { background-color: hsl(300 70% 55%); }
    100% { background-color: hsl(360 75% 55%); }
}

.arp-morph {
    background-color: hsl(0 75% 55%);
    border-radius: 50%;
    animation:
        arp-morph-corners 6.5s cubic-bezier(0.4, 0, 0.2, 1) infinite,
        arp-morph-hue 10s linear infinite;
    will-change: border-radius, background-color;
}

@media (prefers-reduced-motion: reduce) {
    .arp-morph {
        animation: none;
        border-radius: 25%;
    }
}

/* Inside a tool card frame the plain success marker is noise (it's a timeline
   marker; the card frame already sets the result apart) — hide it there.
   Error/warning icons and the spinning pending marker keep rendering: they
   carry state the card needs. */
.ai-tool-card .tool-status-marker--plain {
    display: none;
}

/* Activity segments (both chat widgets)
   ------------------------------------------------------------------
   A collapsed segment hides its step rows through THIS descendant rule, keyed
   off a class on the wrapper, rather than a per-row Alpine `x-show`. The rows
   belong to nested Livewire components, so an x-show bound to the parent's
   scope goes stale exactly when new steps stream in: the header collapses and
   the rows stay visible. A CSS rule follows the wrapper's CURRENT class however
   the morph moved the rows around. Cards are never `.activity-step`, so a card
   inside a fold always stays visible. */
.activity-segment:not(.activity-open) .activity-step {
    display: none;
}

/* The caret reads the same class as the rows, so the two can never disagree
   (an Alpine binding on the icon could). */
.activity-segment.activity-open .activity-caret {
    transform: rotate(90deg);
}

/* Timeline "jump to latest"
   ------------------------------------------------------------------
   Visibility is applied as an inline style by the client (see
   resources/js/components/chat-timeline.js), so only the transition and the
   working-state glow live here. */
.timeline-jump {
    transition: opacity 0.2s ease-out;
}

@keyframes timeline-jump-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgb(var(--primary-500, 59 130 246) / 0.45); }
    50%      { box-shadow: 0 0 0 6px rgb(var(--primary-500, 59 130 246) / 0); }
}

.timeline-jump-pulse {
    animation: timeline-jump-pulse 1.8s ease-out infinite;
}

@media (prefers-reduced-motion: reduce) {
    .timeline-jump-pulse {
        animation: none;
    }
}

/* Record sub-navigation sidebar (e.g. the chats list on chat view pages)
   ------------------------------------------------------------------
   Filament renders it as a plain in-flow column with no height cap, so a long
   list stretches the page into a second scrollbar alongside the chat's own.
   Cap it to the viewport (sticky under the 4rem topbar) and let it scroll
   internally. Short sub-navs (project pages) are unaffected by the cap. */
.fi-page-has-sub-navigation-start .fi-page-sub-navigation-sidebar-ctn,
.fi-page-has-sub-navigation-end .fi-page-sub-navigation-sidebar-ctn {
    position: sticky;
    top: 5rem;
    max-height: calc(100dvh - 6rem);
    overflow-y: auto;
    scrollbar-gutter: stable;
}
