: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); }

/* DataForge credit. Same pill vocabulary as the temperature so the tray reads as
   one row; only the status colours differ in meaning. */
.os-tokens-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-tokens[data-status="low"]   .os-tokens-pill { background: rgba(255, 170, 50, 0.18); border-color: rgba(255, 170, 50, 0.5); }
.os-tray-tokens[data-status="empty"] .os-tokens-pill { background: rgba(220, 60, 60, 0.22); border-color: rgba(220, 60, 60, 0.6); }
.os-tray-tokens[data-status="error"] .os-tokens-pill { opacity: 0.55; }

/* Update-available marker. A dot, not a count: there is only ever one
   pending version, so a number would say nothing a dot does not. The button is
   hidden entirely unless an update is waiting, so this is only ever visible
   when it means something. */
.os-tray-update { position: relative; }
.os-tray-dot {
    position: absolute;
    top: 5px;
    right: 5px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--os-accent);
    box-shadow: 0 0 0 2px var(--os-tb-bg, rgba(0, 0, 0, 0.35));
}

.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;
    /* Digits sit on the flyout PANEL (OS-themed), not on the clock face, so
       colour them with the OS foreground var: this makes them follow the OS
       light/dark toggle like every other element, instead of the clock-face
       var (--osc-hand) which only tracks the clock's own Light/Dark button. */
    color: var(--os-fg);
    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(--os-fg-muted);
    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; }

/* ── App Categorisation Engine: Start menu sections ──────────────────────
   Only active when .os-sm-all carries .categorised; the legacy flat list is
   untouched so engine-off parity is structural, not just tested. */
.os-sm-all.categorised > li.os-sm-cat { margin: 0 0 2px; }

.os-sm-cat-head {
    appearance: none;
    width: 100%;
    background: transparent;
    border: 0;
    color: var(--os-fg-muted);
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: var(--os-radius-sm);
    cursor: pointer;
    text-align: left;
    font: inherit;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
.os-sm-cat-head:hover { background: rgba(255, 255, 255, 0.06); color: var(--os-fg); }
.os-sm-cat-head:focus-visible { outline: 2px solid var(--os-accent, #0078d4); outline-offset: -2px; }

.os-sm-cat-chevron {
    display: inline-block;
    flex-shrink: 0;
    width: 10px;
    font-size: 13px;
    line-height: 1;
    transform: rotate(90deg);
    transition: transform 140ms ease;
}
.os-sm-cat.collapsed > .os-sm-cat-head .os-sm-cat-chevron { transform: rotate(0deg); }

.os-sm-cat-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.os-sm-cat-count {
    flex-shrink: 0;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0;
    padding: 1px 6px;
    border-radius: 9px;
    background: rgba(255, 255, 255, 0.10);
    color: var(--os-fg-muted);
}

.os-sm-cat-body { list-style: none; margin: 0 0 6px; padding: 0; }
.os-sm-cat-body .os-sm-row { padding-left: 18px; }

/* The system drawer reads as a separator, not a peer of the real categories. */
.os-sm-cat-drawer {
    margin-top: 8px !important;
    padding-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}

:root[data-theme="light"] .os-sm-cat-head:hover { background: rgba(0, 0, 0, 0.05); }
:root[data-theme="light"] .os-sm-cat-count { background: rgba(0, 0, 0, 0.08); }
:root[data-theme="light"] .os-sm-cat-drawer { border-top-color: rgba(0, 0, 0, 0.10); }

.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: var(--os-radius-sm);
    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: rgba(255,255,255,0.06);
    border: 1px solid var(--os-surface-border);
    color: var(--os-fg);
}
.os-tb-assistant-mini-mic.mic-idle:hover { background: rgba(255,255,255,0.12); }
.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);
}
/* ── App Categorisation Engine: category edit mode (PRD §6.2) ────────────
   Only active while #os-startmenu carries .cat-editing. */

.os-sm-editbar {
    display: none;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    margin-bottom: 6px;
    border-radius: var(--os-radius-sm);
    background: rgba(0, 120, 212, 0.14);
    border: 1px solid rgba(0, 120, 212, 0.35);
    font-size: 11px;
}
#os-startmenu.cat-editing .os-sm-editbar { display: flex; }
.os-sm-editbar-status { flex: 1; min-width: 0; color: var(--os-fg); }
.os-sm-editbar button {
    appearance: none;
    border: 1px solid rgba(255, 255, 255, 0.18);
    background: transparent;
    color: var(--os-fg);
    font: inherit;
    font-size: 11px;
    padding: 3px 9px;
    border-radius: 6px;
    cursor: pointer;
}
.os-sm-editbar button:hover:not(:disabled) { background: rgba(255, 255, 255, 0.10); }
.os-sm-editbar button:disabled { opacity: 0.4; cursor: default; }
.os-sm-editbar button[data-cat-done] { background: var(--os-accent, #0078d4); border-color: transparent; color: #fff; }

/* Rows become grabbable and show provenance. */
#os-startmenu.cat-editing .os-sm-row { cursor: grab; }
#os-startmenu.cat-editing .os-sm-row:active { cursor: grabbing; }
.os-sm-row-pin {
    margin-left: auto;
    flex-shrink: 0;
    font-size: 10px;
    opacity: 0.75;
    display: none;
}
#os-startmenu.cat-editing .os-sm-row.anchored .os-sm-row-pin { display: inline; }

/* Drop targets. */
#os-startmenu.cat-editing .os-sm-cat { border-radius: var(--os-radius-sm); }
#os-startmenu.cat-editing .os-sm-cat.drop-target {
    outline: 2px dashed var(--os-accent, #0078d4);
    outline-offset: -2px;
    background: rgba(0, 120, 212, 0.10);
}
.os-sm-row.os-sm-row-dragging { opacity: 0.35; }
.os-sm-row-ghost {
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
    background: var(--os-surface, #202020);
    border-radius: var(--os-radius-sm);
    opacity: 0.95;
}

/* The "new category" and "reset to rule" drop zones only exist in edit mode. */
.os-sm-dropzones { display: none; gap: 6px; margin: 6px 0 2px; }
#os-startmenu.cat-editing .os-sm-dropzones { display: flex; }
.os-sm-dropzone {
    flex: 1;
    text-align: center;
    padding: 7px 6px;
    font-size: 10px;
    border: 1px dashed rgba(255, 255, 255, 0.25);
    border-radius: var(--os-radius-sm);
    color: var(--os-fg-muted);
}
.os-sm-dropzone.drop-target {
    border-color: var(--os-accent, #0078d4);
    background: rgba(0, 120, 212, 0.14);
    color: var(--os-fg);
}

:root[data-theme="light"] .os-sm-editbar button { border-color: rgba(0, 0, 0, 0.18); }
:root[data-theme="light"] .os-sm-dropzone { border-color: rgba(0, 0, 0, 0.22); }
:root[data-theme="light"] .os-sm-row-ghost { background: #fff; }

/* Edit-categories affordance in the "All apps" heading. Scoped to that heading
   only: .os-sm-section-head is shared with "Pinned", which must not change. */
.os-sm-section-head[data-os-sm-all-head] { display: flex; align-items: center; gap: 6px; }
.os-sm-edit-cats {
    appearance: none;
    margin-left: auto;
    background: transparent;
    border: 0;
    color: inherit;
    opacity: 0.55;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
    padding: 2px 4px;
    border-radius: 4px;
}
.os-sm-edit-cats:hover { opacity: 1; background: rgba(255, 255, 255, 0.10); }
#os-startmenu.cat-editing .os-sm-edit-cats { opacity: 1; color: var(--os-accent, #0078d4); }
:root[data-theme="light"] .os-sm-edit-cats:hover { background: rgba(0, 0, 0, 0.07); }

/* ── App Categorisation Engine: management pane (PRD §6.4) ─────────────────
   Scoped tokens rather than rgba() guesses. The pane sits on its own opaque
   surface, so every colour is stated per theme instead of relying on whatever
   happens to be behind it. Light values follow the usual accessible ramp
   (#0f172a text, #475569 muted, #e2e8f0 borders) so contrast clears 4.5:1.

   NOTE: use div, never <header>/<footer>, inside this pane. apps/assistant/
   voice.css styles bare `header` globally and it is loaded into /os/, which
   silently painted this dialog's title bar near-black. */
.os-catman {
    --cm-bg:         #1b1b1b;
    --cm-fg:         #f3f3f3;
    --cm-muted:      rgba(243, 243, 243, 0.72);
    --cm-line:       rgba(255, 255, 255, 0.14);
    --cm-col:        rgba(255, 255, 255, 0.05);
    --cm-card:       rgba(255, 255, 255, 0.10);
    --cm-card-hover: rgba(255, 255, 255, 0.18);
    --cm-field:      rgba(255, 255, 255, 0.08);
    --cm-danger:     #ff7b72;

    position: fixed; inset: 0; z-index: 9000;
    display: flex; align-items: center; justify-content: center;
}
:root[data-theme="light"] .os-catman {
    --cm-bg:         #ffffff;
    --cm-fg:         #0f172a;
    --cm-muted:      #475569;
    --cm-line:       #e2e8f0;
    --cm-col:        #f1f5f9;
    --cm-card:       #ffffff;
    --cm-card-hover: #e2e8f0;
    --cm-field:      #ffffff;
    --cm-danger:     #b91c1c;
}
.os-catman[hidden] { display: none; }
.os-catman-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); }

.os-catman-panel {
    position: relative;
    width: min(920px, 92vw);
    height: min(640px, 86vh);
    display: flex; flex-direction: column;
    background: var(--cm-bg);
    color: var(--cm-fg);
    border: 1px solid var(--cm-line);
    border-radius: 12px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
    overflow: hidden;
}

.os-catman-head {
    display: flex; align-items: center;
    padding: 12px 14px;
    background: var(--cm-bg);
    color: var(--cm-fg);
    border-bottom: 1px solid var(--cm-line);
}
.os-catman-head h2 { margin: 0; font-size: 14px; font-weight: 600; flex: 1; color: var(--cm-fg); }
.os-catman-x {
    appearance: none; background: transparent; border: 0;
    color: var(--cm-fg); font-size: 22px; line-height: 1; cursor: pointer;
    width: 32px; height: 32px; border-radius: 6px;
    display: inline-flex; align-items: center; justify-content: center;
}
.os-catman-x:hover { background: var(--cm-card-hover); }
.os-catman-x:focus-visible { outline: 2px solid var(--os-accent, #0078d4); outline-offset: 2px; }

.os-catman-tabs { display: flex; gap: 2px; padding: 8px 10px 0; border-bottom: 1px solid var(--cm-line); }
.os-catman-tabs button {
    appearance: none; background: transparent; border: 0;
    border-bottom: 2px solid transparent;
    color: var(--cm-muted); font: inherit; font-size: 12px;
    padding: 7px 12px; cursor: pointer; border-radius: 6px 6px 0 0;
    transition: color 160ms ease, background-color 160ms ease;
}
.os-catman-tabs button:hover { color: var(--cm-fg); background: var(--cm-col); }
.os-catman-tabs button[aria-selected="true"] { color: var(--cm-fg); border-bottom-color: var(--os-accent, #0078d4); }
.os-catman-tabs button:focus-visible { outline: 2px solid var(--os-accent, #0078d4); outline-offset: -2px; }

.os-catman-body { flex: 1; min-height: 0; overflow: auto; padding: 12px 14px; }
.os-catman-pane[hidden] { display: none; }

.os-catman-foot {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 14px;
    border-top: 1px solid var(--cm-line);
    background: var(--cm-bg);
}
.os-catman-msg { flex: 1; font-size: 11px; color: var(--cm-muted); }
.os-catman-msg.bad { color: var(--cm-danger); font-weight: 600; }
.os-catman-foot button, .os-catman-add {
    appearance: none; background: transparent;
    border: 1px solid var(--cm-line);
    color: var(--cm-fg); font: inherit; font-size: 12px;
    padding: 6px 12px; border-radius: 6px; cursor: pointer;
    transition: background-color 160ms ease;
}
.os-catman-foot button:hover, .os-catman-add:hover { background: var(--cm-card-hover); }
.os-catman-foot button:focus-visible, .os-catman-add:focus-visible { outline: 2px solid var(--os-accent, #0078d4); outline-offset: 2px; }
.os-catman-foot button.danger { border-color: var(--cm-danger); color: var(--cm-danger); }

/* ── Board: wraps, never scrolls sideways ───────────────────────────────── */
.os-catman-board { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-start; }
.os-catman-col {
    flex: 1 1 200px; max-width: 240px;
    background: var(--cm-col);
    border: 1px solid transparent;
    border-radius: 8px; padding: 8px;
    transition: background-color 140ms ease, border-color 140ms ease;
}
.os-catman-col.drop-target { border-color: var(--os-accent, #0078d4); background: rgba(0, 120, 212, 0.12); }
.os-catman-col-head { font-size: 11px; font-weight: 700; margin-bottom: 8px; color: var(--cm-muted); letter-spacing: 0.03em; }
.os-catman-col-list { display: flex; flex-direction: column; gap: 5px; min-height: 34px; }
.os-catman-card {
    display: flex; align-items: center; gap: 6px;
    background: var(--cm-card);
    border: 1px solid var(--cm-line);
    color: var(--cm-fg);
    border-radius: 6px; padding: 7px 9px; font-size: 12px;
    cursor: grab; user-select: none;
    transition: background-color 140ms ease, border-color 140ms ease;
}
.os-catman-card:hover { background: var(--cm-card-hover); }
.os-catman-card:active { cursor: grabbing; }
.os-catman-card.os-catman-card-dragging { opacity: 0.35; }
.os-catman-card-ghost {
    background: var(--cm-card); color: var(--cm-fg);
    border: 1px solid var(--os-accent, #0078d4); border-radius: 6px;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.4); opacity: 0.95;
}
.os-catman-pin { margin-left: auto; font-size: 10px; color: var(--os-accent, #0078d4); }
.os-catman-board-hint { font-size: 11px; color: var(--cm-muted); margin: 0 0 10px; }

/* ── Categories tab ─────────────────────────────────────────────────────── */
.os-catman-cats { display: flex; flex-direction: column; gap: 6px; }
.os-catman-cat { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.os-catman-cat input[type="text"] { flex: 1 1 160px; min-width: 0; }
.os-catman-cat input, .os-catman-cat select {
    background: var(--cm-field); border: 1px solid var(--cm-line);
    color: var(--cm-fg); border-radius: 6px; padding: 6px 8px; font: inherit; font-size: 12px;
}
.os-catman-cat input:focus-visible, .os-catman-cat select:focus-visible,
.os-catman-rule select:focus-visible { outline: 2px solid var(--os-accent, #0078d4); outline-offset: 1px; }
.os-catman-cat .c-sort { width: 74px; }
.os-catman-cat .c-flag { font-size: 11px; display: flex; align-items: center; gap: 5px; white-space: nowrap; color: var(--cm-fg); cursor: pointer; }
.os-catman-cat .c-del {
    appearance: none; background: transparent; border: 1px solid var(--cm-danger);
    color: var(--cm-danger); font: inherit; font-size: 11px;
    padding: 5px 10px; border-radius: 6px; cursor: pointer;
}
.os-catman-cat .c-del:disabled { opacity: 0.4; cursor: not-allowed; }
.os-catman-add { margin-top: 10px; }

/* ── Rules tab ──────────────────────────────────────────────────────────── */
.os-catman-hint { font-size: 11px; color: var(--cm-muted); margin: 0 0 10px; }
.os-catman-rules { list-style: decimal inside; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.os-catman-rule {
    display: flex; align-items: center; gap: 8px;
    background: var(--cm-col); border: 1px solid var(--cm-line);
    border-radius: 6px; padding: 6px 9px;
}
.os-catman-rule select {
    background: var(--cm-field); border: 1px solid var(--cm-line);
    color: var(--cm-fg); border-radius: 6px; padding: 4px 6px; font: inherit; font-size: 11px;
}
.os-catman-rule .r-preds { flex: 1; min-width: 0; font-size: 11px; color: var(--cm-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.os-catman-rule button {
    appearance: none; background: transparent; border: 1px solid var(--cm-line);
    color: var(--cm-fg); border-radius: 6px; width: 28px; height: 26px;
    font-size: 12px; cursor: pointer; padding: 0;
}
.os-catman-rule button:hover:not(:disabled) { background: var(--cm-card-hover); }
.os-catman-rule button:disabled { opacity: 0.35; cursor: not-allowed; }
.os-catman-rule .r-del { border-color: var(--cm-danger); color: var(--cm-danger); }

/* ── Preview tab ────────────────────────────────────────────────────────── */
.os-catman-preview { width: 100%; border-collapse: collapse; font-size: 12px; color: var(--cm-fg); }
.os-catman-preview th {
    text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--cm-muted); padding: 6px; border-bottom: 1px solid var(--cm-line);
}
.os-catman-preview td { padding: 6px; border-bottom: 1px solid var(--cm-line); }
.os-catman-preview .why { font-size: 11px; color: var(--cm-muted); }
.os-catman-preview .why.via-override { color: var(--os-accent, #0078d4); font-weight: 600; }
.os-catman-preview .why.via-fallback { color: #b45309; font-weight: 600; }
:root[data-theme="dark"] .os-catman-preview .why.via-fallback { color: #e3b341; }

/* ── Desktop category folders (Phase 7) ─────────────────────────────────── */
.os-folder-icon {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 2px;
    width: 100%; height: 100%;
    padding: 3px;
    border-radius: 8px;
    background: rgba(255, 255, 255, 0.14);
}
.os-folder-cell {
    display: flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, #4a8be6, #2563c4);
    color: #fff; border-radius: 3px;
    font-size: 7px; font-weight: 700; line-height: 1;
    overflow: hidden;
}
.os-folder-pop {
    position: fixed;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    z-index: 8500;
    width: min(460px, 88vw);
    max-height: 70vh;
    overflow: auto;
    background: var(--os-surface, #1b1b1b);
    color: var(--os-fg);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 12px;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
    padding: 12px;
}
.os-folder-pop-head { font-size: 12px; font-weight: 600; margin-bottom: 10px; }
.os-folder-pop-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.os-folder-app {
    appearance: none; background: transparent; border: 0; color: inherit;
    display: flex; flex-direction: column; align-items: center; gap: 5px;
    padding: 8px 4px; border-radius: 8px; cursor: pointer; font: inherit; font-size: 11px;
    text-align: center;
}
.os-folder-app:hover { background: rgba(255, 255, 255, 0.08); }
.os-folder-app span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; width: 100%; }
.os-folder-empty { grid-column: 1 / -1; font-size: 11px; opacity: 0.6; margin: 0; }
:root[data-theme="light"] .os-folder-pop { background: #fff; border-color: rgba(0,0,0,0.12); }
:root[data-theme="light"] .os-folder-icon { background: rgba(0, 0, 0, 0.10); }
:root[data-theme="light"] .os-folder-app:hover { background: rgba(0, 0, 0, 0.06); }

/* DataForge account flyout. Reuses .os-flyout chrome; only the inner rows are new. */
.os-tokens-flyout { min-width: 320px; max-width: 380px; }
.os-tokens-body { padding: 4px 0; max-height: 60vh; overflow-y: auto; }
.os-tokens-cred {
    padding: 10px 14px;
    border-bottom: 1px solid var(--os-surface-border);
}
.os-tokens-cred:last-child { border-bottom: 0; }
.os-tokens-cred-head { display: flex; align-items: center; gap: 8px; }
.os-tokens-label { font-size: 12px; font-weight: 600; }
.os-tokens-active {
    font-size: 9px; letter-spacing: 0.08em; padding: 1px 5px; border-radius: 3px;
    background: var(--os-accent); color: #fff;
}
.os-tokens-figure { font-size: 18px; font-variant-numeric: tabular-nums; margin-top: 2px; }
.os-tokens-sub  { font-size: 11px; opacity: 0.7; margin-top: 3px; line-height: 1.5; }
.os-tokens-acct { font-size: 10px; opacity: 0.5; margin-top: 4px; }
.os-tokens-err  { font-size: 13px; opacity: 0.6; }
.os-tokens-bar {
    margin-top: 5px; height: 4px; border-radius: 2px;
    background: rgba(255,255,255,0.12); overflow: hidden;
}
.os-tokens-bar > i { display: block; height: 100%; background: var(--os-accent); }
.os-tokens-stamp { padding: 6px 14px 2px; font-size: 10px; opacity: 0.45; }
.os-tokens-actions {
    display: flex; gap: 8px; padding: 10px 14px;
    border-top: 1px solid var(--os-surface-border);
}
.os-tokens-btn {
    flex: 1; text-align: center; text-decoration: none;
    font-size: 11px; padding: 6px 8px; border-radius: 6px;
    border: 1px solid var(--os-surface-border);
    color: inherit; background: rgba(255,255,255,0.06);
}
.os-tokens-btn:hover { background: rgba(255,255,255,0.12); }

.os-tokens-rowacts { display: flex; gap: 6px; margin-top: 8px; }
.os-tokens-connect { padding: 10px 14px; border-top: 1px solid var(--os-surface-border); }
.os-tokens-connect-form { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
/* A light overlay, like .os-sm-search: NOT a dark fill. A heavy dark fill
   reads as a disabled control on the light theme, which is exactly what these
   are not. */
.os-tokens-connect-form input {
    font: inherit; font-size: 11px; padding: 7px 9px; border-radius: 6px;
    border: 1px solid var(--os-surface-border);
    background: rgba(255, 255, 255, 0.08);
    color: var(--os-fg);
}
.os-tokens-connect-form input::placeholder { color: var(--os-fg-muted); }
.os-tokens-connect-form input:focus {
    outline: none;
    border-color: var(--os-accent);
    background: rgba(255, 255, 255, 0.14);
}
:root[data-theme="light"] .os-tokens-connect-form input {
    background: #fff;
    border-color: rgba(0, 0, 0, 0.22);
}
:root[data-theme="light"] .os-tokens-connect-form input:focus {
    border-color: var(--os-accent);
    background: #fff;
}
.os-tokens-mini {
    font: inherit; font-size: 11px; padding: 4px 10px; border-radius: 6px;
    border: 1px solid var(--os-surface-border);
    background: rgba(255,255,255,0.06); color: inherit; cursor: pointer;
}
.os-tokens-mini:hover:not(:disabled) { background: rgba(255,255,255,0.14); }
.os-tokens-mini:disabled { opacity: 0.5; cursor: default; }
.os-tokens-mini.danger:hover:not(:disabled) { background: rgba(220,60,60,0.25); border-color: rgba(220,60,60,0.6); }
.os-tokens-msg { font-size: 11px; opacity: 0.75; }
.os-tokens-msg.bad { color: #ff8f8f; opacity: 1; }

.os-tokens-apps { padding: 10px 14px; border-top: 1px solid var(--os-surface-border); }
.os-tokens-apps-head { font-size: 10px; letter-spacing: 0.06em; opacity: 0.6; margin-bottom: 6px; text-transform: uppercase; }
.os-tokens-assign { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 5px; font-size: 11px; }
.os-tokens-assign select {
    font: inherit; font-size: 11px; padding: 3px 6px; border-radius: 5px; max-width: 58%;
    border: 1px solid var(--os-surface-border);
    background: rgba(255, 255, 255, 0.08); color: var(--os-fg);
}
:root[data-theme="light"] .os-tokens-assign select {
    background: #fff; border-color: rgba(0, 0, 0, 0.22);
}

/* [hidden] has to beat the display rule on .os-tray-btn above: an author class
   selector outranks the UA's [hidden] { display: none }, so without this the
   attribute is inert and the button stays on screen. The same guard already
   exists for .os-flyout, .os-startmenu, .os-snap-overlay and .os-altswitch -
   I simply forgot it for the tray, and a box with no credential showed the
   icon anyway. */
.os-tray-btn[hidden],
.os-tray-popover-item[hidden] { display: none; }

.os-tray-tokens[data-status="signed-out"] .os-tokens-pill { opacity: 0.55; }

.os-tokens-mini.primary { background: var(--os-accent); border-color: var(--os-accent); color: #fff; font-weight: 600; }
.os-tokens-mini.primary:hover:not(:disabled) { filter: brightness(1.1); background: var(--os-accent); }
.os-tokens-link {
    appearance: none; background: none; border: 0; padding: 8px 0 0;
    color: var(--os-fg-muted); font: inherit; font-size: 11px;
    text-decoration: underline; cursor: pointer;
}
.os-tokens-link:hover { color: var(--os-fg); }

/* Same trap as .os-tray-btn: this rule sets display, so it outranks the UA's
   [hidden] and the collapsed form stayed on screen. Guard every element in this
   panel that is toggled by the attribute. */
.os-tokens-connect-form[hidden],
.os-tokens-msg[hidden],
.os-tokens-apps[hidden] { display: none; }

.os-tokens-chips { display: flex; gap: 5px; margin-top: 7px; }
.os-tokens-chip {
    font-size: 9px; letter-spacing: 0.05em; text-transform: uppercase;
    padding: 2px 6px; border-radius: 3px;
    border: 1px solid var(--os-surface-border); background: rgba(255,255,255,0.07);
}
.os-tokens-chip.off { opacity: 0.35; text-decoration: line-through; }
:root[data-theme="light"] .os-tokens-chip { background: rgba(0,0,0,0.05); }

/* ── Start menu folder shelf + drill-in view ─────────────────────────────── */
/* Wraps, no scrollbar. Folders are sized to their label rather than forced into
   fixed columns, so a curated handful packs onto one or two rows. Nothing is ever
   hidden off to the side, which a horizontal scroller does. */
.os-sm-folders {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.os-sm-folders > .os-sm-folder { flex: 0 1 auto; max-width: 100%; }

/* Edit mode is about rearranging the list, so the shelf steps aside there and
   gives its height back. */
#os-startmenu.cat-editing .os-sm-folders-section { display: none; }
.os-sm-folder {
    appearance: none;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid transparent;
    border-radius: var(--os-radius-sm);
    color: var(--os-fg);
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 9px;
    cursor: pointer;
    font: inherit;
    font-size: 12px;
    text-align: left;
    min-width: 0;
}
.os-sm-folder:hover { background: rgba(255, 255, 255, 0.10); }
.os-sm-folder:focus-visible { outline: 2px solid var(--os-accent, #0078d4); outline-offset: -2px; }
.os-sm-folder .os-folder-icon { width: 30px; height: 30px; flex-shrink: 0; }
.os-sm-folder .os-folder-cell { font-size: 7px; }
.os-sm-folder-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.os-sm-folder-count {
    flex-shrink: 0;
    font-size: 10px;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 9px;
    background: rgba(255, 255, 255, 0.10);
    color: var(--os-fg-muted);
}

/* While a folder is open the rest of the menu steps aside. */
#os-startmenu.folder-open .os-sm-folders-section,
#os-startmenu.folder-open .os-sm-section,
#os-startmenu.folder-open .os-sm-editbar,
#os-startmenu.folder-open .os-sm-dropzones { display: none; }
#os-startmenu.folder-open .os-sm-search { display: none; }

.os-sm-folderview {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}
.os-sm-folderview[hidden] { display: none; }

.os-sm-fv-back {
    appearance: none;
    background: transparent;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    color: var(--os-fg);
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 6px;
    margin-bottom: 6px;
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    text-align: left;
}
.os-sm-fv-back:hover { background: rgba(255, 255, 255, 0.06); }
.os-sm-fv-back span[aria-hidden] { font-size: 18px; line-height: 1; opacity: 0.7; }
.os-sm-fv-count {
    margin-left: auto;
    font-size: 11px;
    font-weight: 500;
    color: var(--os-fg-muted);
}

.os-sm-fv-list {
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    flex: 1;
    min-height: 0;
}
.os-sm-fv-row {
    appearance: none;
    width: 100%;
    background: transparent;
    border: 0;
    color: var(--os-fg);
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 9px 8px;
    border-radius: var(--os-radius-sm);
    cursor: pointer;
    font: inherit;
    text-align: left;
}
.os-sm-fv-row:hover { background: rgba(255, 255, 255, 0.08); }
.os-sm-fv-row:focus-visible { outline: 2px solid var(--os-accent, #0078d4); outline-offset: -2px; }

/* The bigger icon is the point of this view. */
.os-sm-fv-icon { flex-shrink: 0; }
.os-sm-fv-icon .os-app-tile-icon {
    width: 40px; height: 40px;
    border-radius: 9px;
    font-size: 15px;
    display: inline-flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, #4a8be6, #2563c4);
    color: #fff; font-weight: 700;
}
.os-sm-fv-icon .os-app-tile-icon img { width: 30px; height: 30px; }

.os-sm-fv-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.os-sm-fv-name { font-size: 13px; font-weight: 600; }
.os-sm-fv-desc {
    font-size: 11px;
    line-height: 1.45;
    color: var(--os-fg-muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

:root[data-theme="light"] .os-sm-folder { background: rgba(0, 0, 0, 0.04); }
:root[data-theme="light"] .os-sm-folder:hover { background: rgba(0, 0, 0, 0.08); }
:root[data-theme="light"] .os-sm-folder-count { background: rgba(0, 0, 0, 0.08); }
:root[data-theme="light"] .os-sm-fv-back { border-bottom-color: rgba(0, 0, 0, 0.10); }
:root[data-theme="light"] .os-sm-fv-back:hover { background: rgba(0, 0, 0, 0.05); }
:root[data-theme="light"] .os-sm-fv-row:hover { background: rgba(0, 0, 0, 0.06); }
