/* study-browse-panel.css — Khio's browser, docked beside the Khio AI chat.
   James 2026-09-11.

   Paired with public/js/study/study-browse-panel.js, which appends a single
   <aside id="khioBrowsePanel"> to <body> and toggles body.khio-browse-open.
   Everything here is scoped to that id or to that body class, so nothing in
   the rest of Study can be touched by it.

   Look: the same frosted glass as the Khio AI chat's rail and input bar
   (study-deeptutor-glass.css) — translucent white over the chat's gradient in
   light, translucent white over black in dark, dark keyed off
   html[data-theme="dark"] like the rest of the Study theme system.

   VIEWPORTS (CLAUDE.md §13.7 / the CSS LAYER GUIDE in study-themes.css):
     desktop  body.khio-desktop  — the umbrella, both laptop-scale and wide:
                                   the panel is pinned to the right edge.
                                   Whether the CHAT gives up the width for it
                                   is a width question, not a machine
                                   question, so it is a media query:
                                     ≥ 1280  dock — 300 sidebar + 560 thread
                                             + 420 panel is the narrowest the
                                             thread is still readable at
                                     < 1280  float over the chat as a card
                                   1024 used to dock too, which left a 304px
                                   chat column with a clipped composer.
              body.khio-desktop-wide — a wider panel (≥1908), because the
                                   picture is the point and the thread still
                                   keeps 1100px+.
     mobile   @media (max-width: 1023px) — a full-height sheet over the chat.
   The mobile half is a media query, not body.khio-mobile: NO JavaScript sets
   that class (see the warning in CLAUDE.md §13.7) and the Capacitor shell
   carries none of the viewport classes at all. */

:root {
    --khio-bp-w: 420px;
}
body.khio-desktop-wide {
    --khio-bp-w: 520px;
}

#khioBrowsePanel {
    position: fixed;
    /* Over the chat and its composer, under everything study-deeptutor.js
       stacks above it: the chat-actions menu, the mobile drawer and the
       modals all start at 1300. */
    z-index: 1200;
    top: 0;
    right: 0;
    bottom: 0;
    width: var(--khio-bp-w);
    max-width: 100vw;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px 14px calc(14px + var(--khio-kbh, 0px));
    box-sizing: border-box;
    -webkit-backdrop-filter: blur(22px) saturate(150%);
    backdrop-filter: blur(22px) saturate(150%);
    background: rgba(255, 255, 255, .72);
    border-left: 1px solid rgba(255, 255, 255, .85);
    box-shadow: -10px 0 30px rgba(80, 100, 140, .12);
    /* Explicit ink in both themes, NOT var(--study-text). The panel's dark
       skin is keyed on html[data-theme="dark"] but --study-text comes from
       body[data-scheme] + the Study palette, and on /askai those two can
       disagree (a forced day palette under a dark data-theme) — which paints
       #2d2f31 text on a #141416 panel. Verified in the browser 2026-09-12. */
    color: #15172a;
    font-size: 13px;
    overflow-y: auto;
    overscroll-behavior: contain;
}
#khioBrowsePanel[hidden] { display: none; }

html[data-theme="dark"] #khioBrowsePanel {
    background: rgba(20, 20, 22, .88);
    border-left: 1px solid rgba(255, 255, 255, .12);
    box-shadow: -10px 0 30px rgba(0, 0, 0, .5);
    color: #f2f2f4;
}

/* Wide enough to dock: the chat gives up the width rather than sliding under
   the panel, because a docked panel that covers the composer is worse than a
   narrower thread. */
@media (min-width: 1280px) {
    body.khio-desktop.khio-browse-open #dt2Main { margin-right: var(--khio-bp-w); }
}

/* Not wide enough to dock: float over the chat as a card instead of squeezing
   the thread into a gutter. Inset and rounded so it reads as a layer in front
   rather than a broken column, and Esc / × puts the thread back. */
@media (min-width: 1024px) and (max-width: 1279px) {
    #khioBrowsePanel {
        top: 12px;
        bottom: 12px;
        right: 12px;
        border-radius: 18px;
        border-left: 0;
        border: 1px solid rgba(255, 255, 255, .85);
        box-shadow: 0 18px 50px rgba(15, 23, 42, .22);
    }
    html[data-theme="dark"] #khioBrowsePanel {
        border: 1px solid rgba(255, 255, 255, .12);
        box-shadow: 0 18px 50px rgba(0, 0, 0, .6);
    }
}

/* ── header ── */
.khio-bp-head { display: flex; align-items: center; gap: 8px; }
.khio-bp-title { font-weight: 600; font-size: 14px; }
.khio-bp-site {
    flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    opacity: .65; font-variant-numeric: tabular-nums;
}
.khio-bp-x {
    flex: 0 0 auto; width: 28px; height: 28px; border: 0; border-radius: 999px;
    background: transparent; color: inherit; font-size: 18px; line-height: 1; cursor: pointer;
}
.khio-bp-x:hover { background: rgba(15, 23, 42, .07); }
html[data-theme="dark"] .khio-bp-x:hover { background: rgba(255, 255, 255, .10); }

/* ── status strip ── */
.khio-bp-status {
    min-height: 18px; opacity: .8; line-height: 1.4;
}
.khio-bp-status b { font-weight: 600; }
/* The step counter. Quiet, and it must not wrap on its own. */
.khio-bp-step {
    display: inline-block; margin-left: 5px; padding: 1px 7px; border-radius: 999px;
    background: rgba(15, 23, 42, .07); font-size: 11px; white-space: nowrap; opacity: .85;
}
html[data-theme="dark"] .khio-bp-step { background: rgba(255, 255, 255, .10); }

/* ── the live frame ── */
.khio-bp-stage {
    position: relative;
    border-radius: 12px;
    overflow: hidden;
    /* Idle is a quiet well, not a black slab: 180px of pure black in a cream
       panel read as a dead screen rather than "nothing is running". Black is
       for when there is actually a picture in it, where it is the letterbox. */
    background: rgba(15, 23, 42, .045);
    border: 1px solid rgba(15, 23, 42, .10);
    min-height: 180px;
    display: flex; align-items: center; justify-content: center;
}
.khio-bp-stage.has-frame { background: #0d0d0f; }
html[data-theme="dark"] .khio-bp-stage { background: rgba(255, 255, 255, .05); border-color: rgba(255, 255, 255, .12); }
html[data-theme="dark"] .khio-bp-stage.has-frame { background: #0d0d0f; }
/* max-* only, never a set width: the box then measures exactly the painted
   picture, which is what onStageClick turns a click into a page coordinate
   with (getBoundingClientRect × frameW/rect.width). A stretched or
   object-fit'd image would make that arithmetic lie. The stage's own flex
   centring is what letterboxes a frame that does not fill it. */
.khio-bp-stage img {
    display: block; margin: 0 auto;
    max-width: 100%; max-height: 46vh; width: auto; height: auto;
}
/* Between "a task started" and the first frame landing there is no src, and a
   sourceless <img> paints its alt text as broken-image copy across the stage.
   The status line is already saying "Opening a browser…"; the stage just stays
   empty until there is something real to show. */
.khio-bp-stage img:not([src]) { display: none; }
.khio-bp-stage.is-driving { outline: 2px solid #0a84ff; outline-offset: -2px; cursor: crosshair; }
.khio-bp-stage-empty { padding: 28px 16px; color: inherit; opacity: .5; text-align: center; font-size: 12px; }

/* ── how old the picture is, and a way to not wait ── */
.khio-bp-frameline { display: flex; align-items: center; gap: 8px; margin-top: -3px; }
.khio-bp-stamp {
    flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 11px; opacity: .55; font-variant-numeric: tabular-nums;
}
.khio-bp-refresh {
    flex: 0 0 auto; padding: 3px 10px; border-radius: 999px;
    border: 1px solid rgba(15, 23, 42, .14); background: rgba(255, 255, 255, .6);
    color: inherit; font: inherit; font-size: 11.5px; cursor: pointer;
}
.khio-bp-refresh:hover { background: rgba(255, 255, 255, .95); }
html[data-theme="dark"] .khio-bp-refresh { background: rgba(255, 255, 255, .09); border-color: rgba(255, 255, 255, .16); }
html[data-theme="dark"] .khio-bp-refresh:hover { background: rgba(255, 255, 255, .16); }

/* ── buttons ── */
.khio-bp-row { display: flex; flex-wrap: wrap; gap: 8px; }
.khio-bp-btn {
    flex: 1 1 auto; min-height: 34px; padding: 7px 12px;
    border: 1px solid rgba(15, 23, 42, .14); border-radius: 10px;
    background: rgba(255, 255, 255, .7); color: inherit;
    font: inherit; font-weight: 500; cursor: pointer;
}
.khio-bp-btn:hover { background: rgba(255, 255, 255, .95); }
.khio-bp-btn[disabled] { opacity: .45; cursor: default; }
.khio-bp-btn.is-primary { background: #0a84ff; border-color: #0a84ff; color: #fff; }
.khio-bp-btn.is-primary:hover { background: #0b76e0; }
.khio-bp-btn.is-danger { color: #dc2626; }
html[data-theme="dark"] .khio-bp-btn {
    background: rgba(255, 255, 255, .09); border-color: rgba(255, 255, 255, .16);
}
html[data-theme="dark"] .khio-bp-btn:hover { background: rgba(255, 255, 255, .16); }
html[data-theme="dark"] .khio-bp-btn.is-primary { background: #0a84ff; border-color: #0a84ff; color: #fff; }

/* ── a park: sign in, or approve a submit ── */
.khio-bp-park {
    padding: 11px 12px; border-radius: 12px;
    background: rgba(10, 132, 255, .08);
    border: 1px solid rgba(10, 132, 255, .22);
    display: flex; flex-direction: column; gap: 9px;
}
.khio-bp-park h3 { margin: 0; font-size: 13px; font-weight: 600; }
.khio-bp-park p { margin: 0; line-height: 1.4; }
.khio-bp-park label { font-size: 12px; opacity: .75; }
/* !important on the fill and the border, on both fields, in both themes.
   study-themes.css carries a global `body[data-scheme="light"] input[type="text"]
   { background: #f6f6f8 !important; border: ... }` — it hits the username box
   and not the password box, so without this the two halves of one sign-in form
   are different colours (grey box, white box). Same collision the composer pill
   documents in study-deeptutor-glass.css. !important alone is not enough: that
   selector is (0,2,2) and .khio-bp-park input[type=text] is only (0,2,1), so
   the id is load-bearing too. Verified in the browser 2026-09-12. */
#khioBrowsePanel .khio-bp-park input[type=text], #khioBrowsePanel .khio-bp-park input[type=password] {
    width: 100%; box-sizing: border-box; font: inherit; font-size: 15px;
    padding: 9px 10px; border-radius: 9px;
    border: 1px solid rgba(15, 23, 42, .18) !important;
    background: #fff !important;
    color: #15172a !important;
}
html[data-theme="dark"] #khioBrowsePanel .khio-bp-park input[type=text],
html[data-theme="dark"] #khioBrowsePanel .khio-bp-park input[type=password] {
    background: rgba(255, 255, 255, .06) !important;
    border-color: rgba(255, 255, 255, .18) !important;
    color: #f2f2f4 !important;
}
.khio-bp-fine { margin: 0; font-size: 11px; line-height: 1.4; opacity: .62; }
.khio-bp-err { margin: 0; font-size: 12px; color: #dc2626; }
.khio-bp-link {
    align-self: flex-start; padding: 0; border: 0; background: none;
    color: #0a84ff; font: inherit; font-size: 12px; cursor: pointer; text-decoration: underline;
}

/* ── the composer button ── */
.dt2-browse-btn {
    position: relative; flex: 0 0 auto;
    width: 34px; height: 34px; padding: 0; border: 0; border-radius: 999px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; color: var(--study-text-secondary, rgba(15, 23, 42, .65));
    cursor: pointer; transition: background .15s, color .15s;
}
.dt2-browse-btn:hover { background: rgba(15, 23, 42, .055); color: var(--study-text, #15172a); }
.dt2-browse-btn.is-on { color: #0a84ff; }
.dt2-browse-btn i, .dt2-browse-btn svg { width: 18px; height: 18px; }
html[data-theme="dark"] .dt2-browse-btn { color: var(--text-secondary, rgba(255, 255, 255, .66)); }
html[data-theme="dark"] .dt2-browse-btn:hover { background: rgba(255, 255, 255, .09); }
/* The live dot. Only painted while a task is actually running. */
.dt2-browse-btn .dt2-browse-dot {
    position: absolute; top: 4px; right: 4px; width: 7px; height: 7px; border-radius: 999px;
    background: #22c55e; box-shadow: 0 0 0 2px rgba(255, 255, 255, .85);
    animation: khioBpPulse 1.8s ease-out infinite;
}
html[data-theme="dark"] .dt2-browse-btn .dt2-browse-dot { box-shadow: 0 0 0 2px rgba(0, 0, 0, .7); }
@keyframes khioBpPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
    .dt2-browse-btn .dt2-browse-dot { animation: none; }
}

/* ── mobile: a sheet down from the top, stopping above the composer ──
   Safe-area insets on all four sides: the sheet starts at top:0, so without
   the top inset the title sits under the notch and the × under the status bar.
   It stops 137px short of the bottom because that is the shipped height of the
   phone composer card (1px border + 10 pad + 51 input + 6 gap + 38 button + 8
   pad + 1px border = 115, inside .dt2-composer's 10/12 padding — see the
   two-row composer note in study-deeptutor-glass.css). A full-height sheet
   covered the composer, and "reply in the chat and I'll carry on" is an
   instruction you cannot follow with the chat behind a sheet. A composer grown
   to several lines does poke under the sheet's bottom edge; the panel is still
   closable with ×, Esc, or the Reply in the chat button on a question park. */
@media (max-width: 1023px) {
    #khioBrowsePanel {
        width: 100%;
        border-left: 0;
        bottom: calc(137px + env(safe-area-inset-bottom, 0px) + var(--khio-kbh, 0px));
        border-bottom-left-radius: 20px;
        border-bottom-right-radius: 20px;
        box-shadow: 0 14px 40px rgba(15, 23, 42, .18);
        padding: calc(14px + env(safe-area-inset-top, 0px))
                 calc(14px + env(safe-area-inset-right, 0px))
                 16px
                 calc(14px + env(safe-area-inset-left, 0px));
    }
    html[data-theme="dark"] #khioBrowsePanel { box-shadow: 0 14px 40px rgba(0, 0, 0, .6); }
    /* Finger-sized, not pointer-sized. */
    .khio-bp-x { width: 40px; height: 40px; font-size: 22px; }
    .khio-bp-btn { min-height: 44px; }
    .khio-bp-refresh { padding: 7px 14px; font-size: 13px; }
    .khio-bp-stage img { max-height: 56vh; }
}
