/* page.css -- the desktop kit for app pages: the dashboards and tools that open in desktop windows (Jay, 2026-10-24:
   "I DO want all pages served by Voice to use the same L&F. This is important architecturally"). A page links, in order:
     <link rel="stylesheet" href="/ui/glass.css">   tokens, appearance, the glass, macOS scroll bars, the framed mode
     <link rel="stylesheet" href="/ui/page.css">    this file: the page's paper, native controls, panels, cards
     <script src="/ui/glass.js"></script>           the appearance from System Settings, and the framed check
   Its own CSS then keeps only its layout and its drawing, coloured with the kit's tokens (--lg-text, --lg-text-2,
   --lg-text-3, --lg-accent, --lg-control, --pg-*), never a hard-coded paper or ink.
   - Framed in a desktop window the page is clear, and the window's frosted glass is its paper. On its own it sits on
     the desktop's wallpaper under one pane of frosted glass.
   - Native controls (buttons, selects, text and number fields, checkboxes, radios, sliders) take the kit's look with
     no classes.
   - .lg-panel is a glass pane for a group of controls. .lg-cards / .lg-card is the dashboard tile, after the homelab
     dashboards Jay picked (2026-10-24): a glass tile with a hairline rim, an icon, a title and a muted subtitle, a
     status dot, small stat boxes and thin bars. .lg-section is a section heading. */

/* EVERYTHING HERE IS IN ONE CASCADE LAYER, "page" (2026-10-24). Rules outside any layer beat layered ones whatever
   their specificity, so glass.css's own components (the menu bar, the Dock, the traffic lights, sidebar items,
   capsules) and each page's own CSS always win, and this file only fills in what they leave alone. Without it the
   bare button/select/body rules re-skinned the desktop chrome on pages that draw their own desktop (Corpus, found by
   the small-pages agent). */
@layer page {


/* ---- tokens: dark is glass.css's default appearance; the light ones follow ---- */
:root {
  --pg-card: rgba(30, 32, 38, .52);
  --pg-card-hover: rgba(46, 48, 56, .62);
  --pg-card-lift: rgba(38, 40, 46, .95);        /* a tile lifted over its neighbours: near opaque, so they don't read through */
  --pg-rim: rgba(255, 255, 255, .10);
  --pg-card-shadow: inset 0 0 0 .5px rgba(255, 255, 255, .09), inset 0 1px 0 rgba(255, 255, 255, .06), 0 8px 24px rgba(0, 0, 0, .22);
  --pg-card-shadow-hover: inset 0 0 0 .5px rgba(255, 255, 255, .16), inset 0 1px 0 rgba(255, 255, 255, .08), 0 12px 28px rgba(0, 0, 0, .28);
  --pg-inset: rgba(255, 255, 255, .05);
  --pg-track: rgba(255, 255, 255, .12);
  --pg-line: rgba(255, 255, 255, .10);
  --pg-ok: #34d399;
  --pg-warn: #fbbf24;
  --pg-bad: #f87171;
  --pg-option: #1f2126;
  --pg-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%23c7ccd4' d='M0 0l5 6 5-6z'/%3E%3C/svg%3E");
}
:root[data-theme="light"] {
  --pg-card: rgba(255, 255, 255, .58);
  --pg-card-hover: rgba(255, 255, 255, .76);
  --pg-card-lift: rgba(250, 250, 252, .95);
  --pg-rim: rgba(0, 0, 0, .09);
  --pg-card-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .06), inset 0 1px 0 rgba(255, 255, 255, .75), 0 6px 18px rgba(0, 0, 0, .07);
  --pg-card-shadow-hover: inset 0 0 0 .5px rgba(0, 0, 0, .09), inset 0 1px 0 rgba(255, 255, 255, .85), 0 10px 24px rgba(0, 0, 0, .10);
  --pg-inset: rgba(0, 0, 0, .04);
  --pg-track: rgba(0, 0, 0, .10);
  --pg-line: rgba(0, 0, 0, .08);
  --pg-ok: #10b981;
  --pg-warn: #d97706;
  --pg-bad: #dc2626;
  --pg-option: #fff;
  --pg-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%235b6573' d='M0 0l5 6 5-6z'/%3E%3C/svg%3E");
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --pg-card: rgba(255, 255, 255, .58);
    --pg-card-hover: rgba(255, 255, 255, .76);
    --pg-card-lift: rgba(250, 250, 252, .95);
    --pg-rim: rgba(0, 0, 0, .09);
    --pg-card-shadow: inset 0 0 0 .5px rgba(0, 0, 0, .06), inset 0 1px 0 rgba(255, 255, 255, .75), 0 6px 18px rgba(0, 0, 0, .07);
    --pg-card-shadow-hover: inset 0 0 0 .5px rgba(0, 0, 0, .09), inset 0 1px 0 rgba(255, 255, 255, .85), 0 10px 24px rgba(0, 0, 0, .10);
    --pg-inset: rgba(0, 0, 0, .04);
    --pg-track: rgba(0, 0, 0, .10);
    --pg-line: rgba(0, 0, 0, .08);
    --pg-ok: #10b981;
    --pg-warn: #d97706;
    --pg-bad: #dc2626;
    --pg-option: #fff;
    --pg-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='%235b6573' d='M0 0l5 6 5-6z'/%3E%3C/svg%3E");
  }
}

/* ---- the page's paper ---- */
/* The wallpaper is html's, the whole canvas, and the frosted pane is body's ::before over it. With the wallpaper on body
   (glass.css gives html a colour, so body kept its own) a page opened on its own showed it sharp, the pane painting
   beneath it, and a short page's wallpaper stopped at the page's end. Found by two of the restyle agents, 2026-10-24.
   Framed, glass.css clears html and body both. */
html { background: #1f3346 url("/ui/wallpaper.jpg") center / cover fixed; }
body:not(.lg-desktop) { isolation: isolate; font: 13px/1.45 var(--lg-font); color: var(--lg-text); -webkit-font-smoothing: antialiased; }
/* (not on a page that draws its own desktop, body.lg-desktop: its windows are the glass there) */
body:not(.lg-desktop)::before { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; background: var(--lg-window-tint);
               -webkit-backdrop-filter: blur(40px) saturate(170%); backdrop-filter: blur(40px) saturate(170%); }
.lg-embedded body::before { display: none; }

/* ---- native controls: on app pages only. A page that draws its own desktop (body.lg-desktop) styles its controls as
   kit components, and these bare rules would leak whatever those leave unset (a rim, a hover tint, the line height). */
body:not(.lg-desktop) {
  button, select, input, textarea { font: inherit; }
  button, select, textarea,
  input:is([type="text"], [type="number"], [type="search"], [type="email"], [type="url"], [type="password"], [type="time"], [type="date"], :not([type])) {
    border: 0; border-radius: 7px; color: var(--lg-text); background-color: var(--lg-control);
    box-shadow: inset 0 0 0 .5px var(--pg-rim), 0 .5px 1.5px rgba(0, 0, 0, .10);
  }
  button { padding: 4px 11px; font-weight: 500; cursor: default; }
  button:hover:not(:disabled) { background-color: var(--lg-selected); }
  button:active:not(:disabled) { filter: brightness(.94); }
  button:disabled { opacity: .45; }
  select { padding: 3px 26px 3px 9px; -webkit-appearance: none; appearance: none; cursor: default;
           background-image: var(--pg-chevron); background-repeat: no-repeat; background-position: right 9px center; }
  select option { background: var(--pg-option); color: var(--lg-text); }
  textarea, input:is([type="text"], [type="number"], [type="search"], [type="email"], [type="url"], [type="password"], [type="time"], [type="date"], :not([type])) { padding: 3px 8px; }
  :is(button, select, input, textarea):focus-visible { outline: 2px solid var(--lg-accent); outline-offset: 1px; }
  input[type="checkbox"], input[type="radio"], input[type="range"], progress, meter { accent-color: var(--lg-accent); }
  hr { border: 0; border-top: .5px solid var(--pg-line); }
}

/* ---- a glass pane for a group of controls (a sidebar, an inspector, a toolbar) ---- */
.lg-panel { border-radius: 14px; background: var(--pg-card); box-shadow: var(--pg-card-shadow);
            -webkit-backdrop-filter: blur(20px) saturate(160%); backdrop-filter: blur(20px) saturate(160%); }

/* ---- the dashboard tile ---- */
.lg-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.lg-card { position: relative; display: flex; align-items: center; gap: 11px; min-width: 0; padding: 11px 14px; border-radius: 14px;
           color: var(--lg-text); text-decoration: none; background: var(--pg-card); box-shadow: var(--pg-card-shadow);
           transition: background .15s, box-shadow .15s, transform .15s; }
a.lg-card:hover, button.lg-card:hover, .lg-card.is-clickable:hover { background: var(--pg-card-hover); box-shadow: var(--pg-card-shadow-hover); transform: translateY(-1px); }
.lg-card-icon { flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 9px; background: var(--pg-inset); }
.lg-card-icon svg, .lg-card-icon img { width: 22px; height: 22px; }
.lg-card-icon.is-app { background: none; }                    /* an app's own squircle icon, at full size */
.lg-card-icon.is-app svg { width: 34px; height: 34px; }
.lg-card-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.lg-card-title { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lg-card-sub { font-size: 11.5px; color: var(--lg-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lg-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; --dot: var(--pg-ok); background: var(--dot);
          box-shadow: 0 0 0 2px color-mix(in srgb, var(--dot) 22%, transparent), 0 0 8px color-mix(in srgb, var(--dot) 70%, transparent); }
.lg-dot.is-warn { --dot: var(--pg-warn); }
.lg-dot.is-bad { --dot: var(--pg-bad); }
.lg-dot.is-off { --dot: var(--lg-text-3); box-shadow: none; }
.lg-card > .lg-dot { position: absolute; top: 11px; right: 11px; }
.lg-stats { display: grid; grid-auto-columns: 1fr; grid-auto-flow: column; gap: 6px; }
.lg-stat { padding: 5px 8px; border-radius: 8px; background: var(--pg-inset); text-align: center; }
.lg-stat b { display: block; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.lg-stat small { display: block; font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--lg-text-3); }
.lg-bar { height: 4px; border-radius: 2px; overflow: hidden; background: var(--pg-track); }
.lg-bar > i { display: block; height: 100%; border-radius: inherit; background: var(--lg-accent); }
.lg-section { display: flex; align-items: center; gap: 7px; margin: 18px 4px 9px; font-size: 13px; font-weight: 700; color: var(--lg-text); }
.lg-section svg { width: 15px; height: 15px; opacity: .7; }
.lg-muted { color: var(--lg-text-2); }
.lg-mono { font-family: "SF Mono", "Cascadia Code", Consolas, monospace; font-variant-numeric: tabular-nums; }

/* status colours that are safe as text on light glass too (the --pg-ok/warn/bad dots are too pale for type there) */
:root { --pg-ok-ink: color-mix(in srgb, var(--pg-ok) 70%, var(--lg-text)); --pg-warn-ink: color-mix(in srgb, var(--pg-warn) 70%, var(--lg-text));
        --pg-bad-ink: color-mix(in srgb, var(--pg-bad) 70%, var(--lg-text)); }

/* ---- the dashboard tile (/ui/tile.js; Jay, 2026-10-24: one shape, size and behaviour for every project) ----------------
   An image of the tile's own thing on the left, what it is beside it. Hover magnifies the tile in its own spot and the
   image comes alive; nothing floats out of it.
   THE OPACITY SLIDER, SELECTIVELY (Jay, 2026-10-24: "the background of the image scales with slider, background of tile
   also scales with slider. But foreground either stays opaque or only scales slightly"): the tile's glass, its image's
   ground, its chips' ground and its shadow run from nearly clear at 0 to nearly solid at 100 (--lg-op, the window's own
   slider, relayed into framed pages by sim.js); the words, the dot and what the image draws stay as they are. */
/* THE PICTURE FLOATS (Jay, 2026-10-25: "I want the graphical part of each tile to appear as if it's floating in mid-air,
   so while the background of the whole tile contrasts with the panel that contains it, the background of the graphical
   part is clear, WITHOUT BLURRING WHAT'S BEHIND IT"). The tile's glass is a layer of its own (the sheet's ::before) with a
   hole cut where the picture sits: there the panel behind the tile shows exactly as it does around the tile, untinted and
   unblurred, so the picture stands on nothing. The square has no wash and no rim any more (from 10-25 it went from clear
   to frosted with the slider); the slider still sets how far the tile around it stands out. NO BACKDROP BLUR anywhere
   here: in a framed page Chrome paints the backdrop it captures over that same glass again (measured 10-25, headless Edge). */
.lg-tile { --tile-rgb: 30 32 38; --tile-hover-rgb: 44 46 54; --chip-rgb: 255 255 255;
           --tile-a: calc(.95 * var(--lg-op, .3)); --chip-a: calc(.02 + .12 * var(--lg-op, .3));
           --tile-shadow: 0 8px 24px rgb(0 0 0 / calc(.26 * var(--lg-op, .3))); }
:root[data-theme="light"] .lg-tile { --tile-rgb: 255 255 255; --tile-hover-rgb: 255 255 255; --chip-rgb: 0 0 0;
           --chip-a: calc(.02 + .05 * var(--lg-op, .3));
           --tile-shadow: 0 6px 18px rgb(0 0 0 / calc(.1 * var(--lg-op, .3))); }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .lg-tile { --tile-rgb: 255 255 255; --tile-hover-rgb: 255 255 255; --chip-rgb: 0 0 0;
           --chip-a: calc(.02 + .05 * var(--lg-op, .3));
           --tile-shadow: 0 6px 18px rgb(0 0 0 / calc(.1 * var(--lg-op, .3))); }
}
/* THE TILE'S GLASS IS THE SIDEBAR'S, AT EVERY SETTING (Jay, 2026-10-24: "Anything that's a 'tile' will look better if it
   looks like the frosted glass of the left panel ... the same look and opacity of the left panel"): glass.css's frost,
   the sidebar's tint and rims, over the window's own glass, which is what the slider moves. No frost of its own and no
   shadow at rest, as the sidebar has none; a magnified tile lifts with a shadow. */
.lg-tile { --tile-bg: var(--lg-frost); --tile-bg-hover: var(--lg-frost-hover); --tile-rims: var(--lg-frost-rims); --tile-shadow: 0 0 transparent; }
.lg-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--tile-w, 316px), 1fr)); grid-auto-rows: var(--tile-h, 132px); gap: 12px; }
.lg-tile { position: relative; min-width: 0; height: var(--tile-h, 132px); color: var(--lg-text); outline: none; cursor: default; }
.lg-tile-sheet { position: absolute; inset: 0; z-index: 1; display: flex; gap: 12px; box-sizing: border-box; padding: 12px; overflow: hidden;
                 border-radius: 14px; box-shadow: var(--tile-shadow);
                 transition: transform .22s cubic-bezier(.2, .9, .3, 1.15), box-shadow .2s; }
/* the tile's glass, behind its content, cut through at the picture: the square's own box (12 px in, tile height less 24) */
.lg-tile-sheet::before { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
                         background: var(--tile-bg); box-shadow: var(--tile-rims); transition: background .2s;
                         --hole: calc(var(--tile-h, 132px) - 24px);
                         -webkit-mask: linear-gradient(#000 0 0), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='9.3'/%3E%3C/svg%3E") 12px 12px / var(--hole) var(--hole) no-repeat;
                         -webkit-mask-composite: xor;
                         mask: linear-gradient(#000 0 0), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' rx='9.3'/%3E%3C/svg%3E") 12px 12px / var(--hole) var(--hole) no-repeat;
                         mask-composite: exclude; }
.lg-tile-sheet.has-accent::before { box-shadow: inset 3px 0 0 var(--tile-accent), var(--tile-rims); }
.lg-tile:hover .lg-tile-sheet::before { background: var(--tile-bg-hover); }
.lg-tile.is-mag { z-index: 5; --tile-shadow: 0 22px 50px rgb(0 0 0 / calc(.08 + .2 * var(--lg-op, .3))), 0 6px 14px rgb(0 0 0 / calc(.04 + .08 * var(--lg-op, .3))); }
.lg-tile.is-mag .lg-tile-sheet { transform: scale(1.07); }
.lg-tile.is-mag .lg-tile-sheet::before { background: var(--tile-bg-hover); }
.lg-tile:focus-visible .lg-tile-sheet { outline: 2px solid var(--lg-accent); outline-offset: 2px; }
.lg-tile-img { position: relative; flex: none; width: calc(var(--tile-h, 132px) - 24px); height: 100%; overflow: hidden; border-radius: 10px; }
.lg-tile-img.pv-dark { background: rgb(0 0 0 / var(--lg-op, .3)); }    /* the rain's own black, thinned by the slider */
.lg-tile-img.is-live > :not(.lg-tile-live) { visibility: hidden; }     /* the live image replaces the still, never over it */
.lg-tile-img.is-icon { display: grid; place-items: center; }
.lg-tile-img.is-icon .lg-card-icon { width: 54px; height: 54px; border-radius: 14px; }
.lg-tile-img.is-icon .lg-card-icon svg { width: 30px; height: 30px; }
.lg-tile-live { position: absolute; inset: 0; }
.lg-tile-img .pv-tag, .lg-tile-img .pv-cap { display: none; }        /* the tile's own text says what the image is */
.lg-tile-img .pv-note { font-size: 10.5px; padding: 6px; text-align: center; }
.lg-tile-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px;
                text-shadow: 0 1px 4px rgb(0 0 0 / calc(.65 * (1 - var(--lg-op, .3)))); }   /* clear glass on a bright sky: the words keep an edge */
:root[data-theme="light"] .lg-tile-body { text-shadow: 0 1px 2px rgb(255 255 255 / calc(.6 * (1 - var(--lg-op, .3)))); }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .lg-tile-body { text-shadow: 0 1px 2px rgb(255 255 255 / calc(.6 * (1 - var(--lg-op, .3)))); } }
.lg-tile-id { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.lg-tile-names { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.lg-tile-title { font-size: 13px; font-weight: 600; color: inherit; text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
a.lg-tile-title:hover { text-decoration: underline; }
.lg-tile-context { font: 11px/1.3 "SF Mono", "Cascadia Code", Consolas, monospace; color: var(--lg-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lg-tile .lg-dot { flex: none; margin-top: 4px; }
.lg-tile-link { flex: none; padding: 1px 8px; border-radius: 999px; font-size: 10.5px; line-height: 16px; font-weight: 600; color: var(--lg-text-2);
                text-decoration: none; background: var(--lg-frost); box-shadow: var(--lg-frost-rims); }
.lg-tile-link:hover { color: var(--lg-text); background: var(--lg-frost-hover); }
button.lg-tile-link { border: 0; font-family: inherit; cursor: default; }   /* a link that runs something (tile.js links[].run) */
.lg-tile-chip + .lg-tile-link, .lg-tile-chips > .lg-tile-link:first-child { margin-left: auto; }
.lg-tile:not(.is-mag):not(:focus-within) .lg-tile-link { display: none; }   /* the links come up with the magnified tile; at rest the chips read whole */
.lg-tile-x { flex: none; width: 18px; height: 18px; padding: 0; border: 0; border-radius: 50%; font-size: 11px; line-height: 18px; text-align: center;
             color: var(--lg-text-3); background: var(--pg-inset); cursor: default; }
.lg-tile-x:hover { color: var(--lg-text); background: var(--lg-selected); }
.lg-tile-x.is-on, .lg-tile-x.is-on:hover { color: #fff; background: var(--pg-bad); }
.lg-tile-head { display: flex; align-items: baseline; gap: 6px; min-height: 24px; line-height: 1; }
.lg-tile-head b { font-size: 24px; font-weight: 700; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.lg-tile-head small { font-size: 12px; color: var(--lg-text-2); }
.lg-tile-summary { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; font-size: 12px; line-height: 1.38; color: var(--lg-text-2); }
.lg-tile-signal { display: flex; align-items: center; gap: 8px; min-width: 0; height: 18px; }
.lg-tile-signal svg { flex: 1; min-width: 0; height: 100%; overflow: visible; }
.lg-tile-legend { flex: none; display: flex; gap: 8px; max-width: 55%; overflow: hidden; font-size: 10.5px; color: var(--lg-text-2); white-space: nowrap; }
.lg-tile-legend i { display: inline-block; width: 7px; height: 7px; margin-right: 3px; border-radius: 2px; background: var(--c); }
.lg-tile-note { font-size: 11px; line-height: 17px; color: var(--lg-text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lg-tile-note:empty { display: none; }
.lg-tile-note:not(:empty) + .lg-tile-chips { display: none; }      /* a page's note stands in for the chips while it has text */
.lg-tile-chips { display: flex; gap: 5px; min-height: 17px; margin-top: auto; overflow: hidden; }
.lg-tile-chip { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; padding: 1px 7px; border-radius: 999px; font-size: 10.5px; line-height: 15px; color: var(--lg-text-2); background: rgb(var(--chip-rgb) / var(--chip-a)); white-space: nowrap; }
}
