/* Sonaline for Windows: the web app's desktop mode (docs/desktop-native-web.md).
 *
 * Every rule here is under html.winapp, which desktop.js sets only when
 * the Windows app's bridge (window.sonalineDesktop) is on the page. In a
 * browser or on a phone none of it applies. It changes how what exists
 * looks and answers, never what is there: the things that give a web page
 * away (selectable labels, the hand cursor, pictures dragged out as ghosts,
 * a browser's focus ring after a click, its rubber band and scrollbars),
 * Windows 11's type, menus, hover and pressed looks in their place, and
 * the top bar as the window's title bar. */

/* ---- type: Windows 11's own face ----
 * Segoe UI Variable is what Windows 11 draws its own windows in (Text for
 * reading sizes, Display for the big ones); Windows 10 has only Segoe UI. */
:root.winapp {
  --ui: "Segoe UI Variable Text", "Segoe UI Variable", "Segoe UI", system-ui, sans-serif, "Segoe UI Emoji";
  --label: "Segoe UI Variable Text", "Segoe UI Variable", "Segoe UI", system-ui, sans-serif;
  /* Windows 11's pressed fill, a shade under its hover. */
  --win-pressed: color-mix(in srgb, var(--text) 4%, transparent);
  /* Windows 11's flyout: 8px corners, a soft two-part shadow. */
  --win-radius: 8px;
  --win-shadow: 0 8px 16px rgba(0, 0, 0, .14), 0 0 2px rgba(0, 0, 0, .12);
}
/* The room Windows' window buttons take at the top right. The shell
   defines it on html[data-sonaline-app] (docs/desktop-native.md, "The
   title bar"), and desktop.js sets it exactly from the window where it can;
   this is the fallback for a shell that does neither. */
:root.winapp:not([data-sonaline-app]) {
  --titlebar-inset-right: calc(100vw - env(titlebar-area-x, 0px) - env(titlebar-area-width, 100vw));
}
:root.winapp[data-theme="dark"], :root.winapp:not([data-theme]) {
  --win-shadow: 0 8px 16px rgba(0, 0, 0, .36), 0 0 2px rgba(0, 0, 0, .3);
}
@media (prefers-color-scheme: light) {
  :root.winapp:not([data-theme="dark"]) { --win-shadow: 0 8px 16px rgba(0, 0, 0, .14), 0 0 2px rgba(0, 0, 0, .12); }
}
:root.winapp body { font-family: var(--ui); }

/* ---- nothing selectable but words meant to be read or copied ----
 * Labels, buttons, rows and headings stay put under a drag, as in any
 * program. What stays selectable: what was typed (fields), a message's
 * text, a voicemail's words, and what the app already marks to copy
 * (keys, addresses, codes: their own user-select: all). */
:root.winapp body { -webkit-user-select: none; user-select: none; }
:root.winapp :is(input, textarea, [contenteditable]:not([contenteditable="false"])) {
  -webkit-user-select: text; user-select: text;
}
:root.winapp :is(.bubble, .bubble *, .transcript, .transcript *, .selectable, .selectable *) {
  -webkit-user-select: text; user-select: text;
}

/* ---- the arrow, not the hand ----
 * Windows programs point with the arrow at everything that is clicked:
 * buttons, rows, tabs, menu items. The I-beam stays over text to type in,
 * the hand only over a link inside a message's words, and the cursors that
 * say something (resize a pane, drag a grip, zoom a picture) keep theirs. */
:root.winapp *, :root.winapp *::before, :root.winapp *::after { cursor: default !important; }
:root.winapp :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="button"],
  [type="submit"], [type="reset"], [type="color"], [type="file"]), textarea,
  [contenteditable]:not([contenteditable="false"])) { cursor: text !important; }
:root.winapp :is(.bubble, .transcript) a[href] { cursor: pointer !important; }
:root.winapp :is(.split, .split *), :root.winapp body.splitting,
:root.winapp body.splitting * { cursor: col-resize !important; }
:root.winapp #lightbox img { cursor: zoom-in !important; }
:root.winapp .sdm-grip, :root.winapp #line-menu .hl-cal { cursor: grab !important; }
:root.winapp .sdm-grip:active { cursor: grabbing !important; }

/* ---- no ghosts ----
 * A picture, an icon or a link does not come away under the mouse
 * (desktop.js refuses the drag too, for what CSS cannot stop). */
:root.winapp :is(img, a, svg, video) { -webkit-user-drag: none; }

/* ---- the focus ring is for the keyboard ----
 * A click does not leave a ring on what was clicked; Tab still shows it,
 * in Windows' shape: two pixels, rounded, just outside the control. */
:root.winapp :focus:not(:focus-visible) { outline: none; }
:root.winapp :focus-visible { outline-offset: 1px; border-radius: 4px; }

/* ---- no rubber band, anywhere ----
 * A list stops at its end; it neither bounces nor drags the page under it. */
:root.winapp, :root.winapp body, :root.winapp * { overscroll-behavior: none; }

/* ---- Windows 11's scrollbars ----
 * A thin line with no arrows that thickens under the mouse, in the text's
 * colour. Lists that hide their bar until they scroll (.scroll-hints,
 * scrollhint.js) keep doing that, which is what Windows 11 does too. */
@media not (forced-colors: active) {
  :root.winapp *:not(.scroll-hints, .scroll-hints *) { scrollbar-width: auto; scrollbar-color: auto; }
  :root.winapp *:not(.scroll-hints, .scroll-hints *)::-webkit-scrollbar { width: 12px; height: 12px; background: transparent; }
  :root.winapp *::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
  :root.winapp *::-webkit-scrollbar-track, :root.winapp *::-webkit-scrollbar-corner { background: transparent; }
  :root.winapp *:not(.scroll-hints, .scroll-hints *)::-webkit-scrollbar-thumb {
    border: 4.5px solid transparent; border-radius: 6px; background-clip: padding-box;
    background-color: color-mix(in srgb, var(--text) 32%, transparent);
    min-height: 32px;
  }
  :root.winapp *:not(.scroll-hints, .scroll-hints *)::-webkit-scrollbar-thumb:hover,
  :root.winapp *:not(.scroll-hints, .scroll-hints *)::-webkit-scrollbar-thumb:active {
    border-width: 3px; background-color: color-mix(in srgb, var(--text) 48%, transparent);
  }
}

/* ---- menus and flyouts: Windows 11's ----
 * 8px corners, the flyout's shadow, a hair of border, items inset from the
 * edge with their own rounded hover, and the flyout's entrance: a short
 * fade with a few pixels of travel. */
:root.winapp .menu {
  border-radius: var(--win-radius); box-shadow: var(--win-shadow);
  padding: 4px 0;
}
:root.winapp .menu:not(.hidden) { animation: winapp-flyout 167ms cubic-bezier(0, 0, 0, 1); }
:root.winapp .menu .item {
  width: calc(100% - 8px); margin: 0 4px; border-radius: 4px;
  min-height: 44px; transition: background-color 83ms linear;
}
:root.winapp .menu .item:not(:disabled):active { background: var(--win-pressed); }
@keyframes winapp-flyout {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  :root.winapp .menu:not(.hidden) { animation: none; }
}
:root.winapp dialog { border-radius: var(--win-radius); }
:root.winapp dialog::backdrop { transition: none; }
:root.winapp .toast { border-radius: var(--win-radius); box-shadow: var(--win-shadow); }

/* ---- hover and pressed: Windows' ----
 * A hover fills quietly; a press fills a shade lighter, at once (no
 * fading in, no ripple), and nothing shrinks or grows under the mouse. */
:root.winapp :is(.row, .callrow, .vmrow, .contactrow) { transition: background-color 83ms linear; }
:root.winapp :is(.row, .callrow, .vmrow, .contactrow):not([aria-selected="true"]):not(.selected):active {
  background: var(--win-pressed);
}
:root.winapp :is(.icon-btn, .rowdots):not(:disabled):active { background: var(--win-pressed); }
:root.winapp :is(button, .btn, [role="button"], [role="tab"]):not(:disabled):active { transform: none; }
:root.winapp * { -webkit-tap-highlight-color: transparent; }

/* ---- the top bar is the title bar ----
 * The app draws no title bar of its own: the page's top bar is where the
 * window is dragged from (and double-clicked to maximise), and Windows'
 * buttons sit over its right end, so the bar keeps room for them. Every
 * control in the bar stays clickable (no-drag). While a menu or a dialog
 * is open the bar stops being a drag area, so nothing laid over it is
 * swallowed by the window's drag. */
:root.winapp #app > header.bar {
  -webkit-app-region: drag; app-region: drag;
  /* A narrow window: the bar is the pill, moved in from the buttons with
     12px to spare (0 where there are no buttons over the page). */
  margin-right: min(calc(var(--titlebar-inset-right, 0px) * 100), calc(var(--titlebar-inset-right, 0px) + 12px));
}
@media (min-width: 840px) {
  :root.winapp #app > header.bar { margin-right: 0; padding-right: calc(var(--titlebar-inset-right, 0px) + 24px); }
}
:root.winapp #app > header.bar :is(button, a, input, select, textarea, label, [role="button"],
  [role="menu"], [tabindex], .menu, .bar-right > *) {
  -webkit-app-region: no-drag; app-region: no-drag;
}
:root.winapp:has(dialog[open], .menu:not(.hidden)) #app > header.bar {
  -webkit-app-region: no-drag; app-region: no-drag;
}

/* ---- "Reconnecting" without flicker ----
 * Just woken from sleep, until the live channel and the phone are back,
 * the app says "Reconnecting"
 * in the top bar (app.js deskReconnecting). A program
 * does not flash a word for the half second a reconnection takes: the
 * word shows only once the wait has gone on for a second and a half,
 * then fades in; a reconnection quicker than that is never seen. */
:root.winapp #wake-chip:not(.hidden) {
  animation: winapp-late 1700ms linear both;
}
@keyframes winapp-late {
  0%, 88% { opacity: 0; visibility: hidden; }
  100% { opacity: 1; visibility: visible; }
}

/* ---- a narrow window ----
 * Under 840px the app is one column, as on a phone, and an open
 * conversation, person or new message fills it with its own head at the
 * top, where the app's bar was. That head is then the title bar: the
 * window is dragged by it, its buttons stay clickable, and it keeps the
 * same room for Windows' buttons at its right. */
@media (max-width: 839.98px) {
  :root.winapp :is(.thread-head, .pane-head, .nc-head, .cd-top) {
    -webkit-app-region: drag; app-region: drag;
    margin-right: min(calc(var(--titlebar-inset-right, 0px) * 100), calc(var(--titlebar-inset-right, 0px) + 12px));
  }
  :root.winapp :is(.thread-head, .pane-head, .nc-head, .cd-top) :is(button, a, input, select, textarea, label,
    [role="button"], [tabindex], .menu) {
    -webkit-app-region: no-drag; app-region: no-drag;
  }
  :root.winapp:has(dialog[open], .menu:not(.hidden)) :is(.thread-head, .pane-head, .nc-head, .cd-top) {
    -webkit-app-region: no-drag; app-region: no-drag;
  }
}
