/*
 * Copyright (c) Biovisuals Private Limited. All rights reserved.
 *
 * THE FLOATING-INSPECTOR CONTRACT (D3.1, corrected by D3.2 §1-§4).
 *
 * The surface the floating toolbar's Style action opens, replacing the D3 behaviour of
 * routing it into the asset-library bottom sheet. It hosts the SAME live control nodes
 * (`#shapeControls`, `#textTools`, and `#layerControls` where a build has one) that the
 * per-type selection handlers assemble — see utils/portraitStyleInspector.js. Nothing here
 * creates a control; everything here is presentation.
 *
 * EVERY RULE IS KEYED ON `.bv-inspector`, not on the style inspector specifically. That is the
 * D3.2 §1 requirement expressed in CSS: one window contract, reused, rather than a Shape
 * window and a Text window that drift apart. `.bv-style-inspector` is still on the host as a
 * PUBLIC selector — `contextMenu.js`'s exclusion list and the existing portrait suites match
 * on it — but no presentation depends on it.
 *
 * WHY ITS OWN STYLESHEET RATHER THAN EXTENDING THE SHEET'S RULES.
 * The sheet's contextual-edit block in `slider-container.css` is keyed on
 * `[data-bv-sheet-view="edit"] #sliderContent ...` and is built for the sheet's FULL width:
 * a `repeat(auto-fit, minmax(220px, 1fr))` grid that earns two or three columns at
 * 768-899px. This surface is deliberately a single ~320-360px column, so that grid is not just
 * unnecessary here, it would be wrong.
 */

/* ── the window ───────────────────────────────────────────────────────────────
   `position: fixed` on `document.body`: it must never become a shell grid track, because a
   track change resizes Fabric. `left`/`top`/`max-height`/`min-height` are written by JS from
   the live visual viewport.

   WIDTH RULES:
   - Default: clamp(280px, 320px, calc(100vw - 16px)) - compact width for docked layouts
   - When docked over sidebar: matches sidebar width (handled by JS)
   - In portrait: 320-360px as before
   The JS placement logic overrides width when docking to match sidebar exactly. */
.bv-inspector {
    position: fixed;
    width: clamp(280px, 320px, calc(100vw - 16px));
    max-width: calc(100vw - 16px);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    /* Above the floating toolbar (99999) and its submenus (100000), because the inspector can
       be clamped into contact with either on a short viewport. The value is unchanged; it now
       comes from the documented layer ladder in `global.css` so the inspector and the popovers
       it owns cannot drift apart on unrelated literals. */
    z-index: var(--bv-layer-inspector, 100002);
    background: #ffffff;
    border: 1px solid #d9dde3;
    border-radius: 12px;
    box-shadow: 0 12px 32px rgba(16, 24, 40, 0.2);
    /* Belt and braces alongside the JS clamp: even if a future caller forgets to position
       it, the device insets are still respected. */
    margin: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
            env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
    overflow: hidden;   /* the BODY scrolls, so the rounded corners stay clean */
}
.bv-inspector[hidden] { display: none; }

/* ── header = the drag handle ──────────────────────────────────────────────────
   Sticky BY CONSTRUCTION rather than by `position: sticky`: it is a non-shrinking flex child
   of a bounded column and sits OUTSIDE the scrolling body, so it cannot scroll away. The same
   construction the bottom sheet's header uses.

   `touch-action: none` is scoped to THIS element only (D3.2 §3). On the host it would kill
   scrolling in the body and break every range input inside it. */
.bv-inspector__head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 8px 8px 10px;
    border-bottom: 1px solid #eceff3;
    background: #ffffff;
    touch-action: none;
    cursor: grab;
    -webkit-user-select: none;
    user-select: none;
}
.bv-inspector__head.is-dragging { cursor: grabbing; }

/* A visible affordance that the header is the thing you drag. Purely decorative — the drag
   listener is on the header, so the target is the full 44px-tall row, not this 10px mark. */
.bv-inspector__grip {
    flex: 0 0 auto;
    width: 10px;
    height: 16px;
    border-radius: 2px;
    background-image: radial-gradient(circle, #c2c8d0 1px, transparent 1px);
    background-size: 5px 5px;
    background-position: 0 1px;
}
.bv-inspector__head.is-dragging .bv-inspector__grip {
    background-image: radial-gradient(circle, #8b939d 1px, transparent 1px);
}

/* The object-specific title (`Shape style` / `Text style` / `Line style` / `Image style`). */
.bv-inspector__title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: 'Arial', 'Helvetica', sans-serif;
    font-size: 14px;
    font-weight: 700;
    color: #1b263b;
}

/* The close control. `cursor: pointer` and its own `touch-action` deliberately override the
   header's, so it never reads as part of the drag surface; the JS also excludes every button
   in the header from starting a drag, so the two agree. */
.bv-inspector__close {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    /* A real touch target, not a 16px glyph. */
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 8px;
    color: #52606d;
    font-size: 16px;
    cursor: pointer;
    touch-action: manipulation;
}
.bv-inspector__close:hover { background: #eef1f5; }
.bv-inspector__close:focus-visible { outline: 2px solid #ff6f00; outline-offset: 2px; }

/* ── body = the ONLY scrolling region ─────────────────────────────────────────
   `overscroll-behavior: contain` stops a flick that reaches the end of this list from
   scrolling the page behind it, which on a tablet reads as the canvas jumping.

   `touch-action` is restored to the default here so the header's `none` cannot leak in and
   disable touch scrolling or drag-to-set on a range input. */
.bv-inspector__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: auto;
    padding: 10px 12px 12px;

    /* Firefox: the same thin native scrollbar as the slide navigator. */
    scrollbar-width: thin;
    scrollbar-color: rgba(16, 24, 40, 0.22) transparent;
}

/* ── THIN SCROLLBAR (Chromium/WebKit) ─────────────────────────────────────────
   The SAME treatment as the slide navigator (`slides-rightPanel.css`): 6px, transparent
   track, neutral semi-transparent fully-rounded thumb that darkens on hover or keyboard
   focus, and no arrow buttons or corner patch. Scoped to this body only, exactly as the
   navigator's is scoped to `#canvas-previews`, so no other scrolling region changes. */
.bv-inspector__body::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

.bv-inspector__body::-webkit-scrollbar-track {
    background: transparent;
}

.bv-inspector__body::-webkit-scrollbar-thumb {
    background-color: rgba(16, 24, 40, 0.18);
    border-radius: 999px;
    transition: background-color 0.16s ease;
}

.bv-inspector:hover .bv-inspector__body::-webkit-scrollbar-thumb,
.bv-inspector__body:focus-within::-webkit-scrollbar-thumb,
.bv-inspector__body:hover::-webkit-scrollbar-thumb {
    background-color: rgba(16, 24, 40, 0.3);
}

.bv-inspector__body::-webkit-scrollbar-thumb:hover {
    background-color: rgba(16, 24, 40, 0.42);
}

.bv-inspector__body::-webkit-scrollbar-button,
.bv-inspector__body::-webkit-scrollbar-corner {
    display: none;
}

/* Firefox equivalent of the hover darkening. */
.bv-inspector:hover .bv-inspector__body,
.bv-inspector__body:focus-within {
    scrollbar-color: rgba(16, 24, 40, 0.3) transparent;
}

/* ── resize handle (non-portrait only) ─────────────────────────────────────────
   Only shown in non-portrait layouts; hidden in portrait. */
.bv-inspector__resize {
    flex: 0 0 auto;
    height: 12px;
    background: #eceff3;
    border-top: 1px solid #d9dde3;
    cursor: ns-resize;
    display: flex;
    align-items: center;
    justify-content: center;
    touch-action: none;
    -webkit-user-select: none;
    user-select: none;
    transition: background-color 0.15s ease;
}

.bv-inspector__resize:hover {
    background: #d9dde3;
}

.bv-inspector__resize.is-resizing {
    background: #c2c8d0;
}

.bv-inspector__resize i {
    color: #8b939d;
    font-size: 12px;
}

.bv-inspector__resize.is-resizing i {
    color: #52606d;
}

/* Hidden in portrait, where the window is already height-budgeted against a sheet and a
   creation bar and there is no spare vertical room to hand the user.

   Keyed on a class the module writes onto the HOST, not on `[data-bv-mode]`: the host is a
   direct child of `document.body`, so `#app-studio[data-bv-mode="portrait"]` is not an ancestor
   of it and a descendant selector on that attribute matches nothing. Same constraint the
   `body.bv-presenting` / `body.datalab-open` rules at the bottom of this file work around. */
.bv-inspector--portrait .bv-inspector__resize {
    display: none;
}

/* ── the adopted control panels: ONE column, NO SECOND CARD ───────────────────
   D3.2 §4. Both `#shapeControls` and `#textTools` are authored as standalone desktop cards —
   `#textTools` carries `padding: 14px; background: #fff; border: 1px solid #e7e7e7;
   border-radius: 10px; box-shadow: 0 6px 18px rgba(0,0,0,.06); max-width: 280px` in
   `text-tools.css`, and `#shapeControls` has the equivalent panel framing. Inside an
   already-framed window that reads as a panel inside a panel, and the 280px cap leaves a dead
   strip down the right-hand side of a 360px window.

   EVERY RULE HERE IS SCOPED TO `.bv-inspector__body >`. The desktop docked presentation and
   the sheet presentation of these same nodes are untouched: the moment the node is handed back
   to `#sliderContent`, this selector stops matching and its own stylesheet applies again. */
/* The two selectors carry the SAME declarations on purpose, and the id list is not redundant:
   `text-tools.css` and `shape-container.css` author their panels through ID selectors
   (`#textTools { border: 1px solid #e7e7e7; ... }`), which at specificity (1,0,0) beat a class
   selector at (0,1,0). Without the id-scoped companion the card would survive inside the window
   and the whole §4 correction would be silently inert. `!important` would also work and is
   deliberately not used — it would leak past any future scoping and is harder to reason about
   than stating the specificity plainly. */
.bv-inspector__body > *,
.bv-inspector__body > #textTools,
.bv-inspector__body > #shapeControls,
.bv-inspector__body > #layerControls {
    width: 100%;
    max-width: none;   /* releases #textTools's 280px desktop cap */
    box-sizing: border-box;
    display: block;
    /* The window IS the card. Strip the inner one. */
    margin: 0;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

/* The window header already names the surface (`Text style`, `Shape style`, ...); a second
   heading inside the panel would repeat it. */
.bv-inspector__body > #shapeControls > h3,
.bv-inspector__body > #layerControls > h3,
.bv-inspector__body > #textTools > .textToolsHeader {
    display: none;
}

/* `#textTools` is `display: flex; flex-direction: column; gap: 12px` in its own stylesheet.
   The `display: block` above removes that gap, so the spacing is restated per row — one
   number, in one place, instead of relying on a flex context this surface does not use. */
.bv-inspector__body > #shapeControls > .section,
.bv-inspector__body > #shapeControls > #imageFiltersSection,
.bv-inspector__body > #shapeControls > #dropShadowSection,
.bv-inspector__body > #textTools > .form-group,
.bv-inspector__body > #textTools > .textPresetRow {
    margin-bottom: 12px;
}
.bv-inspector__body > #shapeControls > :last-child,
.bv-inspector__body > #textTools > :last-child {
    margin-bottom: 0;
}

/* ── finger-sized controls ────────────────────────────────────────────────────
   Presentation only. Every `input`/`change` listener — and therefore every style
   transaction these controls open and commit — is untouched. */
.bv-inspector__body .color-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.bv-inspector__body .color-swatches .swatch {
    /* Comfortable for a finger without turning the row into a wall. */
    width: 32px;
    height: 32px;
}

.bv-inspector__body input[type="range"] {
    width: 100%;
    height: 32px;
}

.bv-inspector__body select,
.bv-inspector__body input[type="number"],
.bv-inspector__body input[type="text"] {
    min-height: 40px;
    width: 100%;
    box-sizing: border-box;
}

.bv-inspector__body .button-group button,
.bv-inspector__body .input-group button,
.bv-inspector__body .presetChip,
.bv-inspector__body .width-btn,
.bv-inspector__body .stroke-style-btn,
.bv-inspector__body .stroke-cap-btn {
    min-width: 40px;
    min-height: 40px;
}

/* `.input-group` is a row of [-] [value] [+]; the blanket `width: 100%` above would otherwise
   stretch each button to the full column. */
.bv-inspector__body .input-group,
.bv-inspector__body .button-group {
    display: flex;
    gap: 8px;
    align-items: center;
}
.bv-inspector__body .input-group > button {
    width: auto;
    flex: 0 0 auto;
}

/* ── DENSITY: mouse/desktop only ──────────────────────────────────────────────
   The sizes above are TOUCH sizes — 40px inputs, 32px swatches, 12px row gaps — and they are the
   right default for a tablet. On a mouse-driven desktop the same numbers make a 280px column scroll
   for content that would otherwise fit, which is the "controls are too large" report.

   TWO THINGS MAKE THIS SAFE TO NARROW:

   1. `@media (pointer: fine)` — the query asks about the INPUT DEVICE, not the screen width. A
      tablet in landscape at 1180px reports `pointer: coarse` and keeps every touch target, so this
      cannot shrink controls under a finger. A desktop with a touchscreen reports `fine` for the
      mouse but `any-pointer: coarse` too; `pointer: fine` follows the PRIMARY pointer, which is the
      correct signal for the primary way that machine is driven.

   2. Every selector is scoped to `.bv-inspector__body >` or `.bv-inspector__body`. The same live
      `#shapeControls` / `#textTools` nodes are shared with the docked column and the portrait sheet,
      and the moment they are handed back these selectors stop matching and their own stylesheet
      applies again — so nothing is shrunk globally.

   Type sizes are deliberately NOT reduced: the complaint is about spacing, and shrinking labels
   would cost legibility for no real vertical gain. Focus rings and tab order are untouched. */
@media (pointer: fine) {
    .bv-inspector__body {
        padding: 8px 10px;
    }

    /* Card margins between sections. */
    .bv-inspector__body > #shapeControls > .section,
    .bv-inspector__body > #shapeControls > #imageFiltersSection,
    .bv-inspector__body > #shapeControls > #dropShadowSection,
    .bv-inspector__body > #textTools > .form-group,
    .bv-inspector__body > #textTools > .textPresetRow {
        margin-bottom: 8px;
    }

    /* Section padding and the label/title spacing above each control. */
    .bv-inspector__body .section {
        padding: 6px 0;
    }
    .bv-inspector__body .section-title,
    .bv-inspector__body label {
        margin-bottom: 3px;
        line-height: 1.25;
    }

    /* Row gaps. */
    .bv-inspector__body .input-group,
    .bv-inspector__body .button-group,
    .bv-inspector__body .color-swatches {
        gap: 5px;
    }

    /* Input heights: still a comfortable mouse target, 8px shorter than the touch size. */
    .bv-inspector__body select,
    .bv-inspector__body input[type="number"],
    .bv-inspector__body input[type="text"] {
        min-height: 32px;
        padding-top: 2px;
        padding-bottom: 2px;
    }

    .bv-inspector__body input[type="range"] {
        height: 24px;
    }

    /* Swatches: 32px is a fingertip; 22px is generous for a cursor. */
    .bv-inspector__body .color-swatches .swatch {
        width: 22px;
        height: 22px;
    }

    .bv-inspector__body .button-group button,
    .bv-inspector__body .input-group button,
    .bv-inspector__body .presetChip,
    .bv-inspector__body .width-btn,
    .bv-inspector__body .stroke-style-btn,
    .bv-inspector__body .stroke-cap-btn {
        min-width: 32px;
        min-height: 32px;
    }

    /* ── HORIZONTAL FIT ────────────────────────────────────────────────────────
       The window is now the slider column minus an inset, so a control that insists on a fixed
       width can force the whole row to overflow. The blanket `width: 100%` further up is right for
       a single stacked control and wrong inside an `.input-group`, where the row is
       [-] [value] [+]: the buttons are `flex: 0 0 auto`, so the VALUE is the element that should
       absorb whatever is left.

       `min-width: 0` is the load-bearing part. A flex item will not shrink below its intrinsic
       content width without it, which is how a numeric input with a wide `size` pushes its own row
       past the window edge instead of shrinking. */
    .bv-inspector__body .input-group > input[type="number"],
    .bv-inspector__body .input-group > input[type="text"],
    .bv-inspector__body .input-group > select {
        flex: 1 1 auto;
        width: auto;
        min-width: 0;
    }

    /* Rows may wrap rather than overflow — a swatch row and a decoration row both read fine on two
       lines, and neither reads at all cut off at the edge. */
    .bv-inspector__body .input-group,
    .bv-inspector__body .button-group {
        flex-wrap: wrap;
    }

    /* Nothing inside may establish a wider box than the column. */
    .bv-inspector__body > * {
        max-width: 100%;
    }
}

/* ── surfaces that OUTRANK the inspector ──────────────────────────────────────
   The inspector sits at z-index 100002 so it can overlay the asset slider (1001) and stay above
   the floating toolbar it is anchored to (99999) and that toolbar's submenus (100000). That is
   deliberately high, so the two full-screen surfaces it must never cover are suppressed by state
   rather than by z-order — the same technique `datalab.css` already uses for the floating toolbar.

   Presentation: `bv-presenting`, never the dormant `presenting` class that `additional-styles.css`
   carries unused rules for.

   DataLab: while that workspace owns the screen a canvas-editing affordance is not applicable.
   Suppression is presentational only — removing the class restores the inspector exactly, and its
   own placement/visibility logic is untouched. */
body.bv-presenting .bv-inspector { display: none !important; }

body.datalab-open .bv-inspector {
    opacity: 0 !important;
    pointer-events: none !important;
    visibility: hidden !important;
}

/* ── a colour picker OWNED BY the inspector ───────────────────────────────────
   MEASURED CAUSE, not an assumed one. With the picker open from a field inside the inspector,
   the browser reports: `parentElement` is `BODY`, `isInsideInspector` false, no intervening
   stacking-context ancestor, `overflow` clipping absent — and `z-index: 1000` against the
   inspector's 100002. So the picker is a plain SIBLING losing a z-index comparison in the root
   stacking context. It is not reparented, and it is not clipped.

   That means one step above the inspector is the entire fix, and it is applied ONLY to a picker
   the inspector owns. Coloris keeps a SINGLE `.clr-picker` node shared by every bound field in
   the document, so raising `.clr-picker` itself would relocate every colour picker in the app
   — the Draw panel's, the background swatch's, DataLab's — into the inspector band for reasons
   that have nothing to do with them. `inspectorColorPickerLayer.js` adds the marker class while
   the open field is inside `.bv-inspector` and drops it afterwards.

   `.clr-open` is part of the selector deliberately: it makes a stale marker inert, because
   Coloris removes `clr-open` on close whatever route the close took. */
.clr-picker.clr-open.bv-clr-above-inspector {
    z-index: var(--bv-layer-inspector-popover, 100003);
}

/* Suppression PARITY with the surface that owns it. Presentation and DataLab keep the inspector
   off screen by state rather than by z-order, so a popover sitting one layer above the inspector
   has to answer to the same two states — otherwise closing over the inspector would leave its
   colour picker painted on top of a full-screen surface. Scoped to the marker class, so a colour
   field belonging to DataLab's own UI is untouched. */
body.bv-presenting .clr-picker.bv-clr-above-inspector,
body.datalab-open .clr-picker.bv-clr-above-inspector {
    display: none !important;
}
