/* ==================================================================
   Components — panels, controls, menu. The brand's chrome vocabulary.
   ================================================================== */

/* ---------------- panels ---------------- */
.cs-panel {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0; min-height: 0;
    color: var(--cs-text);
    background: var(--cs-panel);
    border-radius: var(--cs-radius-lg);
    box-shadow: 0 10px 30px rgba(0,0,0,.35),
                var(--cs-chrome-seat),
                inset 0 2px 0 rgba(255,255,255,.045);
    /* Not hidden: the border art below is drawn with an outset and has
       to be free to overhang. The inner surface does the clipping. */
    overflow: visible;
}

/* The frosting lives on a leaf of its own rather than on the panel.
   On .cs-panel it would make the panel a backdrop root, and a backdrop
   root re-rasterises whenever anything inside it gains or loses a
   compositing layer — which is exactly what hovering a button does.
   Every hover would drag the panel through a repaint, and the frame is
   border-image, a bitmap that re-samples at a different scale when it
   is redrawn. On an empty leaf the filter has no descendants that can
   promote, so it has nothing to react to. */
.cs-frost {
    position: absolute; inset: 0;
    z-index: 0;
    border-radius: inherit;
    pointer-events: none;
    backdrop-filter: blur(2.5px) saturate(1.04);
    -webkit-backdrop-filter: blur(2.5px) saturate(1.04);
}

.cs-panel-inner {
    position: relative;
    z-index: 1;                      /* above .cs-frost */
    flex: 1;
    min-width: 0; min-height: 0;
    display: flex;
    flex-direction: column;
    gap: var(--cs-3);
    padding: var(--cs-4);
    border-radius: inherit;
    overflow: hidden;                /* the clipping the panel gave up */
}

/* Chrome ring. A border-box background paints across the whole box, so
   it only reads as a border while the interior above it is opaque —
   and these panels are translucent. Masking a 1px inset frame keeps the
   metal on the edge alone and leaves the interior showing the sky. */
.cs-panel::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1px;
    background: var(--cs-chrome-edge);
    -webkit-mask: linear-gradient(#000 0 0) content-box,
                  linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box,
          linear-gradient(#000 0 0);
    mask-composite: exclude;
    pointer-events: none;
    z-index: 3;
}

/* ---------------- border art ----------------
   9-slice ornament straddling the panel edge. border-width stays 0 so
   the frame costs no layout; the art is drawn at border-image-width
   and pushed back out by the outset. Slice and outset numbers are the
   visualiser's, measured against these exports — the panel-hugging
   stroke inside each slice sits at a known fraction, and the outset is
   what lands that stroke on the panel edge. Changing them by eye turns
   the ornament into a squiggle. */
.cs-panel--framed::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 4;
    border: 0 solid transparent;
    border-image-repeat: stretch;
    /* Its own layer, permanently: this is bitmap art, and a redraw is
       precisely when it can come back sampled at a different scale. */
    transform: translateZ(0);
}

.cs-panel--framed-left::after {
    border-image-source: url("../assets/panel_border_left.webp");
    border-image-slice: 165 53 221 179;
    border-image-width: 26px 10px 34px 30px;
    border-image-outset: 7px 3px 5px 7px;
}

.cs-panel--framed-right::after {
    border-image-source: url("../assets/panel_border_right.webp");
    border-image-slice: 165 179 221 53;
    border-image-width: 26px 30px 34px 10px;
    border-image-outset: 7px 6px 7px 4px;
}

/* ---------------- module heading ---------------- */
.cs-module-head {
    display: flex;
    align-items: center;
    gap: var(--cs-2);
    flex: none;
}
.cs-module-head h2 {
    margin: 0;
    font-size: 13px;
}
/* The bullet is a sprite now; sprites.css owns its box and its filter.
   Hard-coding a size here set the element to 14px while the sheet was
   still being tiled at --star-size, so every frame landed off by 1px
   and the star sheared as it turned. */
.cs-module-head .cs-rule {
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, var(--cs-chrome-shadow), transparent);
}

/* ---------------- buttons ---------------- */
.cs-button {
    position: relative;
    overflow: hidden;
    min-height: 30px;
    padding: 0 var(--cs-3);
    color: var(--cs-text);
    background: var(--cs-control);
    border: 1px solid #343b43;
    border-radius: var(--cs-radius-md);
    font-family: var(--cs-font-ui);
    font-size: 10px;
    font-weight: 650;
    letter-spacing: .06em;
    text-transform: uppercase;
    /* The landing's door is an <a> wearing this class, so that it still
       works as a link with the script gone. Without this it arrives
       underlined and the metal reads as a hyperlink. */
    text-decoration: none;
    cursor: pointer;
    box-shadow: 0 4px 8px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.08);
    transition: transform var(--cs-fast), border-color var(--cs-fast),
                background var(--cs-fast);
}
/* Metallic highlight sweep on hover — one pass, no looping. */
.cs-button::before {
    content: "";
    position: absolute; inset: 0;
    background: linear-gradient(105deg, transparent 30%,
                rgba(255,255,255,.16) 48%, rgba(221,246,255,.22) 52%, transparent 70%);
    transform: translateX(-120%);
    transition: transform 520ms ease;
    pointer-events: none;
}
.cs-button:hover::before { transform: translateX(120%); }
.cs-button:hover { border-color: var(--cs-titanium); background: var(--cs-control-hi); }
.cs-button:active { transform: translateY(1px); box-shadow: inset 0 2px 5px rgba(0,0,0,.65); }
.cs-button:focus-visible {
    outline: none;
    border-color: var(--cs-lunar);
    box-shadow: 0 0 0 1px rgba(255,255,255,.10), 0 0 12px rgba(142,220,255,.12);
}

/* The one button that commits: cosmic light on the edge. */
.cs-button--primary {
    border-color: #46596b;
    box-shadow: 0 4px 8px rgba(0,0,0,.35),
                inset 0 1px 0 rgba(255,255,255,.10),
                0 0 14px rgba(142,220,255,.10);
    color: var(--cs-ice);
}
.cs-button--primary:hover {
    border-color: var(--cs-cosmic);
    box-shadow: 0 4px 8px rgba(0,0,0,.35),
                inset 0 1px 0 rgba(255,255,255,.10),
                0 0 18px rgba(142,220,255,.22);
}

.cs-button--danger:hover { border-color: var(--tm-danger); color: #f4c3c7; }

/* ---------------- fields ---------------- */
.cs-field {
    min-height: 30px;
    padding: 0 var(--cs-2);
    color: var(--cs-text);
    background: var(--cs-void);
    border: 1px solid var(--cs-chrome-shadow);
    border-radius: var(--cs-radius-md);
    font-family: var(--cs-font-ui);
    font-size: 12px;
    box-shadow: inset 0 1px 3px rgba(0,0,0,.9), inset 0 1px 0 rgba(255,255,255,.02);
    transition: border-color var(--cs-fast), box-shadow var(--cs-fast);
    user-select: text;
}
.cs-field::placeholder { color: var(--cs-text-muted); }
.cs-field:hover { border-color: var(--cs-dark-chrome); }
.cs-field:focus {
    outline: none;
    border-color: var(--cs-titanium);
    box-shadow: inset 0 1px 3px rgba(0,0,0,.9), 0 0 12px rgba(142,220,255,.16);
}
select.cs-field {
    cursor: pointer;
    /* Chevron drawn rather than shipped, so it inherits the metal. */
    appearance: none; -webkit-appearance: none;
    padding-right: var(--cs-6);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'><path d='M1 1.5 L6 6.5 L11 1.5' fill='none' stroke='%23bbc2cb' stroke-width='1.6' stroke-linecap='round'/></svg>");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 10px;
}
select.cs-field option { background: var(--cs-obsidian); color: var(--cs-text); }

/* ---------------- context menu ---------------- */
#context-menu {
    display: none;
    position: absolute;
    z-index: 10000;
    min-width: 210px;
    padding: var(--cs-1) 0;
    background: linear-gradient(180deg, rgba(24,29,35,.97), rgba(12,15,19,.98));
    border-radius: var(--cs-radius-md);
    box-shadow: 0 14px 34px rgba(0,0,0,.7), var(--cs-chrome-seat);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    overflow: hidden;
}
/* Same masked chrome ring the panels wear, at the smaller radius. */
#context-menu::before {
    content: "";
    position: absolute; inset: 0;
    border-radius: inherit;
    padding: 1px;
    background: var(--cs-chrome-edge);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    pointer-events: none;
}

.context-menu-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--cs-2);
    padding: 9px var(--cs-3);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--cs-text-secondary);
    cursor: pointer;
    transition: background var(--cs-fast), color var(--cs-fast);
}
.context-menu-item .glyph {
    width: 13px; height: 13px;
    flex: none;
    display: grid;
    place-items: center;
    font-size: 12px;
    line-height: 1;
}
.context-menu-item .glyph img { width: 100%; height: 100%; -webkit-user-drag: none; }
.context-menu-item:hover {
    background: linear-gradient(90deg, rgba(142,220,255,.14), rgba(142,220,255,.03));
    color: var(--cs-ice);
    /* A hairline of cosmic light on the leading edge, rather than a
       filled highlight bar — the menu is chrome, not a painted list. */
    box-shadow: inset 2px 0 0 var(--cs-cosmic);
}
.context-menu-item.danger:hover {
    background: linear-gradient(90deg, rgba(226,125,134,.16), rgba(226,125,134,.03));
    color: #f4c3c7;
    box-shadow: inset 2px 0 0 var(--tm-danger);
}
.context-menu-sep {
    height: 1px;
    margin: var(--cs-1) 0;
    background: var(--cs-chrome-shadow);
}
