/* =====================================================================
   LightPane embedded pane — self-contained CSS (v1, 2026-04-23)
   =====================================================================
   Everything here is scoped under `.lp-pane`. We never touch the host
   page's globals — no `html`, `body`, `*`, or bare-element rules.
   Selectors are wrapped in `:where()` so specificity stays at (0,1,0)
   or lower; that means an embedder can override any rule with a single
   class on their own page without needing `!important`.

   Configurable via CSS custom properties. Override them in host-page
   CSS (e.g. `.my-theme .lp-pane { --lp-pane-radius: 0; }`) to re-skin
   without forking this file.
   --------------------------------------------------------------------- */

/* Token files (Phase 8 / doc 36). Imported in dependency order so
   every consumer that loads sd-embed.css gets the full chain:
     reserved   — status + chart-series tokens (theme-invariant)
     functional — spacing / type / overflow geometry (theme-invariant)
     theme      — palette + functional-name mappings (default amber;
                  switch via <html data-lp-theme="..."> + alt theme file)
   Migrated panes reference --lp-fn-* tokens which only resolve when
   the active theme file is loaded — without this import they would
   render unstyled. */
@import url("./sd-tokens-reserved.css");
@import url("./sd-tokens-functional.css");
@import url("./sd-theme-amber.css");

.lp-pane,
.lp-pane-modal {
    /* -----------------------------------------------------------------
       Tunables — override at :root or on a parent container to re-skin.
       Declared on BOTH .lp-pane and .lp-pane-modal because the policy
       viewer modal is appended to document.body (outside any .lp-pane)
       but still needs the amber palette.
       ----------------------------------------------------------------- */
    --lp-pane-font-family:
        ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
        "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --lp-pane-font-size:       14px;
    --lp-pane-line-height:     1.5;

    /* -----------------------------------------------------------------
       Brand amber palette. Carried inside the embed stylesheet so host
       pages don't need the Sunlit theme installed; the tokens are
       aliased below into the specific slots (head bg, thead bg, hover,
       etc.) so an embedder can either swap the whole palette here or
       override individual slots.
       ----------------------------------------------------------------- */
    --lp-pane-amber-900:       #3d2100;   /* deepest amber — body ink on amber bg */
    --lp-pane-amber-800:       #7a3f00;   /* deep amber — pane head fill */
    --lp-pane-amber-700:       #a5620e;   /* rich amber — accents */
    --lp-pane-amber-500:       #f5c518;   /* brand core — spinner, focus */
    --lp-pane-amber-300:       #fcd34d;   /* mid golden amber — thead fill */
    --lp-pane-amber-200:       #fde9a6;   /* pale amber */
    --lp-pane-amber-100:       #fef3c7;   /* very pale — row hover */
    --lp-pane-amber-50:        #fffbeb;   /* amber wash — detail drawer */

    --lp-pane-bg:              #ffffff;

    /* Pane head (service label strip at top). Meta ink matches the
       title so the region + source read cleanly rather than fading
       out at 72%. */
    --lp-pane-head-bg:         var(--lp-pane-amber-300);
    --lp-pane-head-ink:        var(--lp-pane-amber-900);
    --lp-pane-head-meta-ink:   var(--lp-pane-amber-900);

    /* Table header row */
    --lp-pane-thead-bg:        var(--lp-pane-amber-100);
    --lp-pane-thead-ink:       var(--lp-pane-amber-900);

    /* Row hover. The drawer wash below is deliberately MORE yellow
       than the row hover, so (i) value cells inside the drawer
       (which use the amber-50 hover wash) clearly stand out against
       the drawer wash, and (ii) the drawer itself reads as a sunken
       yellow panel rather than just more white. */
    --lp-pane-row-hover-bg:    var(--lp-pane-amber-50);
    /* Soft pale amber for the expanded-drawer band — chosen to sit
       between the value-cell white (#fffbeb) and the thead-row
       amber (#fef3c7). The earlier #fdedb0 read too heavy. */
    --lp-pane-detail-bg:       #fbf4e5;

    /* Borders — warm-tinted so they don't read as cold grey next to
       amber. --lp-pane-outer-border is deliberately stronger than
       internal dividers so a pane embedded on a similarly-toned host
       page still reads as a discrete object. */
    --lp-pane-outer-border:    #c9a05a;
    --lp-pane-border:          #e8dfc9;
    --lp-pane-divider:         #f3ebd6;

    /* Body text */
    --lp-pane-ink:             #2b2a1e;   /* warm near-black */
    --lp-pane-ink-dim:         #6b6452;   /* warm grey for meta / labels */
    --lp-pane-ink-faint:       #9c9583;   /* null dashes, chevron */

    --lp-pane-accent:          var(--lp-pane-amber-500);  /* spinner accent */
    --lp-pane-code-bg:         var(--lp-pane-amber-50);
    --lp-pane-code-ink:        #4a2a00;

    --lp-pane-err-bg:          #fffbeb;
    --lp-pane-err-border:      #fcd34d;
    --lp-pane-err-ink:         #92400e;

    --lp-pane-radius:          10px;
    --lp-pane-radius-sm:       6px;
    --lp-pane-shadow:          0 1px 2px rgba(17, 24, 39, 0.04),
                               0 1px 3px rgba(17, 24, 39, 0.02);

    --lp-pane-pad-x:           16px;
    --lp-pane-pad-y:           12px;
    --lp-pane-cell-pad-y:      10px;

    --lp-pane-gap:             4px;

    /* Label-column width inside the expander drawer (and anywhere
       else a label:value grid is used). */
    --lp-pane-stack-label-col: 120px;
}

/* Container-box layout applies only to the .lp-pane outer wrapper —
   NOT to the modal, which has its own dimensions, border, and
   positioning driven by .lp-pane-modal[open] further down. */
.lp-pane {
    box-sizing: border-box;
    font-family: var(--lp-pane-font-family);
    font-size: var(--lp-pane-font-size);
    line-height: var(--lp-pane-line-height);
    color: var(--lp-pane-ink);
    background: var(--lp-pane-bg);
    border: 1px solid var(--lp-pane-outer-border);
    border-radius: var(--lp-pane-radius);
    box-shadow: var(--lp-pane-shadow);
    overflow: hidden;
    margin-bottom: 16px;
}

/* Reset box-sizing for all descendants so host-page resets don't
   corrupt our internal layout maths. */
:where(.lp-pane) *,
:where(.lp-pane) *::before,
:where(.lp-pane) *::after {
    box-sizing: border-box;
}

/* ---------------------------------------------------------------------
   Head — service label + region/source meta row.
   --------------------------------------------------------------------- */

:where(.lp-pane-head) {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: var(--lp-pane-pad-y) var(--lp-pane-pad-x);
    background: var(--lp-pane-head-bg);
    border-bottom: 1px solid var(--lp-pane-amber-900);
}

:where(.lp-pane-head-left) {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;   /* allow the title to ellipsise */
}

:where(.lp-pane-head-right) {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

:where(.lp-pane-title) {
    font-weight: 600;
    color: var(--lp-pane-head-ink);
    letter-spacing: -0.005em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

:where(.lp-pane-meta) {
    font-size: 12px;
    color: var(--lp-pane-head-meta-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

:where(.lp-pane-meta .lp-pane-meta-sep) {
    margin: 0 6px;
    /* Separator stays slightly faded so the meta text itself — now
       full amber-900 — reads as the dominant element. */
    color: rgba(61, 33, 0, 0.45);
}

/* Provider badge — small rounded pill at the start of the pane head.
   Background + foreground colours are set inline from
   PROVIDER_BADGES in sd-embed.js so an embedder can't override one
   half and break contrast. */
:where(.lp-pane-badge) {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    border-radius: 4px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.03em;
    line-height: 1.3;
    white-space: nowrap;
    text-transform: uppercase;
    flex-shrink: 0;
}

/* Refresh button — lives in the pane head's right slot, shows a
   live countdown until the cache's fresh_until has elapsed, then
   becomes an active "Refresh" affordance. Data-state transitions
   (locked / ready / busy / denied) are driven by sd-embed.js's
   tickRefreshButton(). */
:where(.lp-pane-refresh) {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px 10px;
    border: 1px solid transparent;
    border-radius: 999px;
    font: inherit;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease,
                color 120ms ease;
    background: rgba(61, 33, 0, 0.08);
    color: var(--lp-pane-amber-900);
    border-color: rgba(61, 33, 0, 0.15);
    white-space: nowrap;
}

:where(.lp-pane-refresh[data-state="locked"]) {
    /* Countdown running — not clickable, dimmed. */
    cursor: default;
    background: transparent;
    color: rgba(61, 33, 0, 0.65);
    border-color: rgba(61, 33, 0, 0.20);
}

:where(.lp-pane-refresh[data-state="ready"]) {
    /* Cache past fresh_until — solid "Refresh" button. */
    background: var(--lp-pane-amber-900);
    color: #ffffff;
    border-color: var(--lp-pane-amber-900);
}

:where(.lp-pane-refresh[data-state="ready"]:hover) {
    background: #000000;
    border-color: #000000;
}

:where(.lp-pane-refresh[data-state="busy"]) {
    cursor: progress;
    background: rgba(61, 33, 0, 0.08);
    color: var(--lp-pane-amber-900);
    border-color: rgba(61, 33, 0, 0.25);
}

:where(.lp-pane-refresh[data-state="busy"] .lp-pane-refresh-icon) {
    animation: lp-pane-spin 0.9s linear infinite;
}

:where(.lp-pane-refresh--denied),
:where(.lp-pane-refresh[data-state="denied"]) {
    cursor: not-allowed;
    background: transparent;
    color: rgba(61, 33, 0, 0.45);
    border-color: transparent;
    font-style: italic;
}

:where(.lp-pane-refresh-icon) {
    display: block;
    flex-shrink: 0;
}

/* ---------------------------------------------------------------------
   Body — a table wrapper. Horizontal scroll is a fallback only;
   the responsive-row stack (below) is the primary narrow-screen story.
   --------------------------------------------------------------------- */

:where(.lp-pane-body) {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Resource-cap banner — emitted by sd-embed when the discovery
   response carries a resource_usage block with status ∈ {warn,
   truncated, blocked}. Sits at the top of .lp-pane-body, full
   width inside the pane. Colours are local (don't depend on the
   amber theme tokens) so they read the same across every theme. */
:where(.lp-pane-cap-banner) {
    padding: 10px 14px;
    font-size: 13px;
    line-height: 1.45;
    display: flex; align-items: flex-start; gap: 10px;
}
:where(.lp-pane-cap-banner .lp-pane-cap-icon) {
    flex: 0 0 auto;
    width: 18px; height: 18px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    font-weight: 700; font-size: 11px;
    line-height: 1;
}
:where(.lp-pane-cap-banner.warn) {
    background: #fff4d6; color: #7a4f00; border: 1px solid #f0c674;
}
:where(.lp-pane-cap-banner.warn .lp-pane-cap-icon) {
    background: #f0c674; color: #7a4f00;
}
:where(.lp-pane-cap-banner.truncated) {
    background: #ffe5cf; color: #7a3a00; border: 1px solid #f3b27a;
}
:where(.lp-pane-cap-banner.truncated .lp-pane-cap-icon) {
    background: #f3b27a; color: #7a3a00;
}
:where(.lp-pane-cap-banner.blocked) {
    background: #fde8e8; color: #6a1a1a; border: 1px solid #f0bfbf;
}
:where(.lp-pane-cap-banner.blocked .lp-pane-cap-icon) {
    background: #f0bfbf; color: #6a1a1a;
}
:where(.lp-pane-cap-banner strong) { font-weight: 600; }

:where(.lp-pane-table) {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin: 0;
}

:where(.lp-pane-table thead th) {
    font-weight: 600;
    text-align: left;
    font-size: 12px;
    letter-spacing: 0.01em;
    color: var(--lp-pane-thead-ink);
    padding: var(--lp-pane-cell-pad-y) var(--lp-pane-pad-x);
    border-bottom: 1px solid var(--lp-pane-amber-700);
    background: var(--lp-pane-thead-bg);
    white-space: nowrap;
}

:where(.lp-pane-table tbody td) {
    padding: var(--lp-pane-cell-pad-y) var(--lp-pane-pad-x);
    border-bottom: 1px solid var(--lp-pane-divider);
    vertical-align: top;
    font-size: var(--lp-pane-font-size);
    color: var(--lp-pane-ink);
    /* Permit long strings to wrap rather than force horizontal scroll. */
    overflow-wrap: anywhere;
    word-break: break-word;
}

:where(.lp-pane-table tbody tr:last-child td) {
    border-bottom: 0;
}

:where(.lp-pane-table tbody tr:hover td) {
    background: var(--lp-pane-row-hover-bg);
}

/* ---------------------------------------------------------------------
   Expandable rows — when a service has more attributes than fit as
   columns, the overflow attributes live in a hidden detail row that
   the user reveals by clicking anywhere on the primary row (or the
   chevron). Driven by the `lp-pane-row--expandable` class on the tr,
   `aria-expanded="true|false"`, and the `hidden` attribute on the
   following `.lp-pane-detail` row.
   --------------------------------------------------------------------- */

:where(.lp-pane-row--expandable) {
    cursor: pointer;
}

:where(.lp-pane-row--expandable:hover .lp-pane-expander) {
    color: var(--lp-pane-ink);
    background: var(--lp-pane-row-hover-bg);
}

:where(.lp-pane-th-expander),
:where(.lp-pane-expander-cell) {
    width: 36px;
    padding: 0 8px 0 0;
    text-align: right;
    /* Body cells default to vertical-align: top so long values start
       at the top of the row — good for data, wrong for the chevron.
       Centre the chevron on the row regardless of value height. */
    vertical-align: middle;
    white-space: nowrap;
}

:where(.lp-pane-expander) {
    appearance: none;
    background: transparent;
    border: 0;
    cursor: pointer;
    padding: 6px 8px;
    /* Brand amber instead of the neutral faint ink — a filled triangle
       in amber-700 reads clearly against every row bg (white, amber-50
       hover, amber-100 thead) without needing a decorative outline. */
    color: var(--lp-pane-amber-700);
    font: inherit;
    line-height: 0;
    border-radius: var(--lp-pane-radius-sm);
    transition: color 120ms ease, background-color 120ms ease;
}

:where(.lp-pane-expander:hover) {
    color: var(--lp-pane-amber-900);
}

:where(.lp-pane-chevron) {
    display: block;
    transition: transform 150ms ease;
    transform-origin: center;
}

:where(.lp-pane-row[aria-expanded="true"] .lp-pane-chevron) {
    transform: rotate(90deg);
}

/* Detail row — one per expandable row. `hidden` toggled by JS. */
/* Drawer wrapper: padding around the embedded detail table so it
   sits visually inside the pane rather than bleeding to the edges.
   The top is deliberately deeper than the bottom, giving the
   embedded table room to sit under the gradient shadow that
   simulates the primary row "casting shadow" into the drawer.
   Collapses to zero on narrow panes via .lp-pane-detail--tight. */
:where(.lp-pane-detail > td) {
    padding: 18px var(--lp-pane-pad-x) 14px;
    background:
        /* Top shadow — dark amber fading out over 12px to suggest
           the primary row above casting into the drawer. */
        linear-gradient(180deg,
            rgba(61, 33, 0, 0.14) 0,
            rgba(61, 33, 0, 0.04) 6px,
            transparent 14px),
        var(--lp-pane-detail-bg);
    /* Border-top matches the unexpanded inter-row divider — the
       sense of depth comes from the gradient + inset shadow below,
       NOT from a dark 1px line which reads as a hard edge rather
       than a shadow. Bottom is a heavy amber-900 line that demarks
       the end of this drawer so stacked expansions read as distinct
       rather than bleeding into each other. */
    border-top: 1px solid var(--lp-pane-divider);
    border-bottom: 2px solid var(--lp-pane-amber-900);
    /* Second inset highlight at the very bottom returns the sense of
       the drawer rising back up to the next row. */
    box-shadow:
        inset 0 4px 6px -4px rgba(61, 33, 0, 0.18),
        inset 0 -1px 0 rgba(255, 255, 255, 0.45);
}

:where(.lp-pane-detail--tight > td) {
    padding: 10px 0 6px;
}

/* The embedded detail table: a real <table> with 1px grid lines so
   each row/value pair is visually bounded. 1px amber-700 outer
   border isolates it from the surrounding drawer wash. */
:where(.lp-pane-detail-table) {
    width: 100%;
    border-collapse: collapse;
    /* 2px outer border — deliberately heavier than the 1px inner
       grid lines so the embedded detail table reads as a discrete
       object against the surrounding drawer wash. */
    border: 2px solid var(--lp-pane-amber-700);
    border-radius: var(--lp-pane-radius-sm);
    overflow: hidden;
    font-size: 13px;
    background: var(--lp-pane-bg);
}

:where(.lp-pane-detail--tight .lp-pane-detail-table) {
    /* When padding is gone, borders flush to the drawer's amber-200
       top border — drop radius + outer horizontal borders so the
       edges line up with the primary table above. */
    border-radius: 0;
    border-left: 0;
    border-right: 0;
}

:where(.lp-pane-detail-table th),
:where(.lp-pane-detail-table td) {
    padding: 7px 12px;
    text-align: left;
    vertical-align: top;
    border: 1px solid var(--lp-pane-divider);
    font-weight: normal;
}

/* Key cell — same wash as the primary thead row for consistency. */
:where(.lp-pane-detail-table th) {
    background: var(--lp-pane-thead-bg);
    color: var(--lp-pane-amber-900);
    font-weight: 500;
    font-size: 12px;
    width: 1%;              /* shrink-to-fit */
    white-space: nowrap;
    letter-spacing: 0.01em;
}

/* Value cell — same wash as row hover, so the drawer reads as an
   extension of the interactive row above. */
:where(.lp-pane-detail-table td) {
    background: var(--lp-pane-amber-50);
    color: var(--lp-pane-ink);
    overflow-wrap: anywhere;
    word-break: break-word;
}

/* Carved-depth hover — the same inset shadow recipe the pill-nav
   uses on the Sunlit site. Applied to each cell in the hovered row
   so the effect spans the full width. No layout shift. */
:where(.lp-pane-detail-table tbody tr:hover > *) {
    box-shadow: inset 0 1px 2px rgba(26, 24, 20, 0.09),
                inset 0 -1px 0 rgba(255, 255, 255, 0.6);
}

/* Padding cells used to align the final row of a wide drawer when
   overflow / tags count is odd. Both the th and td pad take the
   value-cell colour so the empty half-row is a uniform continuation
   of the table rather than a bright white slot that pulls the eye. */
:where(.lp-pane-detail-table .lp-pane-detail-pad) {
    background: var(--lp-pane-amber-50);
}

/* Shared section-head for any sub-table rendered inside the
   drawer (tags, security-group rules, route-table details, …). Sits
   across the full column span of its sub-table and provides the
   dark-amber title bar that distinguishes each section from the
   surrounding drawer wash. */
:where(.lp-pane-section-head) {
    background: var(--lp-pane-amber-700);
    color: #ffffff;
    font-weight: 600;
    font-size: 13px;
    padding: 8px 14px;
    text-align: left;
    letter-spacing: 0.02em;
    /* Override the generic detail-table th — the title bar needs to
       be solid amber edge to edge, not interrupted by the 1px
       divider border that the other ths use. */
    border: 0;
}

/* Empty-state row inside any drawer sub-table (tags or compound).
   Italic muted text on the amber-50 value-cell wash, matching the
   styling the "No policy" message uses in the modal. */
:where(.lp-pane-section-empty) {
    padding: 10px 14px;
    background: var(--lp-pane-amber-50);
    color: var(--lp-pane-ink-dim);
    font-style: italic;
    font-size: 12px;
}

/* Compound sub-tables — security-group rules, route-table details,
   network-ACL rules. Wrapped in an overflow-x container so a sub-
   table with long content (ARNs, CIDR ranges) on a narrow pane
   scrolls horizontally rather than squashing each column to
   unreadable widths. The column count itself is driven by the
   data — not a responsive 2/4-col switch like the extended-attrs
   table. */
:where(.lp-pane-compound-wrap) {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* Space between stacked drawer sub-tables. Applies uniformly to
   compound wrappers and tables, so the drawer's order
   (extended-attrs → compound sub-tables → tags) gets consistent
   14px gaps between adjacent sections without needing each
   section to know its neighbours. */
:where(.lp-pane-detail > td > *:not(:first-child)) {
    margin-top: 14px;
}

/* Null / empty value. */
:where(.lp-pane-nil) {
    color: var(--lp-pane-ink-faint);
}

/* ---------------------------------------------------------------------
   State / status pill — small coloured rectangle. Three signalling
   tones (green = ok, amber = transitional, red = bad) + a neutral
   fallback for state values we don't have tone metadata for. Used
   on columns whose id is `state`, `status`, or ends `_state` /
   `_status`. The amber tone reuses our brand palette for visual
   continuity with the rest of the pane.
   --------------------------------------------------------------------- */
:where(.lp-pane-state) {
    display: inline-flex;
    align-items: center;
    padding: 1px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.55;
    white-space: nowrap;
    border: 1px solid transparent;
    /* Force display case so mixed-case API values (EC2's "running",
       Lambda's "Active", CloudWatch's "INSUFFICIENT_DATA") all read
       consistently. Underlying DOM text stays untouched so copy/paste
       picks up the real API value. */
    text-transform: lowercase;
}

:where(.lp-pane-state--ok) {
    background: #d1fae5;
    color:      #065f46;
    border-color: #6ee7b7;
}

:where(.lp-pane-state--warn) {
    background: var(--lp-pane-amber-200);
    color:      var(--lp-pane-amber-900);
    border-color: var(--lp-pane-amber-700);
}

:where(.lp-pane-state--bad) {
    background: #fee2e2;
    color:      #991b1b;
    border-color: #fca5a5;
}

:where(.lp-pane-state--neutral) {
    background: #f1f5f9;
    color:      #475569;
    border-color: #cbd5e1;
}

/* ---------------------------------------------------------------------
   Policy link — cells in columns with format: 'policy_link' render
   as an inline link-styled button. Click pops up the shared
   native <dialog> (defined below) which fetches the policy
   document on demand via action=get_policy.
   --------------------------------------------------------------------- */
:where(.lp-pane-policy-link) {
    appearance: none;
    background: transparent;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    font: inherit;
    color: var(--lp-pane-amber-900);
    text-decoration: underline;
    text-decoration-color: rgba(61, 33, 0, 0.35);
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    transition: text-decoration-color 120ms ease;
}

:where(.lp-pane-policy-link:hover) {
    text-decoration-color: currentColor;
}

/* ---------------------------------------------------------------------
   Policy viewer modal — shared native <dialog> appended to
   document.body. Native element gives us the browser's top-layer +
   ESC close + focus trap for free. Backdrop styled via ::backdrop.
   --------------------------------------------------------------------- */
.lp-pane-modal[open] {
    max-width: min(800px, 92vw);
    max-height: 82vh;
    width: min(800px, 92vw);
    padding: 0;
    border: 1px solid var(--lp-pane-outer-border);
    border-radius: var(--lp-pane-radius);
    box-shadow: 0 16px 48px rgba(17, 24, 39, 0.35),
                0 4px 12px rgba(17, 24, 39, 0.25);
    overflow: hidden;
    font-family: var(--lp-pane-font-family);
    font-size: var(--lp-pane-font-size);
    color: var(--lp-pane-ink);
    /* Fully opaque fallback colour before the body paints — browsers
       can briefly render the native dialog default (sometimes
       white-ish but not always, and on dark host pages that can
       flicker) before our descendant .lp-pane-modal-body takes
       over. */
    background: #ffffff;
    /* Structure the dialog as a column of head + body so the body
       is what scrolls while the head stays pinned. */
    display: flex;
    flex-direction: column;
}

/* Backdrop — a dark warm amber at ~50% so the host page recedes
   without being completely hidden. Keeping it slightly see-through
   keeps the modal feeling anchored to the page it opened from. */
.lp-pane-modal::backdrop {
    background: rgba(61, 33, 0, 0.5);
}

.lp-pane-modal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 14px 10px 16px;
    background: var(--lp-pane-head-bg);
    color: var(--lp-pane-head-ink);
    border-bottom: 1px solid var(--lp-pane-amber-900);
    flex-shrink: 0;
}

.lp-pane-modal-title {
    font-weight: 600;
    font-size: 14px;
    color: var(--lp-pane-head-ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.lp-pane-modal-close {
    appearance: none;
    /* Fixed-size square with flex centring around the SVG icon.
       Using an SVG × (two crossed lines in a viewBox) rather than
       the U+00D7 glyph — character metrics put the glyph below
       line centre in most fonts, so a glyph-based × visually
       sits on the baseline even with flex alignment. SVG has a
       true geometric centre. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--lp-pane-head-ink);
    line-height: 0;
    cursor: pointer;
    border-radius: 4px;
    transition: background-color 120ms ease;
    flex-shrink: 0;
}

.lp-pane-modal-close:hover {
    background: rgba(61, 33, 0, 0.15);
}

.lp-pane-modal-body {
    flex: 1;
    overflow: auto;
    padding: 16px;
    background: var(--lp-pane-bg);
}

.lp-pane-policy-doc {
    margin: 0;
    font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo,
                 Consolas, Liberation Mono, monospace;
    font-size: 12px;
    line-height: 1.55;
    background: var(--lp-pane-detail-bg);
    color: var(--lp-pane-amber-900);
    padding: 14px 16px;
    border-radius: var(--lp-pane-radius-sm);
    border: 1px solid var(--lp-pane-border);
    white-space: pre-wrap;
    word-break: break-word;
}

.lp-pane-modal-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 40px 20px;
    color: var(--lp-pane-ink-dim);
    font-size: 13px;
}

.lp-pane-modal-error {
    padding: 14px 16px;
    border-radius: var(--lp-pane-radius-sm);
    background: #fee2e2;
    color: #991b1b;
    border: 1px solid #fca5a5;
    font-size: 13px;
}

.lp-pane-modal-message {
    padding: 20px;
    text-align: center;
    color: var(--lp-pane-ink-dim);
    font-size: 13px;
    font-style: italic;
}

/* Small-viewport behaviour: take the full width with a small
   margin so narrow screens get usable space rather than a
   cramped dialog. */
@media (max-width: 520px) {
    .lp-pane-modal[open] {
        max-width: calc(100vw - 16px);
        width: calc(100vw - 16px);
        max-height: calc(100vh - 32px);
    }
    .lp-pane-modal-head { padding: 8px 8px 8px 12px; }
    .lp-pane-modal-body { padding: 12px; }
}

/* Object / array value rendered as mono code. */
:where(.lp-pane-code) {
    font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo,
                 Consolas, Liberation Mono, monospace;
    font-size: 12px;
    background: var(--lp-pane-code-bg);
    color: var(--lp-pane-code-ink);
    padding: 1px 6px;
    border-radius: var(--lp-pane-radius-sm);
}

/* ---------------------------------------------------------------------
   Empty / loading / error states.
   --------------------------------------------------------------------- */

:where(.lp-pane-empty) {
    padding: var(--lp-pane-pad-y) var(--lp-pane-pad-x);
    color: var(--lp-pane-ink-dim);
    font-size: 13px;
}

/* "Feature not enabled" / soft-error variant — server provides a
   contextual note via metadata.empty_state_note (e.g. Shield Standard
   active, RIs not subscribed). Amber-dashed treatment matches the
   bespoke panes' equivalent empty states (compute-optimizer, rightsize,
   ri-savings, free-tier). */
:where(.lp-pane-empty--note) {
    margin: var(--lp-pane-pad-y) var(--lp-pane-pad-x);
    padding: 16px;
    background: var(--lp-pane-amber-50, #fff8eb);
    border: 1px dashed var(--lp-pane-amber-300, #f5cf86);
    border-radius: 6px;
    color: var(--lp-pane-ink, #1f2937);
    line-height: 1.55;
}

:where(.lp-pane--loading .lp-pane-head) {
    border-bottom: 0;
}

:where(.lp-pane-loading-row) {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: var(--lp-pane-pad-y) var(--lp-pane-pad-x);
    color: var(--lp-pane-ink-dim);
    font-size: 13px;
}

:where(.lp-pane-spinner) {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid var(--lp-pane-border);
    border-top-color: var(--lp-pane-accent);
    animation: lp-pane-spin 0.8s linear infinite;
    flex-shrink: 0;
}

@keyframes lp-pane-spin {
    to { transform: rotate(360deg); }
}

:where(.lp-pane--error) {
    background: var(--lp-pane-err-bg);
    border-color: var(--lp-pane-err-border);
    box-shadow: none;
}

:where(.lp-pane--error .lp-pane-head) {
    background: transparent;
    border-bottom: 0;
}

:where(.lp-pane--error .lp-pane-title) {
    color: var(--lp-pane-err-ink);
}

:where(.lp-pane-error-body) {
    padding: 0 var(--lp-pane-pad-x) var(--lp-pane-pad-y);
    font-size: 13px;
    color: var(--lp-pane-err-ink);
}

/* Respect reduced motion. */
@media (prefers-reduced-motion: reduce) {
    :where(.lp-pane-spinner) {
        animation-duration: 2.4s;
    }
}

/* Narrow-container behaviour is handled by sd-embed.js's
   ResizeObserver-driven primary-column count: on tight panes we show
   1 or 2 primary columns and move the rest into the expander drawer.
   No viewport-based @media rule is needed — which means host-page
   layout changes (e.g. a sidebar opening and halving the pane width)
   still drive a clean re-render rather than a visual-only reflow. */
