@import url("../icons/v1.css?v=6");

/* ALYSSIUN OS — host-page atmosphere styles for the shared launcher.
 *
 * These rules style the *host application's* document (not the launcher's own
 * shadow DOM, which lives in v1.css). They ship as a real stylesheet rather
 * than an injected <style> block because apps with a strict `style-src` (no
 * 'unsafe-inline' — see alyssiun-foundation) block inline stylesheets outright,
 * which silently dropped the launcher clearance and atmosphere variables there.
 * Every app that embeds the launcher already allows https://alyssiun.com in
 * style-src, so one linked file works under the strictest policy we ship. */

html {
  /* Published by the launcher script (v1.js) once the OS bottom bar mounts:
     the bar's reserved height, or 0px while it is not on screen. This is the
     one channel for the bar's size, and the ONLY place the "subtract the bar"
     math lives is the OS desktop shell (desktop.css). Individual apps no longer
     carry the full bar — they get the mini launcher (launcher-mini.js), which
     floats and reserves nothing — so there is no host-page clearance variable
     any more. */
  --os-inset-bottom: 0px;
  --radius: 12px;
  --radius-large: 18px;
  --radius-pill: 999px;
  touch-action: pan-x pan-y;
}

/* A text field always accepts text, whatever its ancestors say. WebKit inherits
   -webkit-user-select, so a field inside a top bar or modal overlay that opts
   out of selection (to keep long-press menus off chrome) inherited "none" —
   and on iPhone a field like that never raises the keyboard. */
input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]),
textarea,
[contenteditable]:not([contenteditable="false"]) {
  -webkit-user-select: text;
  user-select: text;
}

html[data-alyssiun-atmosphere="lux"] {
  --aly-bg: #f7f4ee;
  --aly-bg-soft: #fbfaf6;
  --aly-surface: #fff;
  --aly-surface-strong: #fff;
  --aly-text: #17191f;
  --aly-muted: #687384;
  --aly-border: rgba(46, 42, 36, .12);
  --aly-shadow: 0 18px 38px rgba(34, 27, 18, .07);
  --aly-primary: #06080b;
  --aly-primary-ink: #fff;
  --aly-accent: #315f8f;
  --aos-bg: #f7f4ee;
  --aos-surface: #fbfaf6;
  --aos-card: #fff;
  --aos-text: #17191f;
  --aos-muted: #687384;
  --aos-border: rgba(46, 42, 36, .12);
  --bg: var(--aly-bg);
  --bg-alt: var(--aly-bg-soft);
  --bg-card: var(--aly-surface);
  --bg-card-hover: var(--aly-surface-strong);
  --card: var(--aly-surface);
  --card-strong: var(--aly-surface-strong);
  --text: var(--aly-text);
  --muted: var(--aly-muted);
  --text-muted: var(--aly-muted);
  --line: var(--aly-border);
  --border: var(--aly-border);
  --void: var(--aly-bg);
  --void-2: #e2e0d7;
  --glass: #fff;
  --glass-2: #fff;
  --hair: var(--aly-border);
  --hair-2: rgba(46, 42, 36, .2);
  --app-bg: var(--aly-bg);
  --canvas-bg: #fbfaf6;
  --sidebar-bg: #f5f1ea;
  --surface: var(--aly-surface);
  --surface-soft: #fcfbf8;
  --surface-strong: #eee8dd;
  --surface-pop: #fff;
  --surface-border: var(--aly-border);
  --surface-border-strong: rgba(46, 42, 36, .2);
  --text-primary: var(--aly-text);
  --text-secondary: #313945;
  --text-subtle: var(--aly-muted);
  --text-muted: #8a94a2;
  --primary: var(--aly-primary);
  --primary-ink: var(--aly-primary-ink);
  --accent: var(--aly-accent);
  --shadow-soft: var(--aly-shadow);
  --card-shadow: var(--aly-shadow);
}

html[data-alyssiun-atmosphere="neo"] {
  --aly-bg: #060608;
  --aly-bg-soft: #0c0c11;
  --aly-surface: #11141a;
  --aly-surface-strong: #151821;
  --aly-text: #f4f4f6;
  --aly-muted: #8b8b97;
  --aly-border: rgba(255, 255, 255, .09);
  --aly-shadow: 0 40px 90px -50px rgba(0, 0, 0, .9);
  --aly-primary: #f7f4ee;
  --aly-primary-ink: #17191f;
  --aly-accent: #86e0c0;
  --aos-bg: #060608;
  --aos-surface: #0c0c11;
  --aos-card: #11141a;
  --aos-text: #f4f4f6;
  --aos-muted: #8b8b97;
  --aos-border: rgba(255, 255, 255, .09);
  --bg: var(--aly-bg);
  --bg-alt: var(--aly-bg-soft);
  --bg-card: var(--aly-surface);
  --bg-card-hover: var(--aly-surface-strong);
  --card: var(--aly-surface);
  --card-strong: var(--aly-surface-strong);
  --text: var(--aly-text);
  --muted: var(--aly-muted);
  --text-muted: var(--aly-muted);
  --line: var(--aly-border);
  --border: var(--aly-border);
  --void: #060608;
  --void-2: #0c0c11;
  --glass: #11141a;
  --glass-2: #151821;
  --hair: rgba(255, 255, 255, .09);
  --hair-2: rgba(255, 255, 255, .16);
  --app-bg: var(--aly-bg);
  --canvas-bg: var(--aly-bg-soft);
  --sidebar-bg: #060608;
  --surface: var(--aly-surface);
  --surface-soft: #0c0c11;
  --surface-strong: #151821;
  --surface-pop: #0c0c11;
  --surface-border: var(--aly-border);
  --surface-border-strong: rgba(255, 255, 255, .16);
  --text-primary: var(--aly-text);
  --text-secondary: #d6dde6;
  --text-subtle: var(--aly-muted);
  --text-muted: var(--aly-muted);
  --primary: var(--aly-primary);
  --primary-ink: var(--aly-primary-ink);
  --accent: var(--aly-accent);
  --shadow-soft: var(--aly-shadow);
  --card-shadow: var(--aly-shadow);
}

html[data-alyssiun-atmosphere] {
  background: var(--aly-bg);
  color: var(--aly-text);
  color-scheme: light;
  font-family: "Avenir Next", "Montserrat", Inter, Aptos, "Segoe UI", system-ui, Arial, sans-serif;
}

html[data-alyssiun-atmosphere="neo"] { color-scheme: dark; }

html[data-alyssiun-atmosphere] body,
html[data-alyssiun-atmosphere] #root,
html[data-alyssiun-atmosphere] .crm-shell,
html[data-alyssiun-atmosphere] .workspace,
html[data-alyssiun-atmosphere] .app-shell,
html[data-alyssiun-atmosphere] .shell,
html[data-alyssiun-atmosphere] .main,
html[data-alyssiun-atmosphere] .os-canvas {
  background: var(--aos-bg) !important;
  color: var(--aos-text) !important;
  transition: background .18s ease, color .18s ease;
}

/* Generic host-page chrome only. `header:not([class*="aos-"])` keeps this off
   the OS's own elements — the mobile home header (.aos-mobile-header) must sit
   directly on the atmosphere with no card surface of its own. */
html[data-alyssiun-atmosphere] .nav,
html[data-alyssiun-atmosphere] header:not([class*="aos-"]),
html[data-alyssiun-atmosphere] .site-header,
html[data-alyssiun-atmosphere] .app-topbar,
html[data-alyssiun-atmosphere] .mobile-bottom-nav {
  background: var(--aos-card) !important;
  color: var(--aos-text) !important;
  border-color: var(--aos-border) !important;
}

html[data-alyssiun-atmosphere] .card,
html[data-alyssiun-atmosphere] .profile-card,
html[data-alyssiun-atmosphere] .panel,
html[data-alyssiun-atmosphere] .simple-panel,
html[data-alyssiun-atmosphere] .app-sidebar {
  background: var(--aos-card) !important;
  color: var(--aos-text) !important;
  border-color: var(--aos-border) !important;
}

html[data-alyssiun-atmosphere] .muted,
html[data-alyssiun-atmosphere] small,
html[data-alyssiun-atmosphere] .page-sub {
  color: var(--aos-muted) !important;
}

/* The launcher circle — only rendered in MINI mode (app subdomains). The OS
 * desktop has no launcher chrome of its own: its floating Λ button opens the
 * panel. Base rules here; the mini geometry and the Λ ⇄ X toggle follow. */

/* The launcher circle — the primary OS affordance and the only launcher
 * control. Flat, LUX-consistent: a bordered ring at rest, a faint fill wash on
 * hover, and a solid fill with an inverted mark while the Start panel is open.
 * The mark sits at higher contrast than the app icons so it reads as chrome. */
.aos-bar-launch {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line, rgba(46, 42, 36, .18));
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  color: inherit;
  cursor: pointer;
  transition: background-color 200ms ease, border-color 200ms ease;
}
.aos-bar-launch .aos-mark-img {
  width: 24px;
  opacity: .9;
  transform: translateY(-0.5px); /* optical centering of the A */
  transition: filter 200ms ease, opacity 200ms ease;
}
.aos-bar-launch:hover {
  background: rgba(128, 128, 128, 0.12);
}
.aos-bar-launch:hover .aos-mark-img {
  opacity: 1;
}
:host(.aos-open) .aos-bar-launch {
  background: var(--text, #17191f);
  border-color: var(--text, #17191f);
}
:host(.aos-open) .aos-bar-launch .aos-mark-img {
  filter: invert(1);
  opacity: 1;
}
.aos-bar-launch:focus-visible {
  outline: 2px solid var(--focus, rgba(49, 95, 143, .5));
  outline-offset: 3px;
}

/* ---------------------------------------------------------------------------
 * MINI launcher — the single floating Λ circle carried by individual app
 * subdomains (launcher-mini.js -> v1.js with data-mode="mini"). No bottom
 * bar, no running-app strip, no clock, no reserved --os-inset-bottom: the
 * app is full-bleed and this circle floats over it. Clicking it opens the
 * same Start panel (app grid + LUX/NEO/AUTO switch) as the OS bar.
 * ------------------------------------------------------------------------- */
:host(.aos-mini) .aos-bar-launch {
  position: fixed;
  left: 50%;
  bottom: max(18px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 2147483300;
  width: 52px;
  height: 52px;
  border: 1px solid var(--line, rgba(20, 23, 25, .2));
  border-radius: 50%;
  background: linear-gradient(145deg, #fff, #e6e0d5);
  box-shadow: 0 16px 44px rgba(48, 57, 54, .24), inset 0 1px 0 #fff;
  color: #141719;
  transition: transform 150ms ease, box-shadow 150ms ease, background-color 200ms ease, border-color 200ms ease;
}
:host(.aos-mini) .aos-bar-launch .aos-mark-img {
  width: 26px;
  opacity: .92;
}
:host(.aos-mini) .aos-bar-launch:hover {
  background: linear-gradient(145deg, #fff, #e6e0d5);
  transform: translateX(-50%) translateY(-1px);
  box-shadow: 0 20px 52px rgba(48, 57, 54, .28), inset 0 1px 0 #fff;
}
:host(.aos-mini) .aos-bar-launch:active {
  transform: translateX(-50%) scale(.95);
}
:host(.aos-mini.aos-neo) .aos-bar-launch {
  background: linear-gradient(145deg, #1c1c1e, #0a0a0c);
  border-color: rgba(255, 255, 255, .16);
  box-shadow: 0 16px 44px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(255, 255, 255, .1);
  color: #f5f5f7;
}
:host(.aos-mini.aos-neo) .aos-bar-launch:hover {
  background: linear-gradient(145deg, #1c1c1e, #0a0a0c);
}
:host(.aos-mini.aos-open) .aos-bar-launch {
  background: var(--text, #17191f);
  border-color: var(--text, #17191f);
}

/* ---------------------------------------------------------------------------
 * Start panel bounds — the panel must never cover the bar, so the launcher
 * stays reachable to dismiss it. (Dismissal — launcher tap, tap-outside,
 * Escape — is already wired in v1.js; this only constrains the panel's box.)
 * v1.css defines the panel; host-v1.css loads after it in the shadow root, so
 * these win at equal specificity. Visual design is untouched — only the box.
 * ------------------------------------------------------------------------- */
.aos-panel {
  /* Safety net for the centred (desktop) panel on a short window: subtracting
     the insets twice keeps the symmetric bottom gap >= the bar height so it
     can't overlap. On tall windows the panel's own min(660px, …) height wins
     and this is inert. (Doubled by repetition, not "2 *", to avoid multiplying
     a var() that is itself a calc().) */
  max-height: calc(
    100dvh
    - var(--os-inset-bottom, 0px) - var(--os-inset-bottom, 0px)
    - env(safe-area-inset-top, 0px) - env(safe-area-inset-top, 0px)
  );
}

@media (max-width: 720px) {
  /* The phone-size panel is centred in the visible area (the viewport less the
     bottom bar), like the desktop one (v1.css). Its height is exactly the space
     between the top safe-area and the strip at the bottom: the bar's own
     height, or — with the floating Λ — the 90px band Λ rests in; the app grid
     inside (.aos-grid) already scrolls, so overflow stays internal. */
  .aos-panel {
    /* The 60px band at the top is the interface pill's (top centre on every device). */
    top: calc(var(--aos-panel-clear, 60px) + (100dvh - var(--os-inset-bottom, 0px) - var(--aos-panel-clear, 60px)) / 2);
    bottom: auto;
    height: calc(100dvh - var(--os-inset-bottom, 0px) - var(--aos-panel-clear, 60px) - max(8px, env(safe-area-inset-top, 0px))
      - max(env(safe-area-inset-bottom, 0px), max(90px - var(--os-inset-bottom, 0px), 16px)));
    max-height: calc(100dvh - var(--os-inset-bottom, 0px) - var(--aos-panel-clear, 60px) - max(8px, env(safe-area-inset-top, 0px))
      - max(env(safe-area-inset-bottom, 0px), max(90px - var(--os-inset-bottom, 0px), 16px)));
  }
}

/* ---------------------------------------------------------------------------
 * MINI launcher — panel geometry and the Λ ⇄ X toggle.
 *
 * The circle is fixed at the bottom-centre. The Start panel opens UPWARD from
 * it: its bottom edge is pinned one circle-height-plus-gap above the viewport
 * floor so the circle always sits fully below the panel and is never covered.
 * These selectors out-specify both v1.css and its media queries (:host() adds
 * a class's worth of specificity), so no !important is needed.
 *
 * Layout constants: circle inset  = max(18px, safe-area-bottom)
 *                   circle height = 52px
 *                   gap           = 14px
 * ------------------------------------------------------------------------- */
:host(.aos-mini) .aos-panel {
  left: 50%;
  right: auto;
  top: auto;
  bottom: calc(max(18px, env(safe-area-inset-bottom, 0px)) + 52px + 14px);
  height: min(620px, calc(100dvh - (max(18px, env(safe-area-inset-bottom, 0px)) + 52px + 14px) - 12px));
  max-height: calc(100dvh - (max(18px, env(safe-area-inset-bottom, 0px)) + 52px + 14px) - 12px);
  transform-origin: bottom center;
  transform: translateX(-50%) translateY(12px) scale(.985);
}
:host(.aos-mini) .aos-panel.aos-open {
  transform: translateX(-50%) translateY(0) scale(1);
}

@media (max-width: 720px) {
  :host(.aos-mini) .aos-panel {
    width: min(460px, calc(100vw - 20px));
  }
}

/* Open state = closed state with a different glyph. The circle keeps its
 * exact closed styling — same size, same dark/light fill per atmosphere,
 * same border — and only the mark swaps: the Λ image cross-fades out while
 * an X (two rotated bars) cross-fades in, drawn in the SAME colour the Λ
 * used (the circle's own `color`). No white fill, no size change; these
 * `!important`s undo the shared `:host(.aos-open) .aos-bar-launch` fill that
 * would otherwise turn the button into a solid `var(--text)` block. */
:host(.aos-mini) .aos-bar-launch { position: fixed; }
:host(.aos-mini) .aos-bar-launch .aos-mark-img {
  transition: opacity 180ms ease;
}
:host(.aos-mini) .aos-bar-launch::before,
:host(.aos-mini) .aos-bar-launch::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 19px;
  height: 2.2px;
  border-radius: 2px;
  background: currentColor;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease;
}
:host(.aos-mini) .aos-bar-launch::before { transform: translate(-50%, -50%) rotate(45deg); }
:host(.aos-mini) .aos-bar-launch::after  { transform: translate(-50%, -50%) rotate(-45deg); }

/* LUX: keep the closed light-gradient circle + dark glyph. */
:host(.aos-mini.aos-open) .aos-bar-launch {
  background: linear-gradient(145deg, #fff, #e6e0d5) !important;
  border-color: var(--line, rgba(20, 23, 25, .2)) !important;
  color: #141719 !important;
}
/* NEO: keep the closed dark-gradient circle + light glyph. */
:host(.aos-mini.aos-neo.aos-open) .aos-bar-launch {
  background: linear-gradient(145deg, #1c1c1e, #0a0a0c) !important;
  border-color: rgba(255, 255, 255, .16) !important;
  color: #f5f5f7 !important;
}
:host(.aos-mini.aos-open) .aos-bar-launch .aos-mark-img { opacity: 0; }
:host(.aos-mini.aos-open) .aos-bar-launch .aos-mark-img { filter: none; }
:host(.aos-mini.aos-open) .aos-bar-launch::before,
:host(.aos-mini.aos-open) .aos-bar-launch::after { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  :host(.aos-mini) .aos-bar-launch .aos-mark-img,
  :host(.aos-mini) .aos-bar-launch::before,
  :host(.aos-mini) .aos-bar-launch::after,
  :host(.aos-mini) .aos-panel { transition: none; }
}


/* Atmosphere change: colours cross over one second instead of snapping.
   theme-shell.js / the launcher set data-atmosphere-fading for that second. */
html[data-atmosphere-fading] *,
html[data-atmosphere-fading] *::before,
html[data-atmosphere-fading] *::after {
  transition: background-color 1s ease, color 1s ease, border-color 1s ease, fill 1s ease,
    stroke 1s ease, box-shadow 1s ease, outline-color 1s ease;
}
[data-wallpaper-ghost] { transition: opacity 1s ease; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  html[data-atmosphere-fading] *, html[data-atmosphere-fading] *::before, html[data-atmosphere-fading] *::after,
  [data-wallpaper-ghost] { transition: none; }
}
