:root {
    --os-accent: #0078d4;
    --os-accent-soft: rgba(0, 120, 212, 0.18);
    --os-bg-grad-1: #0a3a6b;
    --os-bg-grad-2: #1d6fb8;
    --os-bg-grad-3: #6ab1e8;
    --os-fg: #f3f3f3;
    --os-fg-muted: rgba(243, 243, 243, 0.72);
    --os-surface: rgba(32, 32, 32, 0.72);
    --os-surface-border: rgba(255, 255, 255, 0.10);
    --os-radius: 8px;
    --os-radius-sm: 4px;
    --os-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
    --os-tb-height: 48px;
    --os-font: "Segoe UI Variable", "Segoe UI", Inter, system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
}

[data-theme="light"] {
    --os-bg-grad-1: #cfe5fb;
    --os-bg-grad-2: #f3f8ff;
    --os-bg-grad-3: #ffffff;
    --os-fg: #1b1b1b;
    --os-fg-muted: rgba(27, 27, 27, 0.65);
    --os-surface: rgba(255, 255, 255, 0.78);
    --os-surface-border: rgba(0, 0, 0, 0.08);
    --os-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    overflow: hidden;
    font-family: var(--os-font);
    color: var(--os-fg);
    -webkit-font-smoothing: antialiased;
}

body.os-shell {
    background:
        radial-gradient(1200px 800px at 20% 20%, var(--os-bg-grad-3), transparent 60%),
        radial-gradient(1000px 700px at 80% 70%, var(--os-bg-grad-2), transparent 65%),
        linear-gradient(135deg, var(--os-bg-grad-1), var(--os-bg-grad-2));
    background-size: cover;
    background-attachment: fixed;
}

.os-desktop {
    position: fixed;
    inset: 0 0 var(--os-tb-height) 0;
    display: block;
}

.os-taskbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--os-tb-height);
    display: flex;
    justify-content: center;
    align-items: stretch;
    padding: 0;
    z-index: 10;
}

.os-taskbar-inner {
    width: 100%;
    height: 100%;
    display: grid;
    /* Four columns: left spacer | Start | Pins | tray-side spacer. Tray is
       absolutely-positioned on the right (see below) so the centre cluster
       stays balanced regardless of the tray's width. */
    grid-template-columns: 1fr auto auto 1fr;
    grid-template-rows: 1fr;
    align-items: center;
    padding: 0 12px;
    background: var(--os-surface);
    border-top: 1px solid var(--os-surface-border);
    backdrop-filter: blur(28px) saturate(160%);
    -webkit-backdrop-filter: blur(28px) saturate(160%);
    position: relative;
    overflow: hidden;
}

.os-tb-pins {
    display: flex;
    align-items: center;
    gap: 4px;
    grid-column: 3;
    grid-row: 1;
}

.os-tb-tray {
    /* Pin to the right edge — no grid cell needed; keeps the centre cluster centred. */
    position: absolute;
    right: 12px;
    top: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    color: var(--os-fg);
    font-size: 12px;
    line-height: 1.1;
}

.os-tb-btn {
    appearance: none;
    background: transparent;
    border: 0;
    width: 40px;
    height: 40px;
    border-radius: var(--os-radius-sm);
    color: var(--os-fg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 120ms ease;
}

.os-tb-btn:hover { background: rgba(255, 255, 255, 0.08); }
.os-tb-btn:focus-visible { outline: 2px solid var(--os-accent); outline-offset: 2px; }

.os-start-btn {
    grid-column: 2; grid-row: 1;
    width: calc(var(--os-tb-height) - 4px);   /* 44 px in the 48 px bar */
    height: calc(var(--os-tb-height) - 4px);
    padding: 0;
}
.os-start-btn .os-start-glyph {
    width: calc(var(--os-tb-height) - 8px);   /* 40 px glyph — almost edge-to-edge */
    height: calc(var(--os-tb-height) - 8px);
    display: block;
}
/* Polish: brighten slightly on hover, press on click. */
.os-start-btn:hover .os-start-glyph { filter: brightness(1.08); }
.os-start-btn:active .os-start-glyph { filter: brightness(0.92); transform: translateY(0.5px); }

.os-tray-clock {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--os-fg);
    user-select: none;
}

.os-tray-clock .os-clock-time { display: block; font-size: 12px; }
.os-tray-clock .os-clock-date { display: block; font-size: 11px; color: var(--os-fg-muted); }

.os-tray-btn,
.os-tray-clock-btn {
    appearance: none;
    background: transparent;
    border: 0;
    height: 36px;
    padding: 0 8px;
    border-radius: var(--os-radius-sm);
    color: var(--os-fg);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 100ms ease;
    position: relative;
}
.os-tray-btn:hover,
.os-tray-clock-btn:hover { background: rgba(255, 255, 255, 0.08); }
.os-tray-btn:focus-visible,
.os-tray-clock-btn:focus-visible { outline: 2px solid var(--os-accent); outline-offset: 1px; }

.os-temp-pill {
    font-size: 11px;
    padding: 2px 8px;
    border-radius: 10px;
    background: rgba(255,255,255,0.08);
    border: 1px solid var(--os-surface-border);
    font-variant-numeric: tabular-nums;
}
.os-tray-temp[data-status="warning"] .os-temp-pill { background: rgba(255, 170, 50, 0.18); border-color: rgba(255, 170, 50, 0.5); }
.os-tray-temp[data-status="critical"] .os-temp-pill { background: rgba(220, 60, 60, 0.22); border-color: rgba(220, 60, 60, 0.6); }

.os-tray-badge {
    position: absolute;
    top: 4px;
    right: 4px;
    background: var(--os-accent);
    color: #fff;
    font-size: 10px;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 8px;
    min-width: 14px;
    text-align: center;
    font-weight: 600;
}

/* ── Flyouts (Quick Settings, Action Center, Calendar) ───────────── */
.os-flyout {
    position: fixed;
    right: 8px;
    bottom: calc(var(--os-tb-height) + 8px);
    width: 360px;
    max-height: calc(100vh - var(--os-tb-height) - 24px);
    background: var(--os-surface);
    backdrop-filter: blur(28px) saturate(160%);
    -webkit-backdrop-filter: blur(28px) saturate(160%);
    border: 1px solid var(--os-surface-border);
    border-radius: 10px;
    box-shadow: var(--os-shadow);
    color: var(--os-fg);
    z-index: 22;
    display: flex;
    flex-direction: column;
    padding: 12px 14px;
    gap: 10px;
    overflow: hidden;
}
.os-flyout[hidden] { display: none; }
.os-flyout-head {
    font-size: 13px;
    font-weight: 600;
    color: var(--os-fg-muted);
    padding-bottom: 4px;
    border-bottom: 1px solid var(--os-surface-border);
}

/* Quick Settings */
.os-qs-row { display: flex; gap: 8px; flex-wrap: wrap; }
.os-qs-toggle {
    appearance: none;
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--os-surface-border);
    border-radius: 8px;
    color: var(--os-fg);
    padding: 10px 12px;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 8px;
    font: inherit; font-size: 13px;
}
.os-qs-toggle:hover { background: rgba(255,255,255,0.12); }
.os-qs-toggle.active { background: var(--os-accent-soft); border-color: var(--os-accent); color: var(--os-fg); }
.os-qs-section { display: flex; flex-direction: column; gap: 6px; }
.os-qs-section-head { font-size: 12px; color: var(--os-fg-muted); }
.os-qs-accents { display: flex; gap: 8px; }
.os-qs-accent {
    width: 28px; height: 28px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    background: transparent;
}
.os-qs-accent.selected { border-color: #fff; box-shadow: 0 0 0 2px var(--os-accent); }
.os-qs-wallpapers {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
    gap: 8px;
    max-height: 200px;
    overflow-y: auto;
}
.os-qs-wallpaper {
    aspect-ratio: 16 / 10;
    border-radius: 6px;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    background: rgba(255,255,255,0.04) center/cover no-repeat;
    transition: border-color 120ms ease, background-color 120ms ease;
    position: relative;
}
.os-qs-wallpaper:hover { border-color: rgba(255,255,255,0.3); }
.os-qs-wallpaper.selected { border-color: #fff; box-shadow: 0 0 0 2px var(--os-accent); }
.os-qs-wallpaper-none {
    background: rgba(255,255,255,0.04);
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255,255,255,0.6);
    font-size: 18px;
    line-height: 1;
    font-weight: 300;
}
.os-qs-wallpaper-none::before {
    content: '\00d7';   /* × — clearly "no background" */
}
.os-qs-wallpaper-none:hover { color: #fff; background: rgba(255,255,255,0.08); }
.os-qs-wallpapers-empty {
    grid-column: 1 / -1;
    margin: 0;
    font-size: 12px;
    color: var(--os-fg-muted);
}
.os-qs-wallpapers-empty code {
    font-size: 11px;
    background: rgba(255,255,255,0.08);
    padding: 1px 4px;
    border-radius: 3px;
}
.os-qs-actions { display: flex; gap: 8px; padding-top: 4px; border-top: 1px solid var(--os-surface-border); }
.os-qs-actions button {
    appearance: none;
    flex: 1;
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--os-surface-border);
    color: var(--os-fg);
    border-radius: 6px;
    padding: 8px;
    cursor: pointer;
    font: inherit; font-size: 12px;
}
.os-qs-actions button:hover { background: rgba(255,255,255,0.14); }

/* Action Center */
.os-ac-list { display: flex; flex-direction: column; gap: 6px; overflow-y: auto; flex: 1; }
.os-ac-empty { color: var(--os-fg-muted); font-size: 12px; margin: 12px 0; text-align: center; }
.os-ac-item {
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--os-surface-border);
    border-radius: 8px;
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.os-ac-item.severity-critical { border-color: rgba(220, 60, 60, 0.55); background: rgba(220, 60, 60, 0.16); }
.os-ac-item.severity-warning  { border-color: rgba(255, 170, 50, 0.55); background: rgba(255, 170, 50, 0.14); }
.os-ac-item-meta { display: flex; justify-content: space-between; font-size: 11px; color: var(--os-fg-muted); }
.os-ac-item-title { font-size: 13px; font-weight: 600; }
.os-ac-item-body { font-size: 12px; color: var(--os-fg-muted); }

/* Calendar */
.os-calendar { width: 320px; }
.os-cal-now { font-size: 28px; font-weight: 300; letter-spacing: -0.02em; }
.os-cal-month-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 13px;
    font-weight: 600;
}
.os-cal-month-head button {
    appearance: none; background: transparent; border: 0; color: var(--os-fg);
    width: 28px; height: 28px; border-radius: 6px; cursor: pointer; font-size: 16px;
}
.os-cal-month-head button:hover { background: rgba(255,255,255,0.08); }
.os-cal-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    font-size: 12px;
    text-align: center;
}
.os-cal-dow { color: var(--os-fg-muted); font-weight: 600; padding: 4px 0; }
.os-cal-day { padding: 6px 0; border-radius: 6px; cursor: default; }
.os-cal-day.muted { color: var(--os-fg-muted); opacity: 0.4; }
.os-cal-day.today { background: var(--os-accent); color: #fff; font-weight: 600; }

/* Analog clock inside the calendar flyout */
.os-clock-mini {
    --osc-face: #161b22;
    --osc-edge: #2a313a;
    --osc-tick: #4a525c;
    --osc-tick-major: #c9d1d9;
    --osc-hand: #e6edf3;
    --osc-second: #f97583;
    --osc-pivot: #f97583;
    --osc-text: #8b949e;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 4px 0 6px;
    border-bottom: 1px solid var(--os-surface-border);
}
.os-clock-mini.light {
    --osc-face: #ffffff;
    --osc-edge: #d0d7de;
    --osc-tick: #8b949e;
    --osc-tick-major: #1f2328;
    --osc-hand: #1f2328;
    --osc-text: #57606a;
}
.os-clock-mini-face {
    width: 168px;
    height: 168px;
    filter: drop-shadow(0 6px 18px rgba(0,0,0,0.35));
}
.os-clock-mini-face svg { width: 100%; height: 100%; display: block; }
.os-clock-mini-digital {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    font-size: 22px;
    font-weight: 600;
    letter-spacing: 1px;
    color: var(--osc-hand);
    font-family: "SF Mono", "Menlo", "Consolas", ui-monospace, monospace;
    line-height: 1;
}
.os-clock-mini-digital .os-clock-mini-ampm {
    font-size: 12px;
    font-weight: 500;
    color: var(--osc-text);
    margin-left: 4px;
}
.os-clock-mini-circle { fill: var(--osc-face); stroke: var(--osc-edge); stroke-width: 2; }
.os-clock-mini-inner  { fill: none; stroke: var(--osc-edge); stroke-width: 1; opacity: 0.5; }
.os-clock-mini-tick       { stroke: var(--osc-tick); stroke-width: 1.5; stroke-linecap: round; }
.os-clock-mini-tick-major { stroke: var(--osc-tick-major); stroke-width: 3; stroke-linecap: round; }
.os-clock-mini-numeral {
    fill: var(--osc-tick-major);
    font-size: 12px;
    font-weight: 500;
    text-anchor: middle;
    dominant-baseline: central;
    font-family: "Helvetica Neue", Arial, sans-serif;
}
.os-clock-mini.roman .os-clock-mini-numeral {
    font-family: "Times New Roman", serif;
    font-style: italic;
    font-weight: 400;
}
.os-clock-mini-hand   { stroke-linecap: round; }
.os-clock-mini-hour   { stroke: var(--osc-hand); stroke-width: 5; }
.os-clock-mini-minute { stroke: var(--osc-hand); stroke-width: 3; }
.os-clock-mini-second { stroke: var(--osc-second); stroke-width: 1.5; }
.os-clock-mini-pivot-outer { fill: var(--osc-hand); }
.os-clock-mini-pivot-inner { fill: var(--osc-pivot); }
.os-clock-mini-controls { display: flex; gap: 6px; }
.os-clock-mini-btn {
    appearance: none;
    background: rgba(255,255,255,0.04);
    border: 1px solid var(--os-surface-border);
    color: var(--os-fg-muted);
    padding: 5px 12px;
    border-radius: 999px;
    cursor: pointer;
    font: inherit;
    font-size: 12px;
    transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.os-clock-mini-btn:hover {
    background: rgba(255,255,255,0.1);
    color: var(--os-fg);
    border-color: rgba(255,255,255,0.2);
}
.os-clock-mini-btn.active {
    background: var(--os-accent);
    border-color: var(--os-accent);
    color: #fff;
}

/* ── Pinned taskbar apps ─────────────────────────────────────────── */
.os-tb-pin {
    appearance: none;
    background: transparent;
    border: 0;
    min-width: 40px;
    height: 40px;
    padding: 0 6px;
    border-radius: var(--os-radius-sm);
    color: var(--os-fg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    cursor: pointer;
    position: relative;
    transition: background 120ms ease, max-width 180ms ease, padding 180ms ease;
}
.os-tb-pin:hover { background: rgba(255, 255, 255, 0.08); }
.os-tb-pin:focus-visible { outline: 2px solid var(--os-accent); outline-offset: 2px; }
.os-tb-pin img,
.os-tb-pin svg { width: 22px; height: 22px; display: block; flex-shrink: 0; }
.os-tb-pin .os-pin-fallback {
    width: 22px; height: 22px;
    border-radius: 5px;
    background: linear-gradient(135deg, #4a8be6, #2563c4);
    color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
    flex-shrink: 0;
}
.os-tb-pin-label {
    font-size: 12px;
    line-height: 1.1;
    color: var(--os-fg);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 0;
    opacity: 0;
    transition: max-width 180ms ease, opacity 140ms ease, margin 180ms ease;
    margin-right: -6px; /* collapses gap when hidden */
    pointer-events: none;
}
/* Show the label only when the pin's app is running (pinned-and-running, or
   transient pins which start with `running` always applied). */
.os-tb-pin.running .os-tb-pin-label {
    max-width: 180px;
    opacity: 1;
    margin-right: 0;
    padding-right: 2px;
}

/* ── Start menu ──────────────────────────────────────────────────── */
.os-startmenu {
    position: fixed;
    left: 50%;
    bottom: calc(var(--os-tb-height) + 10px);
    transform: translateX(-50%) translateY(8px);
    width: min(640px, calc(100vw - 32px));
    height: min(680px, calc(100vh - var(--os-tb-height) - 32px));
    background: var(--os-surface);
    backdrop-filter: blur(28px) saturate(160%);
    -webkit-backdrop-filter: blur(28px) saturate(160%);
    border: 1px solid var(--os-surface-border);
    border-radius: var(--os-radius);
    box-shadow: var(--os-shadow);
    color: var(--os-fg);
    z-index: 20;
    display: flex;
    flex-direction: column;
    padding: 18px 20px 12px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 140ms ease, transform 140ms ease;
}
.os-startmenu.open {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(-50%) translateY(0);
}
.os-startmenu[hidden] { display: none; }

.os-sm-search {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    margin-bottom: 16px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--os-surface-border);
    border-radius: 18px;
    color: var(--os-fg-muted);
}
.os-sm-search input {
    flex: 1;
    background: transparent;
    border: 0;
    outline: 0;
    color: var(--os-fg);
    font: inherit;
    font-size: 13px;
}
.os-sm-search input::placeholder { color: var(--os-fg-muted); }

.os-sm-section { margin-bottom: 14px; }
.os-sm-section:last-of-type { flex: 1; min-height: 0; display: flex; flex-direction: column; margin-bottom: 8px; }
.os-sm-section-head {
    font-size: 12px;
    font-weight: 600;
    color: var(--os-fg-muted);
    margin-bottom: 8px;
    padding-left: 4px;
}

.os-sm-pinned {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 6px;
}

.os-app-tile {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--os-radius-sm);
    color: var(--os-fg);
    padding: 12px 6px 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    text-align: center;
    transition: background 120ms ease, border-color 120ms ease;
}
.os-app-tile:hover { background: rgba(255, 255, 255, 0.08); border-color: var(--os-surface-border); }
.os-app-tile:focus-visible { outline: 2px solid var(--os-accent); outline-offset: 2px; }
.os-app-tile-icon {
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 8px;
    background: linear-gradient(135deg, #4a8be6, #2563c4);
    color: #fff;
    font-weight: 700;
    font-size: 14px;
}
.os-app-tile-icon img { width: 28px; height: 28px; }
.os-app-tile-name {
    font-size: 11px;
    line-height: 1.2;
    color: var(--os-fg);
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    word-break: break-word;
}

.os-sm-all {
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    flex: 1;
}
.os-sm-all li { margin: 0; }
.os-sm-row {
    appearance: none;
    width: 100%;
    background: transparent;
    border: 0;
    color: var(--os-fg);
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border-radius: var(--os-radius-sm);
    cursor: pointer;
    text-align: left;
    font: inherit;
    font-size: 13px;
}
.os-sm-row:hover { background: rgba(255, 255, 255, 0.08); }
.os-sm-row-icon {
    width: 22px; height: 22px;
    border-radius: 5px;
    background: linear-gradient(135deg, #4a8be6, #2563c4);
    color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 10px; font-weight: 700;
    flex-shrink: 0;
}
.os-sm-row-icon img { width: 18px; height: 18px; }

.os-sm-foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-top: 8px;
    border-top: 1px solid var(--os-surface-border);
    color: var(--os-fg-muted);
    font-size: 12px;
}

/* ── Windows host & windows ──────────────────────────────────────── */
.os-windows {
    position: fixed;
    inset: 0 0 var(--os-tb-height) 0;
    pointer-events: none;
    z-index: 5;
}
.os-windows > * { pointer-events: auto; }

.os-win {
    position: absolute;
    background: var(--os-surface);
    border: 1px solid var(--os-surface-border);
    border-radius: var(--os-radius);
    box-shadow: 0 12px 36px rgba(0, 0, 0, 0.45);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    color: var(--os-fg);
    backdrop-filter: blur(18px) saturate(140%);
    -webkit-backdrop-filter: blur(18px) saturate(140%);
    transition: opacity 120ms ease;
}
.os-win.minimized { display: none; }
.os-win.focused { box-shadow: 0 16px 48px rgba(0, 0, 0, 0.55); border-color: rgba(255,255,255,0.18); }
.os-win.maximized { border-radius: 0; box-shadow: none; }

.os-win-chrome {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 32px;
    padding: 0 0 0 12px;
    background: rgba(0, 0, 0, 0.22);
    border-bottom: 1px solid var(--os-surface-border);
    color: var(--os-fg);
    font-size: 12px;
    font-weight: 500;
    user-select: none;
    cursor: grab;
    flex-shrink: 0;
}
.os-win-chrome:active { cursor: grabbing; }
.os-win-title {
    flex: 1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    letter-spacing: 0.01em;
}
.os-win-controls { display: flex; align-items: stretch; }
.os-win-btn {
    appearance: none;
    background: transparent;
    border: 0;
    width: 44px; height: 32px;
    color: var(--os-fg);
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background 100ms ease, color 100ms ease;
}
.os-win-btn:hover { background: rgba(255,255,255,0.08); }
.os-win-btn.os-win-close:hover { background: #c42b1c; color: #fff; }

.os-win-frame {
    flex: 1;
    border: 0;
    width: 100%;
    background: #fff;
}
body.os-wm-interacting .os-win-frame { pointer-events: none; }
body.os-wm-interacting .os-assistant-host iframe { pointer-events: none; }
body.os-wm-interacting { user-select: none; cursor: grabbing; }

/* Resize handles */
.os-win-resize {
    position: absolute;
    background: transparent;
    z-index: 1;
}
.os-win.maximized .os-win-resize { display: none; }
.os-win-resize.n  { top: 0;    left: 10px; right: 10px; height: 5px; cursor: ns-resize; }
.os-win-resize.s  { bottom: 0; left: 10px; right: 10px; height: 5px; cursor: ns-resize; }
.os-win-resize.e  { right: 0;  top: 10px; bottom: 10px; width: 5px; cursor: ew-resize; }
.os-win-resize.w  { left: 0;   top: 10px; bottom: 10px; width: 5px; cursor: ew-resize; }
.os-win-resize.ne { top: 0;    right: 0;  width: 12px; height: 12px; cursor: nesw-resize; }
.os-win-resize.nw { top: 0;    left: 0;   width: 12px; height: 12px; cursor: nwse-resize; }
.os-win-resize.se { bottom: 0; right: 0;  width: 12px; height: 12px; cursor: nwse-resize; }
.os-win-resize.sw { bottom: 0; left: 0;   width: 12px; height: 12px; cursor: nesw-resize; }

/* Snap preview overlay */
.os-snap-overlay {
    position: fixed;
    background: rgba(0, 120, 212, 0.18);
    border: 2px solid rgba(0, 120, 212, 0.55);
    border-radius: 6px;
    pointer-events: none;
    z-index: 4;
    transition: all 80ms ease;
}
.os-snap-overlay[hidden] { display: none; }

/* Alt+Tab switcher */
.os-altswitch {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    background: var(--os-surface);
    border: 1px solid var(--os-surface-border);
    border-radius: 12px;
    backdrop-filter: blur(28px) saturate(160%);
    -webkit-backdrop-filter: blur(28px) saturate(160%);
    box-shadow: var(--os-shadow);
    padding: 16px;
    z-index: 30;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    max-width: 80vw;
}
.os-altswitch[hidden] { display: none; }
.os-altswitch-item {
    min-width: 160px;
    padding: 10px 14px;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.05);
    border: 2px solid transparent;
    color: var(--os-fg);
    font-size: 12px;
}
.os-altswitch-item.active {
    border-color: var(--os-accent);
    background: rgba(0, 120, 212, 0.18);
}
.os-altswitch-title {
    display: block;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

/* ── Lock screen ─────────────────────────────────────────────────── */
body.os-lock {
    margin: 0;
    height: 100vh;
    overflow: hidden;
    color: #fff;
    font-family: var(--os-font);
    position: relative;
    background: #0a3a6b;
}
.os-lock-bg {
    position: fixed;
    inset: 0;
    background:
        radial-gradient(1200px 800px at 20% 30%, #6ab1e8, transparent 60%),
        radial-gradient(1000px 700px at 80% 70%, #1d6fb8, transparent 65%),
        linear-gradient(135deg, #0a3a6b, #1d6fb8);
    z-index: 0;
}
.os-lock-clock {
    position: fixed;
    top: 8vh;
    left: 8vw;
    z-index: 1;
    color: #fff;
    text-shadow: 0 2px 16px rgba(0,0,0,0.4);
    user-select: none;
}
.os-lock-time {
    display: block;
    font-size: clamp(72px, 12vw, 144px);
    font-weight: 200;
    line-height: 1;
    letter-spacing: -0.04em;
    font-variant-numeric: tabular-nums;
}
.os-lock-date {
    display: block;
    font-size: clamp(18px, 2vw, 24px);
    font-weight: 400;
    margin-top: 6px;
    opacity: 0.92;
}
.os-lock-card {
    position: relative;
    z-index: 2;
    width: min(360px, calc(100vw - 32px));
    margin: 0 auto;
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    text-align: center;
}
.os-lock-avatar-large {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    background: linear-gradient(135deg, #4a8be6, #2563c4);
    color: #fff;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 32px;
    font-weight: 600;
    letter-spacing: 0.02em;
    box-shadow: 0 8px 24px rgba(0,0,0,0.4);
}
.os-lock-fullname {
    font-size: 20px;
    font-weight: 500;
    margin-bottom: 6px;
}
.os-lock-users {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
    gap: 12px;
    width: 100%;
    margin-bottom: 8px;
}
.os-lock-user {
    appearance: none;
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 10px;
    color: #fff;
    padding: 10px 8px;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}
.os-lock-user:hover { background: rgba(255,255,255,0.16); }
.os-lock-avatar {
    width: 40px; height: 40px; border-radius: 50%;
    background: linear-gradient(135deg, #4a8be6, #2563c4);
    color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 14px; font-weight: 600;
}
.os-lock-username { font-size: 12px; }
.os-lock-form {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 100%;
}
.os-lock-field { display: flex; flex-direction: column; gap: 6px; text-align: left; }
.os-lock-field span { font-size: 12px; color: rgba(255,255,255,0.78); }
.os-lock-field input {
    appearance: none;
    background: rgba(255,255,255,0.92);
    border: 0;
    border-radius: 6px;
    padding: 10px 12px;
    font: inherit;
    font-size: 14px;
    color: #1b1b1b;
    outline: none;
}
.os-lock-field input:focus { box-shadow: 0 0 0 2px rgba(255,255,255,0.7); }
.os-lock-error {
    margin: 0;
    color: #ffd1c4;
    font-size: 12px;
}
.os-lock-submit {
    appearance: none;
    background: rgba(255,255,255,0.92);
    border: 0;
    border-radius: 6px;
    padding: 10px 14px;
    font: inherit;
    font-size: 14px;
    font-weight: 500;
    color: #0a3a6b;
    cursor: pointer;
}
.os-lock-submit:hover { background: #fff; }
.os-lock-instance {
    position: fixed;
    bottom: 16px;
    right: 16px;
    font-size: 12px;
    color: rgba(255,255,255,0.78);
    z-index: 2;
}

/* ── Start-menu power menu ───────────────────────────────────────── */
.os-sm-power-wrap { position: relative; }
.os-sm-power-btn {
    appearance: none;
    background: transparent;
    border: 0;
    width: 32px; height: 32px;
    border-radius: var(--os-radius-sm);
    color: var(--os-fg);
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
}
.os-sm-power-btn:hover { background: rgba(255,255,255,0.08); }
.os-sm-power-menu {
    position: absolute;
    right: 0;
    bottom: 100%;
    margin-bottom: 6px;
    min-width: 160px;
    background: var(--os-surface);
    border: 1px solid var(--os-surface-border);
    border-radius: 8px;
    backdrop-filter: blur(28px) saturate(160%);
    -webkit-backdrop-filter: blur(28px) saturate(160%);
    box-shadow: var(--os-shadow);
    padding: 4px;
    display: flex;
    flex-direction: column;
    z-index: 25;
}
.os-sm-power-menu[hidden] { display: none; }
.os-sm-power-menu button {
    appearance: none;
    background: transparent;
    border: 0;
    color: var(--os-fg);
    text-align: left;
    padding: 8px 12px;
    border-radius: 6px;
    cursor: pointer;
    font: inherit;
    font-size: 13px;
}
.os-sm-power-menu button:hover { background: rgba(255,255,255,0.08); }

/* ── Assistant dock (iframe overlay) ─────────────────────────────────── */
/* The host is a small rectangle in the bottom-right of the desktop. The
   iframe inside it is `pointer-events: auto` so clicks land on the
   visualizer / drawer / panels normally. The rest of the desktop stays
   clickable because the iframe doesn't cover it. */
.os-assistant-host {
    position: fixed;
    left: 0;
    bottom: var(--os-tb-height);
    width: 750px;
    height: min(820px, calc(100vh - var(--os-tb-height) - 16px));
    max-width: 100vw;
    z-index: 4;
    pointer-events: none;
}
.os-assistant-host iframe {
    width: 100%;
    height: 100%;
    border: 0;
    background: transparent;
    pointer-events: auto;
}
.os-assistant-host.obstructed {
    /* Detector hides the dock when a window covers it; the taskbar mini-pill
       (.os-tb-assistant-mini) becomes the visible affordance instead. */
    display: none;
}

/* Phone/tablet docks are taller than --os-tb-height (48px) and extend through
   the home-indicator safe area, so the host's bottom must clear the *real*
   dock height — otherwise the text-drawer (pinned to bottom:0 inside the
   iframe) overlaps the dock. --os-dock-h is the live measured taskbar height,
   published by shell.js once Start/pins/tray have laid out, so the drawer
   tracks the dock's settled end-state (the static fallbacks cover the brief
   pre-JS window and mirror the declared dock heights). */
body.os-mode-phone .os-assistant-host {
    bottom: var(--os-dock-h, calc(60px + env(safe-area-inset-bottom, 0px)));
    height: min(820px, calc(100vh - var(--os-dock-h, calc(60px + env(safe-area-inset-bottom, 0px))) - 16px));
}
body.os-mode-tablet .os-assistant-host {
    bottom: var(--os-dock-h, calc(56px + env(safe-area-inset-bottom, 0px)));
    height: min(820px, calc(100vh - var(--os-dock-h, calc(56px + env(safe-area-inset-bottom, 0px))) - 16px));
}

/* ── Taskbar left slot — mini assistant pill (mirror of right tray) ── */
.os-tb-leftslot {
    position: absolute;
    left: 12px;
    top: 0; bottom: 0;
    display: flex;
    align-items: center;
    pointer-events: none;
}
.os-tb-leftslot > * { pointer-events: auto; }
.os-tb-assistant-mini {
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--os-surface-border);
    border-radius: var(--os-radius-sm);
    color: var(--os-fg);
    height: 36px;
    padding: 0 6px 0 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    max-width: min(480px, 42vw);
    overflow: hidden;
}
.os-tb-assistant-mini[hidden] { display: none; }
.os-tb-assistant-mini-main {
    appearance: none;
    background: transparent;
    border: 0;
    border-radius: var(--os-radius-sm) 0 0 var(--os-radius-sm);
    color: inherit;
    height: 100%;
    padding: 0 8px 0 10px;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    font: inherit;
    font-size: 12px;
    transition: background 100ms ease;
    min-width: 0;
    overflow: hidden;
}
.os-tb-assistant-mini-main:hover { background: rgba(255,255,255,0.12); }
.os-tb-assistant-mini-mic {
    appearance: none;
    flex-shrink: 0;
    height: 24px;
    min-width: 24px;
    padding: 0 10px;
    border: 0;
    border-radius: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    font: inherit;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    transition: background 120ms ease;
}
.os-tb-assistant-mini-mic.mic-idle { background: #16a34a; color: #fff; }
.os-tb-assistant-mini-mic.mic-idle:hover { background: #15803d; }
.os-tb-assistant-mini-mic.mic-connecting {
    background: rgba(255,255,255,0.10);
    color: var(--os-fg);
    animation: os-tb-mini-mic-pulse 1.2s ease-in-out infinite;
}
.os-tb-assistant-mini-mic.mic-active { background: #ef4444; color: #fff; padding: 0 8px; }
.os-tb-assistant-mini-mic.mic-active:hover { background: #dc2626; }
.os-tb-assistant-mini-mic.mic-error {
    background: rgba(251,146,60,0.15);
    color: #fb923c;
    border: 1px solid rgba(251,146,60,0.3);
}
.os-tb-assistant-mini-mic.mic-error:hover { background: rgba(251,146,60,0.25); }
@keyframes os-tb-mini-mic-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.45; }
}
.os-tb-assistant-mini-cog {
    appearance: none;
    flex-shrink: 0;
    height: 24px;
    width: 24px;
    padding: 0;
    border: 0;
    border-radius: 12px;
    background: rgba(255,255,255,0.06);
    color: var(--os-fg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 100ms ease;
}
.os-tb-assistant-mini-cog:hover { background: rgba(255,255,255,0.16); }
.os-tb-assistant-mini-wave {
    width: 96px;
    height: 22px;
    display: block;
    flex-shrink: 0;
    opacity: 0.95;
}
.os-tb-assistant-mini-caption {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
}
.os-tb-assistant-mini-who {
    color: var(--os-accent);
    font-weight: 600;
    flex-shrink: 0;
}
.os-tb-assistant-mini-text {
    color: var(--os-fg);
    opacity: 0.85;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.os-tb-assistant-mini-caption:empty,
.os-tb-assistant-mini-text:empty { display: none; }

/* Running indicators on taskbar pins */
.os-tb-pin { position: relative; }
.os-tb-pin.running::after {
    content: "";
    position: absolute;
    bottom: 2px;
    left: 50%;
    transform: translateX(-50%);
    width: 12px;
    height: 2px;
    border-radius: 1px;
    background: var(--os-accent);
    opacity: 0.7;
}
.os-tb-pin.running.focused::after {
    width: 22px;
    opacity: 1;
}

/* ╔══════════════════════════════════════════════════════════════════╗
   ║  Mobile & PWA foundations (Phase 1 / Phase 2 / Phase 3)         ║
   ║  Desktop styles above are unchanged. Everything below scopes    ║
   ║  to body.os-mode-tablet / .os-mode-phone, or to the .os-standalone
   ║  class set when the page is launched as a PWA.                  ║
   ╚══════════════════════════════════════════════════════════════════╝ */

:root {
    /* Resolved safe-area insets. Fallbacks are 0 so desktop is unaffected. */
    --os-safe-top:    env(safe-area-inset-top, 0px);
    --os-safe-right:  env(safe-area-inset-right, 0px);
    --os-safe-bottom: env(safe-area-inset-bottom, 0px);
    --os-safe-left:   env(safe-area-inset-left, 0px);
}

/* When running as an installed PWA, suppress browser-style overscroll glow
   and use the dynamic viewport so the iOS URL bar doesn't crop content. */
body.os-standalone,
body.os-mode-phone,
body.os-mode-tablet {
    overscroll-behavior: none;
}
body.os-mode-phone,
body.os-mode-tablet {
    /* Use dvh where supported so iOS Safari URL bar resize doesn't crop
       the shell. Falls back to 100vh for older engines. */
    height: 100vh;
    height: 100dvh;
}
body.os-mode-phone .os-lock-bg,
body.os-mode-tablet .os-lock-bg {
    height: 100dvh;
}

/* ╔══════════════════════════════════════════════════════════════════╗
   ║  Phase 2 — Phone shell (max-width: 640px, coarse pointer)       ║
   ║                                                                  ║
   ║  Reuses the existing taskbar / Start menu / flyouts / windows   ║
   ║  DOM but restyles them as a bottom dock, fullscreen Home grid,  ║
   ║  bottom sheets, and fullscreen window sheets respectively.     ║
   ╚══════════════════════════════════════════════════════════════════╝ */

body.os-mode-phone .os-desktop {
    /* Background only; no icons grid on phone. Pull-to-refresh / overscroll
       glow already suppressed via overscroll-behavior on body. */
    padding: 0;
}

/* Lock-screen ─────────────────────────────────────────────────────── */
body.os-mode-phone.os-lock {
    background-position: center;
    background-size: cover;
}
body.os-mode-phone .os-lock-clock {
    top: calc(env(safe-area-inset-top, 0px) + 28px);
    left: 0; right: 0;
    text-align: center;
    transform: none;
    padding: 0 20px;
}
body.os-mode-phone .os-lock-clock .os-lock-time { font-size: 64px; }
body.os-mode-phone .os-lock-clock .os-lock-date { font-size: 16px; }
body.os-mode-phone .os-lock-card {
    left: max(env(safe-area-inset-left, 0px), 16px);
    right: max(env(safe-area-inset-right, 0px), 16px);
    bottom: max(env(safe-area-inset-bottom, 0px), 24px);
    top: auto;
    transform: none;
    width: auto;
    max-width: none;
    padding: 24px 20px;
    border-radius: 18px;
}
body.os-mode-phone .os-lock-users {
    flex-direction: column;
    gap: 8px;
}
body.os-mode-phone .os-lock-user {
    min-height: 56px;
    width: 100%;
    justify-content: flex-start;
    padding: 12px 14px;
}
body.os-mode-phone .os-lock-form input,
body.os-mode-phone .os-lock-form .os-lock-submit {
    min-height: 48px;
    font-size: 16px; /* prevent iOS zoom-on-focus */
}

/* Dock (the existing .os-taskbar restyled) ──────────────────────────── */
body.os-mode-phone .os-taskbar {
    /* Flush bottom edge; height extends through the safe-area so the bar
       visually meets the home indicator. The inner padding-bottom carries
       the safe-area space so content stays touch-reachable. */
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    max-width: none;
    height: calc(60px + env(safe-area-inset-bottom, 0px));
    border-radius: 0;
    padding: 0;
    backdrop-filter: blur(24px) saturate(140%);
    -webkit-backdrop-filter: blur(24px) saturate(140%);
}
body.os-mode-phone .os-taskbar-inner {
    /* Flex so DOM order (Start → Pins → Tray) is visual order. The desktop
       grid would otherwise drop the tray (which loses its absolute-position
       when its container becomes static) into column 1, pushing it left. */
    display: flex;
    align-items: center;
    grid-template-columns: none;
    padding: 6px max(env(safe-area-inset-left, 0px), 8px) calc(env(safe-area-inset-bottom, 0px) + 6px) max(env(safe-area-inset-right, 0px), 8px);
    gap: 6px;
    justify-content: flex-start;
    border-radius: 0;
}
body.os-mode-phone .os-start-btn { grid-column: auto; flex: 0 0 auto; }
body.os-mode-phone .os-tb-pins { grid-column: auto; }
/* Hide the assistant mini-caption that hugs the left of the taskbar; on phone
   we don't have horizontal room. Drag-drive bridge still emits notifications
   via the bell / sheet. */
body.os-mode-phone .os-tb-leftslot { display: none; }

body.os-mode-phone .os-start-btn {
    min-width: 56px;
    min-height: 52px;
    border-radius: 14px;
}
body.os-mode-phone .os-start-btn .os-start-glyph { width: 36px; height: 36px; }

body.os-mode-phone .os-tb-pins {
    flex: 1;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    gap: 6px;
    padding: 0 4px;
    scroll-snap-type: x mandatory;
}
body.os-mode-phone .os-tb-pins::-webkit-scrollbar { display: none; }
body.os-mode-phone .os-tb-pin {
    min-width: 52px;
    min-height: 52px;
    border-radius: 14px;
    scroll-snap-align: center;
}
body.os-mode-phone .os-tb-pin img,
body.os-mode-phone .os-tb-pin svg { width: 28px; height: 28px; }

body.os-mode-phone .os-tb-tray { gap: 4px; padding-right: 2px; }
body.os-mode-phone .os-tray-btn {
    min-width: 48px;
    min-height: 48px;
    padding: 0 10px;
    border-radius: 14px;
}
body.os-mode-phone .os-tray-btn svg { width: 18px; height: 18px; }
/* Temperature pill: keep, but a touch smaller so the dock isn't cramped. */
body.os-mode-phone .os-tray-temp .os-temp-pill { font-size: 12px; }
/* Drop the inline clock label — calendar still opens via the clock button. */
body.os-mode-phone .os-tray-clock-btn .os-clock-time,
body.os-mode-phone .os-tray-clock-btn .os-clock-date { display: none; }
body.os-mode-phone .os-tray-clock-btn .os-clock {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    font-weight: 600;
}
body.os-mode-phone .os-tray-clock-btn::before {
    content: "";
    display: inline-block;
    width: 18px; height: 18px;
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><circle cx='8' cy='8' r='6' fill='none' stroke='black' stroke-width='1.4'/><path d='M8 4 V8 L11 10' stroke='black' stroke-width='1.4' fill='none' stroke-linecap='round'/></svg>") center/contain no-repeat;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><circle cx='8' cy='8' r='6' fill='none' stroke='black' stroke-width='1.4'/><path d='M8 4 V8 L11 10' stroke='black' stroke-width='1.4' fill='none' stroke-linecap='round'/></svg>") center/contain no-repeat;
}

/* Start menu → Home grid that clears the dock ────────────────────────
   The Start menu must NOT cover the dock — otherwise the Start button
   itself, the pins, and the clock all disappear under z-index:20, leaving
   the user with no visible way to dismiss the menu and no notification
   access while it's open. Bottom is clipped to the dock height so the
   dock peeks through. */
body.os-mode-phone .os-startmenu {
    left: 0;
    right: 0;
    top: 0;
    bottom: calc(60px + env(safe-area-inset-bottom, 0px));
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    border-radius: 0;
    transform: none !important;
    padding:
        calc(env(safe-area-inset-top, 0px) + 16px)
        max(env(safe-area-inset-right, 0px), 16px)
        16px
        max(env(safe-area-inset-left, 0px), 16px);
    overflow: hidden;
}
body.os-mode-phone .os-startmenu.open { transform: none; }
body.os-mode-phone .os-sm-search input {
    font-size: 16px;
    min-height: 44px;
}
body.os-mode-phone .os-sm-pinned {
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
}
body.os-mode-phone .os-sm-tile {
    min-height: 88px;
}
body.os-mode-phone .os-sm-tile img,
body.os-mode-phone .os-sm-tile svg { width: 36px; height: 36px; }
body.os-mode-phone .os-sm-all li { min-height: 56px; }
/* Phone: the sheet itself does NOT scroll (overflow:hidden above). The All-apps
   list stays the single scroller (it keeps the base flex:1 + its own overflow-y),
   and the footer is a normal flow item pinned by flex directly above the dock —
   so nothing bleeds past it. */
body.os-mode-phone .os-sm-all { -webkit-overflow-scrolling: touch; }
body.os-mode-phone .os-sm-foot {
    background: var(--os-surface);
    /* Full-bleed bar flush to the sheet's bottom edge (which equals the dock's
       top edge): the negative bottom margin cancels the sheet's 16px bottom
       padding, and the -16px sides cancel its side padding. */
    margin: 8px -16px -16px;
    padding: 12px 16px;
}

/* Flyouts → bottom sheets ─────────────────────────────────────────────
   IMPORTANT: scope to :not([hidden]) so display:flex doesn't beat the
   default .os-flyout[hidden] { display:none } on closed flyouts. */
body.os-mode-phone .os-flyout:not([hidden]) {
    left: max(env(safe-area-inset-left, 0px), 8px);
    right: max(env(safe-area-inset-right, 0px), 8px);
    top: auto;
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    width: auto;
    max-width: none;
    max-height: 70vh;
    max-height: 70dvh;
    border-radius: 22px;
    transform-origin: bottom center;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
body.os-mode-phone .os-flyout::before {
    /* Drag handle. Visual only — actual swipe-to-dismiss is a polish task. */
    content: "";
    display: block;
    width: 44px;
    height: 4px;
    border-radius: 2px;
    background: rgba(255,255,255,0.35);
    margin: 8px auto 4px;
    flex: 0 0 auto;
}
body.os-mode-phone[data-theme="light"] .os-flyout::before { background: rgba(0,0,0,0.25); }
body.os-mode-phone .os-flyout-head {
    font-size: 18px;
    text-align: center;
    padding: 8px 16px 12px;
}
body.os-mode-phone .os-flyout > *:not(.os-flyout-head):not(.os-cal-month-head) {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* Touch-friendly sizing inside sheets. */
body.os-mode-phone .os-qs-toggle,
body.os-mode-phone .os-qs-actions button,
body.os-mode-phone .os-ac-item,
body.os-mode-phone .os-home-tabs button {
    min-height: 48px;
}
body.os-mode-phone .os-qs-accents .os-qs-accent,
body.os-mode-phone .os-qs-wallpapers .os-qs-wallpaper {
    width: 56px; height: 56px;
}

/* Windows → fullscreen sheets ────────────────────────────────────────── */
body.os-mode-phone .os-windows {
    /* Constrain the window host so windows can't bleed past the safe area. */
    position: fixed;
    inset: 0;
    pointer-events: none; /* children re-enable */
}
body.os-mode-phone .os-win {
    /* wm.js skips applyRect() in mobile modes so no inline geometry to fight. */
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 100%;
    border-radius: 0;
    border: none;
    box-shadow: none;
    pointer-events: auto;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: calc(84px + env(safe-area-inset-bottom, 0px));
}
body.os-mode-phone .os-win-chrome {
    cursor: default;
    min-height: 48px;
    padding: 0 8px 0 14px;
}
body.os-mode-phone .os-win-chrome:active { cursor: default; }
body.os-mode-phone .os-win-title { font-size: 15px; font-weight: 600; }
body.os-mode-phone .os-win-btn {
    min-width: 44px;
    min-height: 44px;
}
/* Hide minimize + maximize on phone — only Close remains. Minimize is
   redundant because the dock + Start return the user to Home. */
body.os-mode-phone .os-win-btn[data-win-min],
body.os-mode-phone .os-win-btn[data-win-max] { display: none; }
/* No drag handles, no resize affordances on phone. */
body.os-mode-phone .os-win-resize { display: none !important; }
body.os-mode-phone .os-win.minimized { display: none; }

/* Snap overlay is meaningless on phone. */
body.os-mode-phone .os-snap-overlay { display: none !important; }
body.os-mode-phone .os-altswitch { display: none !important; }

/* Reduced-motion respect (applies in all modes but worth restating). */
@media (prefers-reduced-motion: reduce) {
    body.os-mode-phone .os-flyout,
    body.os-mode-phone .os-startmenu,
    body.os-mode-phone .os-win {
        transition: none !important;
        animation: none !important;
    }
}

/* Safety-net: minimum touch target on coarse pointers. */
@media (pointer: coarse) {
    body.os-mode-phone :is(button, [role="button"], a, input[type="checkbox"], input[type="radio"]) {
        min-height: 44px;
    }
}

/* ╔══════════════════════════════════════════════════════════════════╗
   ║  Phase 3 — Tablet shell (641–1023px, or coarse pointer up to    ║
   ║  1279px). Hybrid: keeps the bottom taskbar (enlarged for touch) ║
   ║  but renders windows fullscreen-by-default. No drag/resize.     ║
   ╚══════════════════════════════════════════════════════════════════╝ */

body.os-mode-tablet .os-taskbar {
    height: calc(56px + env(safe-area-inset-bottom, 0px));
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    max-width: none;
    border-radius: 0;
}
body.os-mode-tablet .os-taskbar-inner {
    display: flex;
    align-items: center;
    grid-template-columns: none;
    padding: 4px max(env(safe-area-inset-left, 0px), 10px) calc(env(safe-area-inset-bottom, 0px) + 4px) max(env(safe-area-inset-right, 0px), 10px);
    border-radius: 0;
    gap: 6px;
}
body.os-mode-tablet .os-tb-tray {
    position: static;
    margin-left: auto;
}
body.os-mode-tablet .os-start-btn { grid-column: auto; flex: 0 0 auto; }
body.os-mode-tablet .os-tb-pins { grid-column: auto; }
body.os-mode-tablet .os-start-btn,
body.os-mode-tablet .os-tb-btn,
body.os-mode-tablet .os-tray-btn {
    min-width: 48px;
    min-height: 48px;
    border-radius: 12px;
}
body.os-mode-tablet .os-tb-pin {
    min-width: 48px;
    min-height: 48px;
    border-radius: 12px;
}
body.os-mode-tablet .os-tb-pin img,
body.os-mode-tablet .os-tb-pin svg { width: 26px; height: 26px; }
body.os-mode-tablet .os-tray-btn svg { width: 18px; height: 18px; }

/* Start menu: drawer from the bottom, full-width with rounded top. ──── */
body.os-mode-tablet .os-startmenu {
    left: max(env(safe-area-inset-left, 0px), 12px);
    right: max(env(safe-area-inset-right, 0px), 12px);
    width: auto;
    max-width: none;
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    height: min(70vh, 70dvh);
    transform: none !important;
    border-radius: 18px;
}
body.os-mode-tablet .os-startmenu.open { transform: none !important; }
body.os-mode-tablet .os-sm-pinned { grid-template-columns: repeat(6, 1fr); }
body.os-mode-tablet .os-sm-tile { min-height: 96px; }
body.os-mode-tablet .os-sm-search input { font-size: 16px; min-height: 44px; }

/* Flyouts: side drawer anchored to the bottom-right. ───────────────────
   Scoped to :not([hidden]) so the desktop's display:none default still
   applies when the flyout is closed. */
body.os-mode-tablet .os-flyout:not([hidden]) {
    right: max(env(safe-area-inset-right, 0px), 12px);
    left: auto;
    bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    width: min(420px, calc(100vw - 24px));
    max-height: min(70vh, 70dvh);
    border-radius: 18px;
    display: flex;
    flex-direction: column;
}

/* Windows: fullscreen by default; tap maximize-toggle to split 50/50. ── */
body.os-mode-tablet .os-windows {
    position: fixed;
    inset: 0 0 calc(64px + env(safe-area-inset-bottom, 0px)) 0;
    pointer-events: none;
}
body.os-mode-tablet .os-win {
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    border-radius: 0;
    border: none;
    pointer-events: auto;
}
/* Allow .os-win.tiled-l / .tiled-r if WM ever sets them — kept generic so a
   future tile gesture works without further CSS. Default tablet has only one
   visible window at a time. */
body.os-mode-tablet .os-win.tiled-l {
    left: 0;
    width: 50%;
}
body.os-mode-tablet .os-win.tiled-r {
    left: 50%;
    width: 50%;
}
body.os-mode-tablet .os-win-chrome { min-height: 44px; }
body.os-mode-tablet .os-win-btn { min-width: 44px; min-height: 44px; }
/* No drag on tablet either. Minimize stays — sends to background; Maximize
   button hidden because windows are already fullscreen. */
body.os-mode-tablet .os-win-btn[data-win-max] { display: none; }
body.os-mode-tablet .os-win-resize { display: none !important; }
body.os-mode-tablet .os-snap-overlay,
body.os-mode-tablet .os-altswitch { display: none !important; }

/* ╔══════════════════════════════════════════════════════════════════╗
   ║  Phase 4 — App switcher + gesture polish                         ║
   ║  Phone/tablet only. Long-press Start opens a card stack; tap a   ║
   ║  card to focus; swipe-left/right to close. Bottom sheets accept  ║
   ║  swipe-down on the drag handle to dismiss.                       ║
   ╚══════════════════════════════════════════════════════════════════╝ */

.os-switcher { display: none; }
body.os-mode-phone .os-switcher,
body.os-mode-tablet .os-switcher {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 90;
    pointer-events: none;
}
.os-switcher[hidden] { display: none !important; }
body.os-mode-phone .os-switcher:not([hidden]),
body.os-mode-tablet .os-switcher:not([hidden]) { pointer-events: auto; }

.os-switcher-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.42);
    backdrop-filter: blur(14px) saturate(120%);
    -webkit-backdrop-filter: blur(14px) saturate(120%);
    opacity: 0;
    transition: opacity 160ms ease;
}
.os-switcher.open .os-switcher-backdrop { opacity: 1; }

.os-switcher-stack {
    position: absolute;
    inset: 0;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    padding:
        calc(env(safe-area-inset-top, 0px) + 32px)
        max(env(safe-area-inset-right, 0px), 16px)
        calc(96px + env(safe-area-inset-bottom, 0px))
        max(env(safe-area-inset-left, 0px), 16px);
    display: flex;
    flex-direction: column;
    gap: 14px;
    align-items: center;
}
.os-switcher-card {
    width: min(520px, 100%);
    min-height: 140px;
    border-radius: 18px;
    background: var(--os-surface);
    border: 1px solid var(--os-surface-border);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.32);
    color: var(--os-fg);
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    cursor: pointer;
    user-select: none;
    touch-action: pan-y;
    transform: translateX(0);
    transition: transform 220ms cubic-bezier(.2,.7,.2,1), opacity 220ms ease;
    opacity: 1;
}
.os-switcher-card.dragging {
    transition: none;
}
.os-switcher-card.removing {
    opacity: 0;
    transform: translateX(120%);
    pointer-events: none;
}
.os-switcher-card-head {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 600;
    font-size: 15px;
}
.os-switcher-card-icon {
    width: 28px; height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: rgba(255,255,255,0.08);
    flex: 0 0 auto;
}
.os-switcher-card-icon img,
.os-switcher-card-icon svg { width: 22px; height: 22px; }
.os-switcher-card-meta { color: var(--os-fg-muted); font-size: 12px; font-weight: 400; }
.os-switcher-card-body {
    flex: 1;
    border-radius: 10px;
    background: rgba(255,255,255,0.04);
    color: var(--os-fg-muted);
    padding: 12px;
    font-size: 12px;
    line-height: 1.5;
}
[data-theme="light"] .os-switcher-card-body { background: rgba(0,0,0,0.04); }
[data-theme="light"] .os-switcher-card-icon { background: rgba(0,0,0,0.06); }
.os-switcher-card-close {
    align-self: flex-end;
    min-height: 36px;
    min-width: 64px;
    background: transparent;
    border: 1px solid var(--os-surface-border);
    color: var(--os-fg);
    border-radius: 10px;
    font: inherit;
    cursor: pointer;
    padding: 0 12px;
}
.os-switcher-card-close:hover { background: rgba(255,255,255,0.06); }
[data-theme="light"] .os-switcher-card-close:hover { background: rgba(0,0,0,0.06); }
.os-switcher-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    color: rgba(255,255,255,0.7);
    font-size: 15px;
}

/* The drag handle on bottom sheets is purely visual today; Phase 4 wires it
   to a swipe-down-to-dismiss gesture. We highlight it on active touch. */
body.os-mode-phone .os-flyout {
    /* y-translate driven by JS during swipe; default identity. */
    transform: translateY(var(--os-sheet-dy, 0));
    transition: transform 220ms cubic-bezier(.2,.7,.2,1);
}
body.os-mode-phone .os-flyout.os-sheet-dragging {
    transition: none;
}

/* ╔══════════════════════════════════════════════════════════════════╗
   ║  Fix-pass: phone tray collapses to clock + system popover       ║
   ║                                                                  ║
   ║  Desktop & tablet are unaffected — the popover is display:none   ║
   ║  unless body.os-mode-phone is set, and the tray-button hides     ║
   ║  only apply in phone mode.                                       ║
   ╚══════════════════════════════════════════════════════════════════╝ */

/* On phone, the tray is a single visible control: the clock button.
   All other tray buttons are hidden by default — they're surfaced via the
   tray popover, or via the actions inside the existing flyouts. */
body.os-mode-phone .os-tb-tray {
    /* Override the desktop absolute-right positioning so the tray no longer
       overlaps the pins area. Drop into the inline flow at the right end. */
    position: static;
    margin-left: auto;
    gap: 0;
    padding: 0;
}
body.os-mode-phone [data-os-temp],
body.os-mode-phone [data-os-bell],
body.os-mode-phone [data-os-home],
body.os-mode-phone [data-os-theme] {
    display: none !important;
}
body.os-mode-phone [data-os-clock-btn] {
    min-height: 48px;
    padding: 0 14px;
    border-radius: 14px;
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--os-surface-border);
}
body.os-mode-phone [data-os-clock-btn]:hover { background: rgba(255,255,255,0.12); }
body.os-mode-phone[data-theme="light"] [data-os-clock-btn] { background: rgba(0,0,0,0.04); }
body.os-mode-phone[data-theme="light"] [data-os-clock-btn]:hover { background: rgba(0,0,0,0.08); }

/* Bring the clock label back: the earlier phone rule masked it. */
body.os-mode-phone [data-os-clock-btn]::before { display: none; }
body.os-mode-phone [data-os-clock-btn] .os-clock-time {
    display: inline-block;
    font-size: 14px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
body.os-mode-phone [data-os-clock-btn] .os-clock-date {
    display: none;
}
/* Notification dot on the collapsed clock when there are pending notifs. */
body.os-mode-phone [data-os-clock-btn].has-notifs::after {
    content: "";
    position: absolute;
    top: 4px;
    right: 4px;
    width: 8px; height: 8px;
    background: var(--os-accent);
    border-radius: 50%;
}

/* Pins area gets the remaining flex room and scrolls. */
body.os-mode-phone .os-tb-pins {
    flex: 1 1 0;
    min-width: 0;
}

/* System popover (phone only) ─────────────────────────────────────── */
.os-tray-popover {
    /* Off by default everywhere; phone mode promotes to fixed flex. */
    display: none;
}
body.os-mode-phone .os-tray-popover:not([hidden]) {
    display: flex;
    flex-direction: column;
    position: fixed;
    right: max(env(safe-area-inset-right, 0px), 8px);
    bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 8px);
    min-width: 200px;
    background: var(--os-surface);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    border: 1px solid var(--os-surface-border);
    border-radius: 14px;
    box-shadow: 0 12px 28px rgba(0,0,0,0.32);
    z-index: 25;
    padding: 6px;
    gap: 2px;
}
.os-tray-popover-item {
    appearance: none;
    background: transparent;
    border: 0;
    color: var(--os-fg);
    font: inherit;
    font-size: 14px;
    text-align: left;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 12px;
    min-height: 44px;
    border-radius: 10px;
    cursor: pointer;
    position: relative;
}
.os-tray-popover-item:hover { background: rgba(255,255,255,0.08); }
[data-theme="light"] .os-tray-popover-item:hover { background: rgba(0,0,0,0.05); }
.os-tray-popover-item svg { flex: 0 0 auto; }
.os-tray-popover-item span { flex: 1; }
.os-tray-popover-badge {
    background: var(--os-accent);
    color: #fff;
    font-size: 11px;
    padding: 2px 6px;
    border-radius: 8px;
    font-weight: 600;
    flex: 0 0 auto !important;
}

/* The earlier dock CSS pushed flyouts up by 84px to clear the floating pill.
   The dock is now flush and ~60px tall — bring sheets closer. */
body.os-mode-phone .os-flyout:not([hidden]) {
    bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 8px);
}
body.os-mode-phone .os-win {
    padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px));
}

/* OS context menu ─────────────────────────────────────────────────── */
.os-ctxmenu {
    position: fixed;
    min-width: 220px;
    max-width: 320px;
    background: var(--os-surface);
    backdrop-filter: blur(24px) saturate(160%);
    -webkit-backdrop-filter: blur(24px) saturate(160%);
    border: 1px solid var(--os-surface-border);
    border-radius: 12px;
    box-shadow: 0 14px 36px rgba(0,0,0,0.42);
    padding: 6px;
    z-index: 9000;
    display: flex;
    flex-direction: column;
    gap: 2px;
    color: var(--os-fg);
    font: inherit;
    font-size: 13px;
    user-select: none;
    animation: os-ctxmenu-in 80ms ease-out;
}
@keyframes os-ctxmenu-in {
    from { opacity: 0; transform: translateY(-4px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .os-ctxmenu { animation: none; }
}
.os-ctxmenu-sub { z-index: 9100; }
.os-ctxmenu-sep {
    border: 0;
    border-top: 1px solid var(--os-surface-border);
    margin: 4px 4px;
    opacity: 0.6;
}
.os-ctxmenu-item {
    appearance: none;
    background: transparent;
    border: 0;
    color: inherit;
    font: inherit;
    font-size: 13px;
    text-align: left;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 10px;
    min-height: 34px;
    border-radius: 8px;
    cursor: pointer;
    position: relative;
    line-height: 1.2;
}
.os-ctxmenu-item:hover:not([disabled]),
.os-ctxmenu-item:focus-visible {
    background: rgba(255,255,255,0.10);
    outline: none;
}
[data-theme="light"] .os-ctxmenu-item:hover:not([disabled]),
[data-theme="light"] .os-ctxmenu-item:focus-visible {
    background: rgba(0,0,0,0.06);
}
.os-ctxmenu-item[disabled] { opacity: 0.42; cursor: default; }
.os-ctxmenu-item.danger    { color: #ff6b6b; }
.os-ctxmenu-item.checked .os-ctxmenu-check { color: var(--os-accent); }
.os-ctxmenu-lead {
    flex: 0 0 18px;
    width: 18px;
    height: 18px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: inherit;
}
.os-ctxmenu-lead svg { width: 14px; height: 14px; }
.os-ctxmenu-check { font-size: 13px; }
.os-ctxmenu-label    { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.os-ctxmenu-shortcut { flex: 0 0 auto; opacity: 0.55; font-size: 11px; margin-left: 12px; }
.os-ctxmenu-chevron  { flex: 0 0 auto; opacity: 0.55; font-size: 14px; margin-left: 6px; }

/* Bottom-sheet variant — phone (and any narrow viewport in Phase 5). */
.os-ctxmenu.os-ctxmenu-sheet {
    position: fixed;
    left: 8px;
    right: 8px;
    bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    top: auto;
    max-width: none;
    min-width: 0;
    border-radius: 16px;
    padding: 8px;
    animation: os-ctxmenu-sheet-in 160ms ease-out;
}
.os-ctxmenu.os-ctxmenu-sheet .os-ctxmenu-item { min-height: 48px; font-size: 15px; }
.os-ctxmenu.os-ctxmenu-sheet .os-ctxmenu-lead { flex-basis: 24px; width: 24px; height: 24px; }
.os-ctxmenu.os-ctxmenu-sheet .os-ctxmenu-lead svg { width: 18px; height: 18px; }
@keyframes os-ctxmenu-sheet-in {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .os-ctxmenu.os-ctxmenu-sheet { animation: none; }
}
.os-ctxmenu-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.32);
    z-index: 8990;
    animation: os-ctxmenu-fade 120ms ease-out;
}
@keyframes os-ctxmenu-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Block the native menu on the desktop background, taskbar, start menu
   and window chrome — keeps the OS feeling integrated. Inputs and iframes
   keep the native menu (ctxmenu.js skips registered surfaces for them). */
body.os-shell #os-desktop,
body.os-shell #os-taskbar,
body.os-shell #os-startmenu,
body.os-shell #os-windows .os-win-titlebar { -webkit-touch-callout: none; }

/* Stacked sheet submenu — Phase 5. Sits above the parent sheet so the back
   item brings the user one level back without dismissing the whole menu. */
.os-ctxmenu.os-ctxmenu-sheet-stacked {
    z-index: 9050;
    animation: os-ctxmenu-sheet-slide-in 200ms ease-out;
}
@keyframes os-ctxmenu-sheet-slide-in {
    from { opacity: 0; transform: translateX(24px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .os-ctxmenu.os-ctxmenu-sheet-stacked { animation: none; }
}

/* When the sheet is open, hide submenu chevrons since the stacked sheet is the
   navigation affordance. Keeps the layout cleaner on touch. */
.os-ctxmenu.os-ctxmenu-sheet .os-ctxmenu-chevron { font-size: 18px; opacity: 0.7; }

/* ── Desktop shortcuts ─────────────────────────────────────────────
   Snap grid on desktop (≥1024px). Paged variant for tablet/phone is
   appended in Phase 4 (CSS just below this block, scoped by body.os-mode-*). */
.os-desktop-icons {
    position: absolute;
    inset: 0;
    padding: 16px;
    display: grid;
    /* Fixed-width cells so stored {col,row} positions stay visually stable
       across renders. Phone/tablet (`.paged`) overrides below. */
    grid-template-columns: repeat(auto-fill, 96px);
    grid-auto-rows: 88px;
    gap: 12px;
    overflow-y: auto;
    overflow-x: hidden;
    align-content: start;
}
.os-desktop-icons.paged { grid-template-columns: none; grid-auto-rows: auto; align-content: stretch; padding: 0; }

.os-desktop-shortcut {
    appearance: none;
    background: transparent;
    border: 0;
    color: inherit;
    font: inherit;
    padding: 6px 4px;
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 6px;
    cursor: pointer;
    transition: background 160ms ease, transform 160ms ease;
    text-align: center;
    width: 100%;
    /* Required so touch pointermove on a tile delivers events to JS for the
       long-press drag instead of being consumed by the scroller. */
    touch-action: none;
}
/* Snap-cell hint shown under the pointer while dragging in desktop mode. */
.os-desktop-drop-cell {
    position: absolute;
    pointer-events: none;
    border-radius: 10px;
    background: rgba(0,120,212,0.18);
    box-shadow: inset 0 0 0 2px var(--os-accent);
    transition: left 80ms ease, top 80ms ease;
    z-index: 7999;
}
.os-desktop-shortcut:hover { background: rgba(255,255,255,0.10); }
[data-theme="light"] .os-desktop-shortcut:hover { background: rgba(0,0,0,0.06); }
.os-desktop-shortcut:focus-visible { outline: 2px solid var(--os-accent); outline-offset: 2px; }
.os-desktop-shortcut.selected { background: rgba(0,120,212,0.22); box-shadow: inset 0 0 0 2px var(--os-accent); }
.os-desktop-shortcut.stale { opacity: 0.55; }

.os-desktop-icon {
    width: 48px; height: 48px;
    display: inline-flex; align-items: center; justify-content: center;
    color: #fff;
}
.os-desktop-icon svg, .os-desktop-icon img { width: 40px; height: 40px; }

.os-desktop-label {
    font-size: 12px;
    line-height: 1.25;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,0.55);
    background: rgba(0,0,0,0.22);
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    padding: 1px 6px;
    border-radius: 6px;
    max-width: 100%;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    text-overflow: ellipsis;
    word-break: break-word;
}
[data-theme="light"] .os-desktop-label { background: rgba(0,0,0,0.36); }

.os-desktop-empty {
    grid-column: 1 / -1;
    align-self: center;
    text-align: center;
    color: #fff;
    opacity: 0.72;
    text-shadow: 0 1px 2px rgba(0,0,0,0.65);
    font-size: 13px;
    margin: 0;
}

@media (prefers-reduced-motion: reduce) {
    .os-desktop-shortcut { transition: none; }
}

/* Paged variant — tablet & phone (`body.os-mode-tablet`, `body.os-mode-phone`).
   Horizontal scroll-snap carousel with one grid per page. */
body.os-mode-tablet .os-desktop-icons.paged,
body.os-mode-phone  .os-desktop-icons.paged {
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    /* Reserve room at the bottom for the pager dots strip. */
    padding-bottom: 28px;
}
body.os-mode-tablet .os-desktop-page,
body.os-mode-phone  .os-desktop-page {
    flex: 0 0 100%;
    scroll-snap-align: center;
    scroll-snap-stop: always;
    display: grid;
    padding: 18px 18px 8px;
    gap: 14px 8px;
    align-content: start;
}
/* Phone: 4 cols × 5 rows = 20 tiles per page */
body.os-mode-phone .os-desktop-page  { grid-template-columns: repeat(4, 1fr); grid-auto-rows: 84px; }
/* Tablet portrait: 5×4 = 20; landscape: 6×4 = 24 (orientation handled by media query below) */
body.os-mode-tablet .os-desktop-page { grid-template-columns: repeat(5, 1fr); grid-auto-rows: 92px; }
@media (orientation: landscape) {
    body.os-mode-tablet .os-desktop-page { grid-template-columns: repeat(6, 1fr); }
}

/* Pager strip — dots above the taskbar */
.os-desktop-pager {
    position: absolute;
    left: 0; right: 0;
    bottom: 8px;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 8px;
    pointer-events: none; /* dots opt back in below */
}
body.os-mode-desktop .os-desktop-pager { display: none; }

.os-desktop-pager-dot {
    pointer-events: auto;
    width: 6px; height: 6px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255,255,255,0.45);
    cursor: pointer;
    transition: background 160ms ease, transform 160ms ease, width 160ms ease, height 160ms ease;
}
.os-desktop-pager-dot:hover { background: rgba(255,255,255,0.75); }
.os-desktop-pager-dot.active {
    width: 8px; height: 8px;
    background: var(--os-accent);
}
[data-theme="light"] .os-desktop-pager-dot { background: rgba(0,0,0,0.32); }
[data-theme="light"] .os-desktop-pager-dot:hover { background: rgba(0,0,0,0.55); }
@media (prefers-reduced-motion: reduce) {
    body.os-mode-tablet .os-desktop-icons.paged,
    body.os-mode-phone  .os-desktop-icons.paged { scroll-behavior: auto; }
    .os-desktop-pager-dot { transition: none; }
}

/* Paged tile gets a bit more room on touch — labels widen */
body.os-mode-tablet .os-desktop-shortcut .os-desktop-label,
body.os-mode-phone  .os-desktop-shortcut .os-desktop-label { font-size: 11.5px; }

/* Desktop drag & drop visuals */
body.os-desktop-dragging                       { cursor: grabbing; user-select: none; -webkit-user-select: none; }
body.os-desktop-dragging .os-desktop-shortcut  { transition: transform 160ms ease, opacity 120ms ease; }
.os-desktop-shortcut-dragging                  { opacity: 0.18; }
.os-desktop-shortcut-ghost                     { opacity: 0.88; transform: scale(1.04); box-shadow: 0 12px 28px rgba(0,0,0,0.45); border-radius: 12px; background: rgba(255,255,255,0.06); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
[data-theme="light"] .os-desktop-shortcut-ghost { background: rgba(0,0,0,0.04); }
.os-desktop-shortcut.os-desktop-drop-before { box-shadow: inset 3px 0 0 var(--os-accent); }
.os-desktop-shortcut.os-desktop-drop-after  { box-shadow: inset -3px 0 0 var(--os-accent); }

@media (prefers-reduced-motion: reduce) {
    body.os-desktop-dragging .os-desktop-shortcut { transition: none; }
}

/* Inline assistant — Phase 4. Positions the assistant UI as a native part
   of the desktop. The aside wrapper is pointer-events:none full-rect; only
   the actual visible UI children opt back into pointer-events:auto. This is
   the fix for the iframe-overlay tile-blocking bug captured in
   2026-05-14-desktop-drag-drop.md. */
#os-assistant {
    position: fixed;
    left: 0;
    bottom: var(--os-tb-height);
    width: 750px;
    height: min(820px, calc(100vh - var(--os-tb-height) - 16px));
    max-width: 100vw;
    /* Sits above the taskbar (z:10) so its drawer paints on top of it.
       Sits below windows (z:5+ but they're a sibling stacking context
       via .os-windows wrapper). */
    z-index: 11;
    pointer-events: none;   /* wrapper does not catch clicks */
}
/* Lift the bottom-stack above the taskbar so the drawer isn't hidden behind it. */
#os-assistant #bottom-stack {
    bottom: var(--os-tb-height) !important;
}
/* On phone/tablet the dock is taller than --os-tb-height (48px) and grows once
   Start/pins/tray lay out (plus the home-indicator safe-area on devices), so
   the drawer must rest on the dock's *measured* height — --os-dock-h, published
   live by shell.js — not the desktop bar height. Without this the drawer
   overlaps the dock by the 48px→dock-height difference. */
body.os-mode-phone #os-assistant #bottom-stack,
body.os-mode-tablet #os-assistant #bottom-stack {
    bottom: var(--os-dock-h, calc(60px + env(safe-area-inset-bottom, 0px))) !important;
}
#os-assistant.obstructed { display: none; }
/* Re-enable pointer events on the actual interactive children so users can
   click the visualizer, drawer, mic button. Empty space passes through to
   the desktop. The settings-panel and eq-panel are intentionally NOT in
   this list — voice.css manages their pointer-events via .open / [hidden]
   so they only catch clicks when actually visible. */
#os-assistant #bottom-stack,
#os-assistant header { pointer-events: auto; }
/* The visualizer is a large transparent canvas (472x200) anchored bottom-left.
   With pointer-events:auto it swallows touch-drags/scroll on app windows that
   sit under it (e.g. ForgeInbox on phone). Keep it purely visual — click-through.
   The drawer still opens via the "▸ text" toggle in the drawer bar. */
#os-assistant #visualizer { pointer-events: none !important; }

/* Override voice.php's body-keyed rules where they need to apply to the aside
   instead. voice.php uses `body.voice-mode-os-dock` selectors; we set that
   class on #os-assistant directly, so most rules already match via
   `.voice-mode-os-dock .descendant`. The exceptions are the few selectors
   that target `body.voice-mode-os-dock` itself — restated here against
   `#os-assistant`. */
#os-assistant {
    background: transparent;
    color: var(--os-fg, #f3f3f3);
}
