/* ==================================================================
   amirkral.ir — layout layer
   Loading screen, lock screen, desktop, taskbar, start menu, windows,
   context menus and the settings window.
   ================================================================== */

/* ==================================================================
   Full-screen overlays
   ================================================================== */
.screen {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-screen);
  transition: opacity 0.5s ease-out;
}
.screen.is-hidden {
  opacity: 0;
  pointer-events: none;
}

/* ---------- Loading screen --------------------------------------- */
#loading-screen { background-color: #000; color: #fff; }

.loader {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.loader__bars {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 0.5rem;
  direction: ltr;
  font-size: 0.8rem;
  font-weight: 600;
}
@media (min-width: 768px) {
  .loader__bars { gap: 1rem; font-size: 1rem; }
}

.candle {
  display: flex;
  flex-direction: column;
  align-items: center;
  opacity: 0;
  transition: opacity 0.8s ease-out, transform 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.candle--down { transform: translateY(-40px); }
.candle--up   { transform: translateY(40px); }
.candle.is-visible { opacity: 1; transform: translateY(0); }

.candle__word { margin-bottom: 0.5rem; height: 1.5rem; }
.candle__shape { display: flex; flex-direction: column; align-items: center; }
.candle__wick { width: 2px; }
.candle__body { width: 1rem; }
.candle--down .candle__wick,
.candle--down .candle__body { background-color: var(--down); }
.candle--up .candle__wick,
.candle--up .candle__body { background-color: var(--up); }

.loader__signature {
  position: absolute;
  bottom: 2.5rem;
  width: 100%;
  text-align: center;
  font-family: 'Exo 2', sans-serif;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 1.2s ease-out, transform 1.2s ease-out;
}
.loader__signature.is-visible { opacity: 1; transform: translateY(0); }
.loader__signature strong {
  display: block;
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: #d1d5db;
}
.loader__signature span { font-size: 0.9rem; color: #9ca3af; }

/* ---------- Lock / login screen ---------------------------------- */
#login-screen {
  background-color: rgba(0, 0, 0, 0.35);
  backdrop-filter: blur(30px);
  -webkit-backdrop-filter: blur(30px);
  overflow: hidden;
  color: #fff;
}

.lock,
.login-form-wrap {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transition: transform 0.5s var(--ease);
}
.lock { cursor: pointer; }
.login-form-wrap { transform: translateY(100%); }

#login-screen.is-unlocking .lock { transform: translateY(-100%); }
#login-screen.is-unlocking .login-form-wrap { transform: translateY(0); }

.lock__time { font-size: clamp(3rem, 12vw, 6rem); font-weight: 700; line-height: 1; }
.lock__date { font-size: clamp(1rem, 3vw, 1.5rem); margin-top: 0.6rem; opacity: 0.95; }
.lock__hint {
  position: absolute;
  bottom: 2.5rem;
  text-align: center;
  font-size: 1rem;
  opacity: 0.9;
}
.lock__hint svg { width: 1.5rem; height: 1.5rem; margin: 0 auto 0.25rem; animation: bounce 1.6s infinite; }
@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-25%); }
}

.login-card { text-align: center; }
.login-card__avatar {
  width: 8rem;
  height: 8rem;
  object-fit: cover;
  border-radius: 50%;
  margin: 0 auto 1rem;
  border: 4px solid rgba(255, 255, 255, 0.5);
}
.login-card__name { font-size: 2rem; font-weight: 700; margin: 0; }

.login-form {
  margin-top: 1.2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
}
.login-form input {
  width: 16rem;
  padding: 0.75rem;
  text-align: center;
  color: #fff;
  background-color: rgba(0, 0, 0, 0.3);
  border: 2px solid rgba(255, 255, 255, 0.5);
  border-radius: var(--radius-sm);
  transition: border-color 0.2s ease;
}
.login-form input::placeholder { color: rgba(255, 255, 255, 0.7); }
.login-form input:focus { border-color: #fff; outline: none; }
.login-form .btn { width: 16rem; border-radius: var(--radius-sm); }
.login-error { color: #fca5a5; margin-top: 0.5rem; min-height: 1.25rem; font-size: 0.85rem; }

/* ==================================================================
   Desktop
   ================================================================== */
#desktop {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  z-index: var(--z-desktop);
}
#desktop[hidden] { display: none; }

.draggable { position: absolute; }
.draggable.is-dragging { transition: none !important; }

/* ==================================================================
   Taskbar
   ================================================================== */
.taskbar {
  position: absolute;
  bottom: 1rem;
  width: 100%;
  padding: 0 1rem;
  pointer-events: none;
  z-index: var(--z-taskbar);
}

.taskbar__group {
  position: absolute;
  bottom: 0;
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  pointer-events: auto;
}
.taskbar__group--left { inset-inline-start: 1rem; }
.taskbar__group--center { left: 50%; transform: translateX(-50%); }
.taskbar__group--right { inset-inline-end: 1rem; align-items: center; }

/* On a pointer this is invisible: the group was already a row with this
   gap, so wrapping three of its children changes nothing on screen. It
   earns its keep on a phone, where the bar reorders its clusters. */
.taskbar__cluster {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.taskbar__dock {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  padding: 0.5rem;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.taskbar__dock .icon-btn { width: 2.5rem; height: 2.5rem; }
.taskbar__dock .icon-btn img { width: 1.75rem; height: 1.75rem; }
/* Start and search share one dock, so they are sized identically and
   centred on the same baseline — previously the two icons were set from
   different rules and did not line up. */
.taskbar__group--center .icon-btn { width: 3rem; height: 3rem; }
.taskbar__group--center .icon-btn img,
.taskbar__group--center .icon-btn > svg,
.taskbar__group--center .icon-btn .icon-svg,
.taskbar__group--center .icon-btn .icon-svg svg {
  width: 1.65rem;
  height: 1.65rem;
}
.taskbar__group--center .icon-btn .icon-svg {
  display: flex;
  align-items: center;
  justify-content: center;
}
.taskbar__group--center .start-btn svg { width: 1.65rem; height: 1.65rem; }

.start-btn svg { width: 1.5rem; height: 1.5rem; color: var(--brand); }

.lang-btn {
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  font-weight: 600;
  font-size: 0.85rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
}
.lang-btn:hover { background-color: var(--glass-hover); }

.notif-btn {
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
  position: relative;
}
.notif-btn:hover { background-color: var(--glass-hover); }
.notif-btn svg { width: 1.5rem; height: 1.5rem; }
.notif-btn__count {
  position: absolute;
  top: 0.35rem;
  inset-inline-end: 0.35rem;
  min-width: 1.05rem;
  height: 1.05rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  background: var(--brand);
  color: var(--brand-contrast);
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 1.05rem;
  text-align: center;
  box-shadow: 0 0 0 2px var(--glass-bg);
}

.theme-dock {
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: center;
}

/* Theme switch */
.switch { position: relative; display: inline-block; width: 3.5rem; height: 2rem; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch__track {
  position: absolute;
  inset: 0;
  background-color: #cbd5e1;
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 0.35s ease;
}
.switch__track::before {
  content: '';
  position: absolute;
  top: 0.25rem;
  inset-inline-start: 0.25rem;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background-color: #fff;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 0.85rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='2.5' stroke='%23374151'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M12 3v1m0 16v1m9-9h-1M4 12H3m15.364-6.364l-.707.707M6.343 17.657l-.707.707m12.728 0l-.707-.707M6.343 6.343l-.707-.707m12.728 10.607a4.5 4.5 0 11-6.364-6.364 4.5 4.5 0 016.364 6.364z'/%3E%3C/svg%3E");
  transition: transform 0.35s ease, background-image 0.35s ease;
}
.switch input:checked + .switch__track { background-color: #374151; }
.switch input:checked + .switch__track::before {
  transform: translateX(1.5rem);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%23ffffff'%3E%3Cpath d='M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z'/%3E%3C/svg%3E");
}
html[dir='rtl'] .switch input:checked + .switch__track::before { transform: translateX(-1.5rem); }

/* Small switch used inside settings lists */
.switch--sm { width: 2.75rem; height: 1.6rem; }
.switch--sm .switch__track::before { width: 1.1rem; height: 1.1rem; top: 0.25rem; background-size: 0.7rem; }
.switch--sm input:checked + .switch__track::before { transform: translateX(1.15rem); }
html[dir='rtl'] .switch--sm input:checked + .switch__track::before { transform: translateX(-1.15rem); }

/* ==================================================================
   Pop-over panels (start menu, search, notifications, small menus)
   ================================================================== */
.popover {
  position: absolute;
  z-index: var(--z-menu);
  transition: opacity 0.2s var(--ease), transform 0.22s var(--ease);
}
.popover.is-hidden {
  opacity: 0;
  pointer-events: none;
  transform: translateY(14px) scale(0.96);
}

.panel-bottom-center {
  bottom: 6rem;
  /* `left` + translateX is used instead of the logical inset-inline-start +
     margin-inline-start pairing on purpose: mixing a physical property
     (left) with a logical one (margin-inline-start) breaks in RTL, because
     inline-start flips to the right while `left` does not — the panel
     rendered off-center in Persian and Turkish. translateX(-50%) shifts by
     the element's own rendered width regardless of text direction, so
     centering is correct in both directions. */
  left: 50%;
  transform: translateX(-50%);
  transform-origin: bottom center;
  width: 600px;
  max-width: 95vw;
  height: 550px;
  max-height: 70vh;
}
.panel-bottom-center.is-hidden { transform: translateX(-50%) translateY(14px) scale(0.96); }

.panel-body {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  color: var(--text);
}

/* ---------- Start menu ------------------------------------------- */
.start__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}
.start__profile {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem;
  margin: -0.5rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.start__profile:hover { background-color: var(--glass-hover); }
.start__profile img { width: 2.5rem; height: 2.5rem; border-radius: 50%; object-fit: cover; }
.start__profile span { font-weight: 600; }

/* Tabs scroll sideways instead of wrapping onto a second row: with many
   categories, wrapping quietly ate the height the app grid needed. The
   scrollbar is the same understated one the cards use. */
.tabs {
  display: flex;
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: 0.35rem;
  border-bottom: 1px solid var(--divider);
  margin-bottom: 1.35rem;
  padding-bottom: 0.15rem;
  font-size: 0.85rem;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-behavior: smooth;
  scrollbar-width: thin;
  scrollbar-color: var(--scroll-thumb) transparent;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
}
/* Centre them while they still fit; only start scrolling once they don't. */
.tabs::before, .tabs::after { content: ''; margin: auto; }
.tabs::-webkit-scrollbar { height: 4px; }
.tabs::-webkit-scrollbar-track { background: transparent; }
.tabs::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 999px; }
.tabs::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); }

.tabs button {
  padding: 0.5rem 0.9rem;
  color: var(--text-soft);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  flex-shrink: 0;
  border-radius: 8px 8px 0 0;
  transition: color 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}
.tabs button:hover { color: var(--text); background-color: var(--glass-hover); }
.tabs button.is-active {
  color: var(--brand);
  font-weight: 600;
  border-bottom-color: var(--brand);
}

.app-grid {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.35rem 1rem;
  padding-block: 0.35rem;
  padding-inline-end: 0.5rem;
  align-content: start;
}
@media (min-width: 520px) {
  .app-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (prefers-reduced-motion: reduce) {
  .tabs { scroll-behavior: auto; }
}

.app-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  text-align: center;
  cursor: pointer;
}
/* Icon tile: a soft flat square tinted by its category's accent colour
   (set by the admin per start-menu tab) — gives icons a distinct, designed
   identity without needing new artwork. Size and corner shape are both
   driven by admin settings (--app-icon-size, --app-icon-radius) so the
   whole grid restyles together. */
.app-tile__icon {
  --tile-pad: calc(var(--app-icon-size, 40px) * 0.32);
  --tile-tint: var(--tile-accent, var(--brand));
  width: calc(var(--app-icon-size, 40px) + var(--tile-pad));
  height: calc(var(--app-icon-size, 40px) + var(--tile-pad));
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--app-icon-radius, 13px);
  background: linear-gradient(155deg,
    color-mix(in srgb, var(--tile-tint) 20%, transparent),
    color-mix(in srgb, var(--tile-tint) 8%, transparent));
  border: 1px solid color-mix(in srgb, var(--tile-tint) 30%, transparent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.app-tile:hover .app-tile__icon {
  transform: translateY(-2px) scale(1.05);
  border-color: color-mix(in srgb, var(--tile-tint) 55%, transparent);
  box-shadow: 0 6px 16px color-mix(in srgb, var(--tile-tint) 25%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
.app-tile__icon img,
.app-tile__icon svg {
  width: var(--app-icon-size, 40px);
  height: var(--app-icon-size, 40px);
  object-fit: contain;
}
.app-tile__icon img { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.12)); }
/* Inlined SVGs take the category accent; a touch heavier than the source
   stroke so they stay legible at small sizes. */
.app-tile__icon svg {
  color: var(--tile-tint);
  stroke-width: 1.6;
}
html.dark .app-tile__icon svg { color: color-mix(in srgb, var(--tile-tint) 78%, white); }
.app-tile__name {
  font-size: 0.78rem;
  line-height: 1.3;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.app-tile__desc {
  font-size: 0.68rem;
  color: var(--text-soft);
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.start__foot {
  margin-top: auto;
  padding-top: 1rem;
  border-top: 1px solid var(--divider);
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}
.start__foot .icon-btn { width: 2.25rem; height: 2.25rem; border-radius: 50%; }

/* ---------- Search ------------------------------------------------ */
.search-input {
  width: 100%;
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
  border: 0;
  border-radius: var(--radius-sm);
  background-color: rgba(255, 255, 255, 0.5);
  color: var(--text);
  outline: none;
  transition: box-shadow 0.2s ease, background-color 0.2s ease;
}
html.dark .search-input { background-color: rgba(0, 0, 0, 0.25); }
.search-input:focus { box-shadow: 0 0 0 2px var(--brand); }
.search-input::placeholder { color: var(--text-soft); }

.empty-state {
  grid-column: 1 / -1;
  text-align: center;
  padding: 2rem 1rem;
  color: var(--text-soft);
  font-size: 0.85rem;
}

/* ---------- Small menus ------------------------------------------ */
.menu {
  border-radius: var(--radius-sm);
  padding: 0.25rem;
  font-size: 0.85rem;
  min-width: 11rem;
  box-shadow: var(--shadow-lg);
  color: var(--text);
}
.menu button {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
  text-align: start;
  transition: background-color 0.15s ease;
}
.menu button:hover { background-color: var(--glass-hover); }
.menu button svg { width: 1rem; height: 1rem; flex-shrink: 0; }

#context-menu { min-width: 14rem; transform-origin: top left; }
#power-menu, #profile-menu, #language-menu, #notification-center { bottom: 5rem; }
#language-menu, #notification-center { inset-inline-end: 1rem; }

/* The power and profile buttons both live inside the centred start menu,
   so their menus open centred under it rather than jumping to a screen
   edge far away from the button that opened them. Centering uses
   translateX(-50%) rather than a logical inset so it is correct in RTL
   and LTR alike; the hidden state has to restate the translate or the
   generic .popover.is-hidden rule would knock it off-centre. */
#power-menu, #profile-menu {
  left: 50%;
  bottom: 7.5rem;
  transform: translateX(-50%);
  transform-origin: bottom center;
  min-width: 13rem;
}
#power-menu.is-hidden, #profile-menu.is-hidden {
  transform: translateX(-50%) translateY(14px) scale(0.96);
}
#power-menu button, #profile-menu button { justify-content: center; }

#language-menu {
  display: flex;
  gap: 0.5rem;
  padding: 0.5rem;
  border-radius: var(--radius);
}
#language-menu button {
  width: auto;
  padding: 0.25rem;
  border: 2px solid transparent;
  border-radius: 50%;
}
#language-menu button.is-active { border-color: var(--brand); }
#language-menu img { width: 2rem; height: 2rem; border-radius: 50%; object-fit: cover; }

/* ---------- Notification centre ---------------------------------- */
#notification-center {
  width: 22rem;
  max-width: calc(100vw - 2rem);
  max-height: 26rem;
  padding: 0;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  color: var(--text);
  overflow: hidden;
}
#notification-center h3 {
  margin: 0;
  padding: 1rem 1.1rem 0.75rem;
  font-size: 0.92rem;
  font-weight: 700;
  border-bottom: 1px solid var(--divider);
}
.notif-list {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 0.75rem;
}

.notif-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 2rem 1rem;
  color: var(--text-soft);
  font-size: 0.82rem;
  text-align: center;
}
.notif-empty svg { width: 2rem; height: 2rem; opacity: 0.55; }

.notif {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: 0.7rem 0.75rem;
  border-radius: var(--radius-sm);
  background-color: rgba(255, 255, 255, 0.32);
  border-inline-start: 3px solid var(--notif-accent, var(--brand));
  transition: background-color 0.15s ease, transform 0.15s ease;
}
.notif:hover { transform: translateX(-2px); }
html[dir='rtl'] .notif:hover { transform: translateX(2px); }
html.dark .notif { background-color: rgba(255, 255, 255, 0.05); }

.notif__icon {
  flex-shrink: 0;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: color-mix(in srgb, var(--notif-accent, var(--brand)) 16%, transparent);
  color: var(--notif-accent, var(--brand));
}
.notif__icon svg { width: 1.05rem; height: 1.05rem; }
.notif__icon img { width: 1.4rem; height: 1.4rem; object-fit: contain; border-radius: 50%; }

.notif__body { min-width: 0; }
.notif__body strong {
  display: block;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text-strong);
  line-height: 1.5;
}
.notif__body p {
  margin: 0.15rem 0 0;
  font-size: 0.76rem;
  color: var(--text-soft);
  line-height: 1.6;
}

.notif--info    { --notif-accent: #3b82f6; }
.notif--success { --notif-accent: #22c55e; }
.notif--warning { --notif-accent: #f59e0b; }
.notif--danger  { --notif-accent: #ef4444; }
html.dark .notif--info    { --notif-accent: #60a5fa; }
html.dark .notif--success { --notif-accent: #4ade80; }
html.dark .notif--warning { --notif-accent: #fbbf24; }
html.dark .notif--danger  { --notif-accent: #f87171; }

/* ==================================================================
   Windows
   ================================================================== */
.window {
  position: absolute;
  z-index: var(--z-window);
  display: flex;
  flex-direction: column;
  min-width: 320px;
  min-height: 240px;
  max-width: calc(100vw - 2rem);
  max-height: calc(100vh - 8rem);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  resize: both;
  color: var(--text);
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
}
.window.is-hidden {
  opacity: 0;
  pointer-events: none;
  transform: scale(0.96);
}

.window__header {
  flex-shrink: 0;
  height: 2.75rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1rem;
  border-bottom: 1px solid var(--divider);
  cursor: grab;
  font-weight: 700;
  font-size: 0.9rem;
}
.window__header:active { cursor: grabbing; }

.window__close {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background-color: #ef4444;
  transition: background-color 0.15s ease;
  flex-shrink: 0;
}
.window__close:hover { background-color: #dc2626; }

.window__body {
  flex: 1;
  padding: 1.25rem;
  overflow-y: auto;
  font-size: 0.88rem;
  line-height: 1.75;
}
.window__body h1, .window__body h2, .window__body h3 { color: var(--text-strong); }
.window__body h3 {
  font-size: 1.05rem;
  font-weight: 700;
  margin: 1.5rem 0 0.75rem;
  padding-bottom: 0.3rem;
  border-bottom: 2px solid var(--brand);
}
.window__body ul { padding-inline-start: 1.2rem; margin: 0.5rem 0; }
.window__body a { color: var(--brand); }
.window__body img { border-radius: var(--radius-sm); margin: 0.5rem 0; max-width: 100%; }

/* Content authored in the panel's editor: headings, tables, quotes and
   code blocks all need to look right here, not just in the editor. */
.window__body h2 { font-size: 1.15rem; font-weight: 700; margin: 1.1rem 0 .55rem; }
.window__body h4 { font-size: .95rem; font-weight: 700; margin: .9rem 0 .4rem; color: var(--text-strong); }
.window__body p { margin: 0 0 .7rem; }
.window__body ol { padding-inline-start: 1.3rem; margin: 0.5rem 0; }
.window__body blockquote {
  margin: 0.8rem 0;
  padding: 0.55rem 0.9rem;
  border-inline-start: 3px solid var(--brand);
  background: rgba(255, 255, 255, 0.14);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
html.dark .window__body blockquote { background: rgba(0, 0, 0, 0.18); }
.window__body pre {
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.16);
  direction: ltr;
  text-align: left;
  overflow-x: auto;
  font-size: 0.78rem;
}
.window__body table {
  width: 100%;
  border-collapse: collapse;
  margin: 0.8rem 0;
  font-size: 0.82rem;
}
.window__body th, .window__body td {
  border: 1px solid var(--divider);
  padding: 0.4rem 0.6rem;
  text-align: start;
}
.window__body th { background: rgba(255, 255, 255, 0.12); font-weight: 700; }
html.dark .window__body th { background: rgba(0, 0, 0, 0.22); }

.window--centered .window__body {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-size: 1.05rem;
  font-weight: 600;
}

/* Resume window layout */
.resume__head { text-align: center; margin-bottom: 1.5rem; }
.resume__head img {
  width: 6rem;
  height: 6rem;
  object-fit: cover;
  border-radius: 50%;
  margin: 0 auto 0.75rem;
  border: 4px solid rgba(255, 255, 255, 0.5);
}
.resume__head h2 { font-size: 1.4rem; font-weight: 700; margin: 0; }
.resume__head p { margin: 0.25rem 0 0; color: var(--text-soft); }

.skills { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem 1.5rem; }
.skill__row { display: flex; justify-content: space-between; font-size: 0.8rem; margin-bottom: 0.3rem; }
.skill__bar { height: 0.5rem; border-radius: 999px; background-color: var(--divider); overflow: hidden; }
.skill__fill { height: 100%; border-radius: 999px; background-color: var(--brand); }

/* ==================================================================
   Display-settings window
   ================================================================== */
.settings-section { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--divider); }
.settings-section:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.settings-section h3 { font-size: 0.95rem; font-weight: 700; margin: 0 0 0.85rem; border: 0; padding: 0; }

.wallpaper-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.5rem; }
.wallpaper-grid button {
  height: 4.5rem;
  border-radius: var(--radius-sm);
  border: 2px solid transparent;
  background-size: cover;
  background-position: center;
  transition: border-color 0.2s ease, transform 0.15s ease;
}
.wallpaper-grid button:hover { transform: scale(1.03); }
.wallpaper-grid button.is-active { border-color: var(--brand); }

.color-row { display: flex; gap: 1rem; flex-wrap: wrap; }
.color-dot {
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  border: 2px solid transparent;
  transition: transform 0.2s ease, border-color 0.2s ease;
}
.color-dot.is-active {
  border-color: #fff;
  transform: scale(1.12);
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
}

.range-row { display: flex; align-items: center; gap: 1rem; font-size: 0.8rem; }
.range-row input[type='range'] {
  flex: 1;
  height: 0.45rem;
  border-radius: 999px;
  appearance: none;
  background: var(--divider);
  cursor: pointer;
}
.range-row input[type='range']::-webkit-slider-thumb {
  appearance: none;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  background: var(--brand);
  border: 2px solid #fff;
}
.range-row input[type='range']::-moz-range-thumb {
  width: 1.1rem;
  height: 1.1rem;
  border: 2px solid #fff;
  border-radius: 50%;
  background: var(--brand);
}

/* Three per row: the toggles are short labels with a small switch, and
   two columns left a lot of empty space in a window this wide. */
.toggle-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.6rem 0.9rem; }
.toggle-grid .toggle-row { font-size: 0.78rem; gap: 0.4rem; }

/* Two controls sharing a row. */
.settings-section--split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.25rem;
}
.settings-section--split > div { min-width: 0; }

@media (max-width: 640px) {
  .toggle-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .settings-section--split { grid-template-columns: 1fr; gap: 0.9rem; }
}
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; font-size: 0.85rem; }

/* ==================================================================
   Mobile
   ================================================================== */
@media (max-width: 767px) {
  body { overflow: auto; }

  /* The page scrolls; the bar does not. #desktop is therefore a plain
     column of cards with room at the foot for the fixed bar, and it is
     no longer a scroll container of its own — one scroller instead of
     two nested ones, which is what made the page fight the browser's
     own address-bar behaviour. */
  #desktop {
    height: auto;
    min-height: 100vh;
    overflow: visible;
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
  }

  .draggable { position: static !important; width: 100% !important; }

  .wallpaper-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .skills { grid-template-columns: 1fr; }
}

/* Social card shown only on mobile */
.social-card {
  display: none;
  align-items: center;
  justify-content: space-around;
  gap: 0.5rem;
  padding: 1rem;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.social-card img { width: 1.75rem; height: 1.75rem; }
@media (max-width: 767px) { .social-card { display: flex; } }

/* ==================================================================
   Taskbar tray — live clock, calendar and weather
   These replace the desktop cards that used to hold the same
   information, so the desktop is free for the cards that need room.
   ================================================================== */
#taskbar-tray { gap: 0.15rem; }

.tray-btn { width: 2.5rem; height: 2.5rem; }
.tray-btn svg, .tray-btn .tray-weather__icon svg { width: 1.5rem; height: 1.5rem; }
.tray-btn .tray-weather__icon { display: flex; }

/* ---------- clock icon ---------- */
.tray-clock__face { fill: none; stroke: currentColor; stroke-width: 1.6; opacity: 0.85; }
.tray-clock__tick { stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; opacity: 0.5; }
.tray-clock__hour,
.tray-clock__minute {
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  transition: transform 0.3s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.tray-clock__minute { stroke-width: 1.4; }
.tray-clock__second {
  stroke: var(--down);
  stroke-width: 1;
  stroke-linecap: round;
  transition: transform 0.15s cubic-bezier(0.34, 1.5, 0.64, 1);
}
.tray-clock__pin { fill: var(--down); }

/* ---------- calendar icon ---------- */
.tray-cal__body { fill: currentColor; opacity: 0.16; stroke: currentColor; stroke-width: 1.3; }
.tray-cal__band { fill: var(--brand); }
.tray-cal__ring { fill: currentColor; opacity: 0.75; }
.tray-cal__day {
  fill: currentColor;
  font-size: 9px;
  font-weight: 700;
  font-family: 'Vazirmatn', system-ui, sans-serif;
}

/* ---------- weather glyphs ---------- */
.wx-sun { fill: #fbbf24; }
.wx-ray { stroke: #fbbf24; stroke-width: 1.6; stroke-linecap: round; }
.wx-cloud { fill: #e2e8f0; stroke: #cbd5e1; stroke-width: 0.8; }
html.dark .wx-cloud { fill: #cbd5e1; stroke: #94a3b8; }
.wx-rain { stroke: #60a5fa; stroke-width: 1.5; stroke-linecap: round; }
.wx-snow { fill: #bfdbfe; }
.wx-moon { fill: #fde68a; }
.wx-star { fill: #fbbf24; }
.wx-bolt { fill: #f59e0b; }

/* ---------- panels ---------- */
/* Centred over the taskbar and shaped like the notification centre, so
   the three read as one family of panels rather than three variations.
   translateX is restated on the hidden state or the shared .popover rule
   would knock them off centre on the way in. */
/* Positioned in script, above whichever icon opened it (see ui/tray.js).
   The left and bottom values here are only a sensible starting point for
   the first paint. */
.tray-panel {
  bottom: 5.5rem;
  left: 50%;
  transform-origin: bottom center;
  width: 19rem;
  padding: 1.1rem;
  /* No scrolling: each panel is small enough to show whole, and a
     scrollbar inside a popover this size looks like a mistake. The cap is
     only a guard for very short viewports. */
  max-height: calc(100vh - 8rem);
  overflow: visible;
  border-radius: var(--radius-lg, 22px);
  text-align: center;
}
.tray-panel.is-hidden { transform: translateY(14px) scale(0.96); }

/* Small pointer toward the icon that opened the panel. */
.tray-panel::after {
  content: '';
  position: absolute;
  top: 100%;
  left: var(--tray-arrow, 50%);
  margin-left: -7px;
  border: 7px solid transparent;
  border-top-color: var(--glass-bg);
  filter: drop-shadow(0 1px 0 var(--glass-border));
}
.tray-panel--wide { width: 20rem; }

.tray-panel__title {
  font-size: 0.82rem;
  font-weight: 700;
  margin-bottom: 0.85rem;
  color: var(--text-strong);
  text-align: center;
}
.tray-panel__state { font-size: 0.8rem; color: var(--text-soft); text-align: center; padding: 1rem 0; }

/* ---------- clock panel ---------- */
.tray-local { text-align: center; padding-bottom: 0.7rem; margin-bottom: 0.6rem; border-bottom: 1px solid var(--divider); }
.tray-local__time {
  display: block;
  font-size: 1.7rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}
.tray-local__label { font-size: 0.68rem; color: var(--text-soft); }


/* ---------- calendar panel ---------- */
.tray-cal__nav { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.6rem; }
.tray-cal__arrow {
  width: 1.6rem; height: 1.6rem;
  border-radius: 8px;
  color: var(--text-soft);
  font-size: 1rem;
  line-height: 1;
}
.tray-cal__arrow:hover { background: var(--glass-hover); color: var(--text); }
.tray-cal__month { font-size: 0.82rem; font-weight: 700; }

.tray-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 0.15rem; }
.tray-cal__grid--head { margin-bottom: 0.2rem; }
.tray-cal__weekday {
  text-align: center;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--brand);
  padding-bottom: 0.2rem;
}
.tray-cal__cell {
  aspect-ratio: 1;
  min-height: 0;
  display: grid;
  place-items: center;
  border-radius: 8px;
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}
.tray-cal__cell.is-blank { visibility: hidden; }
.tray-cal__cell.is-weekend { color: var(--down); }
.tray-cal__cell.is-today {
  background: var(--brand);
  color: var(--brand-contrast);
  font-weight: 800;
}
.tray-cal__today {
  display: block;
  width: 100%;
  margin-top: 0.6rem;
  padding: 0.35rem;
  border-radius: 9px;
  font-size: 0.72rem;
  color: var(--brand);
  background: color-mix(in srgb, var(--brand) 12%, transparent);
}

/* ---------- weather panel ---------- */
.tray-wx__head { display: flex; align-items: center; gap: 0.7rem; margin-bottom: 0.35rem; }
.tray-wx__glyph svg { width: 3.2rem; height: 3.2rem; }
.tray-wx__temp { font-size: 1.9rem; font-weight: 800; line-height: 1.1; color: var(--text-strong); }
.tray-wx__desc { font-size: 0.76rem; color: var(--text-soft); }
.tray-wx__city { font-size: 0.74rem; color: var(--text-soft); margin-bottom: 0.6rem; }
.tray-wx__rows { display: flex; flex-direction: column; gap: 0.35rem; padding-top: 0.6rem; border-top: 1px solid var(--divider); }
.tray-wx__row { display: flex; justify-content: space-between; font-size: 0.76rem; }
.tray-wx__row b { font-weight: 700; }

/* The tray used to be dropped on phones for want of room. It now has a
   place of its own at the far end of the bar, so it stays. */

/* ---------- clock panel: local reference, then the session card ------ */
.tray-local {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  padding-bottom: 0.85rem;
  margin-bottom: 0.85rem;
  border-bottom: 1px solid var(--divider);
}
.tray-local__text { text-align: start; }
.tray-local__time {
  display: block;
  font-size: 1.55rem;
  font-weight: 800;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}
.tray-local__label { font-size: 0.7rem; color: var(--text-soft); }

.tray-face { width: 4.6rem; height: 4.6rem; flex-shrink: 0; }
.tray-face__disc {
  fill: rgba(255, 255, 255, 0.35);
  stroke: var(--divider);
  stroke-width: 1.5;
}
html.dark .tray-face__disc { fill: rgba(255, 255, 255, 0.05); }
.tray-face__tick { stroke: currentColor; stroke-width: 1.6; opacity: 0.3; stroke-linecap: round; }
.tray-face__tick.is-major { opacity: 0.6; stroke-width: 2.4; }
.tray-face__hour,
.tray-face__minute {
  stroke: var(--text-strong);
  stroke-linecap: round;
  stroke-width: 4;
  transition: transform 0.3s cubic-bezier(0.34, 1.4, 0.64, 1);
}
.tray-face__minute { stroke-width: 3; }
.tray-face__second {
  stroke: var(--down);
  stroke-width: 1.6;
  stroke-linecap: round;
  transition: transform 0.15s cubic-bezier(0.34, 1.5, 0.64, 1);
}
.tray-face__pin { fill: var(--down); }

/* The market-hours card, brought into the panel unchanged in spirit. */
.tray-status {
  padding: 0.35rem 0.7rem;
  margin-bottom: 0.75rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-soft);
  background: rgba(148, 163, 184, 0.16);
}
.tray-status.is-open { color: #15803d; background: rgba(34, 197, 94, 0.16); }
html.dark .tray-status.is-open { color: #4ade80; }

.tray-session {
  --session-tone: var(--brand);
  text-align: start;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease);
}
.tray-session.is-in { opacity: 1; transform: none; }
.tray-session:not(.is-open) { filter: saturate(0.6); }

.tray-session__head { display: flex; align-items: center; gap: 0.45rem; font-size: 0.82rem; margin-bottom: 0.45rem; }
.tray-session__dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--session-tone); flex-shrink: 0; }
.tray-session.is-open .tray-session__dot {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--session-tone) 28%, transparent);
}
.tray-session__name { font-weight: 700; flex: 1; }
.tray-session__hours {
  font-size: 0.72rem;
  color: var(--text-soft);
  direction: ltr;
  unicode-bidi: isolate;
  font-variant-numeric: tabular-nums;
}
.tray-session__track { height: 0.32rem; border-radius: 999px; background: var(--divider); overflow: hidden; }
.tray-session__fill { height: 100%; border-radius: 999px; background: var(--session-tone); transition: width 0.6s ease; }
.tray-session__foot { display: flex; justify-content: space-between; margin-top: 0.35rem; }
.tray-session__note { font-size: 0.68rem; color: var(--text-soft); }
.tray-session__zone { font-size: 0.64rem; color: var(--text-soft); direction: ltr; }

.tray-dots { display: flex; justify-content: center; gap: 0.3rem; padding-top: 0.7rem; }
.tray-pip {
  width: 0.4rem; height: 0.4rem;
  border-radius: 999px;
  background: var(--divider);
  transition: width 0.25s var(--ease), background-color 0.25s var(--ease);
}
.tray-pip.is-active { width: 1.05rem; background: var(--brand); }

/* ---------- weather panel, centred ---------- */
.tray-wx__head { justify-content: center; }
.tray-wx__city { text-align: center; }
.tray-wx__rows { text-align: start; }

/* ==================================================================
   Desktop shortcuts
   Apps a visitor has pinned. Laid out in columns down the leading edge,
   under the cards so a shortcut never covers one.
   ================================================================== */
.shortcut-layer {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

.shortcut {
  position: absolute;
  width: 76px;
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.2rem;
  border-radius: 12px;
  border: 1px solid transparent;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}
.shortcut { cursor: grab; touch-action: none; }
.shortcut.is-dragging { cursor: grabbing; opacity: 0.85; transition: none; }
.shortcut:hover { background: rgba(255, 255, 255, 0.14); }
html.dark .shortcut:hover { background: rgba(255, 255, 255, 0.08); }
.shortcut.is-selected {
  background: rgba(255, 255, 255, 0.22);
  border-color: var(--glass-border);
}
html.dark .shortcut.is-selected { background: rgba(255, 255, 255, 0.12); }

.shortcut__icon {
  --tile-tint: var(--tile-accent, var(--brand));
  width: 2.6rem;
  height: 2.6rem;
  display: grid;
  place-items: center;
  border-radius: 13px;
  color: var(--tile-tint);
  background: color-mix(in srgb, var(--tile-tint) 16%, rgba(255, 255, 255, 0.35));
  border: 1px solid color-mix(in srgb, var(--tile-tint) 24%, transparent);
}
html.dark .shortcut__icon {
  background: color-mix(in srgb, var(--tile-tint) 22%, rgba(0, 0, 0, 0.25));
}
.shortcut__icon svg,
.shortcut__icon img { width: 1.6rem; height: 1.6rem; }

.shortcut__label {
  font-size: 0.68rem;
  line-height: 1.5;
  text-align: center;
  color: var(--text-strong);
  /* Two lines at most; a long app name should not push the next row. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}
html.dark .shortcut__label { text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6); }

#shortcut-menu { min-width: 11rem; }

/* Shortcuts are a pointer idea; on a phone the start menu is the way in. */
@media (max-width: 767px) {
  .shortcut-layer { display: none; }
}

/* ==================================================================
   Phones

   The bar at the foot is the whole interaction model on a phone, so it
   is built here as one fixed row rather than three absolutely-positioned
   groups that each guessed at an offset — which is how they came to sit
   on top of each other.

   Reading order in Persian (right to left):
     right   notifications, language, light/dark
     centre  start, search
     left    weather, calendar, world clock
   In English and Turkish the whole row mirrors, because every offset is
   a logical property rather than a physical one.
   ================================================================== */
@media (max-width: 767px) {
  /* Room for the bar plus the phone's own gesture area, so the last card
     is never trapped underneath it. */
  #desktop {
    padding: 1.25rem 0.75rem calc(6.5rem + env(safe-area-inset-bottom, 0px));
  }

  /*
   * One row, three clusters, space-between.
   *
   * The groups stop being absolutely positioned here — that was the whole
   * source of the overlap, since each was placed from a different edge
   * with no knowledge of how wide the others had grown. As flex children
   * they simply cannot overlap: the row divides the width between them.
   */
  .taskbar {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    top: auto;
    width: auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.35rem;
    padding: 0.4rem 0.6rem calc(0.4rem + env(safe-area-inset-bottom, 0px));
    pointer-events: auto;
    background: var(--glass-bg);
    border-top: 1px solid var(--glass-border);
    -webkit-backdrop-filter: blur(var(--glass-blur));
    backdrop-filter: blur(var(--glass-blur));
    box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.16);
  }

  .taskbar__group {
    position: static;
    inset: auto;
    transform: none;
    gap: 0.3rem;
    align-items: center;
  }

  /* The social row has its own card further up the page. */
  .taskbar__group--left { display: none; }

  /* Dissolved so its children become clusters of the bar itself and can
     be ordered independently of one another. */
  .taskbar__group--right { display: contents; }

  .taskbar__cluster { order: 1; gap: 0.3rem; }
  .taskbar__group--center { order: 2; }
  #taskbar-tray { order: 3; display: flex; }

  /* Each cluster is its own floating dock rather than one long bar of
     separate pills — fewer edges, and the three read as three groups. */
  .taskbar__dock,
  .taskbar__cluster {
    padding: 0.25rem;
    border-radius: 999px;
  }

  /*
   * Control size, solved rather than guessed.
   *
   * Measured, not estimated. At a 40px button the three clusters come to
   * 377px, and the gaps and padding around and inside them add 94px more
   * — so the bar needs 8.05 buttons plus 94px of everything else. Turn
   * that round and the largest button a given screen can hold is
   * (width - 94px) / 8.05, which is what this says. Clamped to 40px
   * where there is room to spare, and never below 28px.
   *
   * Deriving it this way means a narrower phone than any I checked still
   * fits, instead of needing another breakpoint each time one turns up.
   *
   * 40px is under Apple's 44px guidance on paper, but that guidance is
   * about the touch target, and the padding around each button inside
   * its dock carries the rest.
   */
  .taskbar {
    --bar-btn: clamp(1.75rem, calc((100vw - 6.4rem) / 8.05), 2.5rem);
  }

  .taskbar .icon-btn,
  .taskbar .notif-btn,
  .taskbar .lang-btn,
  .taskbar .tray-btn {
    width: var(--bar-btn);
    height: var(--bar-btn);
    min-width: 0;
    min-height: 0;
    border-radius: 999px;
  }
  .taskbar__group--center .icon-btn {
    width: calc(var(--bar-btn) + 0.1rem);
    height: calc(var(--bar-btn) + 0.1rem);
  }
  .taskbar__group--center .icon-btn img,
  .taskbar__group--center .icon-btn > svg,
  .taskbar__group--center .icon-btn .icon-svg,
  .taskbar__group--center .icon-btn .icon-svg svg,
  .taskbar__group--center .start-btn svg {
    width: calc(var(--bar-btn) * 0.56);
    height: calc(var(--bar-btn) * 0.56);
  }
  .taskbar .notif-btn svg,
  .taskbar .tray-btn svg,
  .taskbar .tray-btn .tray-weather__icon svg {
    width: calc(var(--bar-btn) * 0.52);
    height: calc(var(--bar-btn) * 0.52);
  }
  .taskbar .lang-btn { font-size: calc(var(--bar-btn) * 0.31); }

  /* The notification and language buttons sit inside the cluster's own
     glass now, so their individual panes would be glass on glass. */
  .taskbar__cluster .notif-btn,
  .taskbar__cluster .lang-btn,
  .taskbar__cluster .theme-dock {
    background: transparent;
    border-color: transparent;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .taskbar__cluster .theme-dock { padding: 0 0.15rem; }

  /* The switch is a control like the others, so it scales with them.
     Its knob and its travel are both fractions of the track, which keeps
     the geometry right at every size instead of only at one. */
  .taskbar .switch {
    width: calc(var(--bar-btn) * 1.05);
    height: calc(var(--bar-btn) * 0.6);
  }
  .taskbar .switch__track::before {
    width: calc(var(--bar-btn) * 0.4);
    height: calc(var(--bar-btn) * 0.4);
    top: calc(var(--bar-btn) * 0.1);
    inset-inline-start: calc(var(--bar-btn) * 0.1);
    background-size: calc(var(--bar-btn) * 0.26);
  }
  .taskbar .switch input:checked + .switch__track::before {
    transform: translateX(calc(var(--bar-btn) * 0.45));
  }
  html[dir='rtl'] .taskbar .switch input:checked + .switch__track::before {
    transform: translateX(calc(var(--bar-btn) * -0.45));
  }

  .card__title { padding: 0.85rem 1rem; font-size: 0.92rem; }

  /* ---------------------------------------------------------------
     Panels open above the icon that opened them.

     Every panel is fixed to the viewport and gets its inline offset
     from script (ui/popover.js), which measures the button and clamps
     the panel to the screen edge. The values here are only what the
     first paint needs before that runs.
     --------------------------------------------------------------- */
  .popover {
    position: fixed;
    inset-inline: auto;
    bottom: calc(4.6rem + env(safe-area-inset-bottom, 0px));
    width: min(21rem, calc(100vw - 1.5rem));
    max-height: calc(100vh - 8rem);
    transform-origin: var(--pop-origin-x, 50%) bottom;
  }

  /* Start and search are the way around the site, so they keep the full
     width and stay centred — they are not anchored to a small icon. */
  .panel-bottom-center,
  .panel-bottom-center.is-hidden {
    inset-inline: 0.6rem;
    width: auto;
    height: auto;
    max-height: 68vh;
    left: auto;
    right: auto;
    transform: none;
  }
  .panel-bottom-center.is-hidden { transform: translateY(14px) scale(0.96); }
  .panel-body { padding: 1rem; }

  .app-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.1rem 0.75rem; }
  .app-tile { padding: 0.55rem 0.25rem; }
  .app-tile__name { font-size: 0.7rem; }

  .tabs { gap: 0.25rem; }
  .tabs button { padding: 0.6rem 0.85rem; }

  /* The tray panels are the same family as the rest now, so they take
     their width and their anchoring from the shared rule above. */
  .tray-panel,
  .tray-panel--wide { width: min(19rem, calc(100vw - 1.5rem)); }

  /*
   * Windows are fixed, not absolute.
   *
   * Absolute meant they were placed against the document, while the
   * script positions them from viewport coordinates — so opening an app
   * halfway down the page put the window off at the top and the page
   * appeared to jump there. Fixed makes the two agree.
   */
  .window {
    position: fixed;
    inset-inline: 0.6rem !important;
    width: auto !important;
    max-height: calc(100dvh - 9rem);
    resize: none;
  }
  .window__resize { display: none; }

  /* Hover-only reveals never appear on touch, so they are always shown. */
  .widget .card__title { opacity: 1; }
}

/* Very small phones: two app columns rather than three. */
@media (max-width: 380px) {
  .app-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The unread badge shrinks with the button it sits on. */
@media (max-width: 767px) {
  .taskbar .notif-btn__count {
    top: calc(var(--bar-btn) * 0.06);
    inset-inline-end: calc(var(--bar-btn) * 0.06);
    min-width: calc(var(--bar-btn) * 0.4);
    height: calc(var(--bar-btn) * 0.4);
    font-size: calc(var(--bar-btn) * 0.24);
    line-height: calc(var(--bar-btn) * 0.4);
  }
}

/* Context menu entries: an icon, a label, and a separator between the
   things that open something and the things that change the desktop. */
.menu__item {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  width: 100%;
  padding: 0.5rem 0.75rem;
  border-radius: 9px;
  font-size: 0.8rem;
  text-align: start;
  color: var(--text);
  transition: background-color 0.14s ease, color 0.14s ease;
}
.menu__item:hover { background: var(--glass-hover); }
.menu__item svg { flex-shrink: 0; opacity: 0.75; }
.menu__item--danger { color: var(--down); }
.menu__item--danger:hover { background: color-mix(in srgb, var(--down) 12%, transparent); }
.menu__sep { height: 1px; margin: 0.3rem 0.4rem; background: var(--divider); }

/* The symbolic password types itself in; a caret while it does. */
#password-input[data-symbolic] {
  letter-spacing: 0.12em;
  font-family: ui-monospace, Menlo, monospace;
}
#password-input[data-symbolic]:not(.is-typed) {
  border-inline-end: 2px solid var(--brand);
  animation: caret-blink 0.9s step-end infinite;
}
@keyframes caret-blink {
  50% { border-inline-end-color: transparent; }
}

/* Rename box for a desktop shortcut. Centred rather than anchored to the
   icon, so it never lands off the edge of the screen. */
.rename {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3000;
  width: min(20rem, calc(100vw - 2rem));
  padding: 1.1rem;
  border-radius: 18px;
  box-shadow: var(--shadow-lg);
}
.rename__label { display: block; font-size: 0.78rem; font-weight: 600; margin-bottom: 0.5rem; }
.rename__input {
  width: 100%;
  padding: 0.6rem 0.75rem;
  border-radius: 10px;
  font-size: 0.85rem;
  color: var(--text);
  background: rgba(255, 255, 255, 0.55);
  border: 1.5px solid var(--divider);
}
html.dark .rename__input { background: rgba(255, 255, 255, 0.08); }
.rename__input:focus { outline: none; border-color: var(--brand); }
.rename__actions { display: flex; justify-content: flex-end; gap: 0.45rem; margin-top: 0.85rem; }
.rename__btn {
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  font-size: 0.78rem;
  color: var(--text-soft);
}
.rename__btn:hover { background: var(--glass-hover); color: var(--text); }
.rename__btn--primary { background: var(--brand); color: var(--brand-contrast); font-weight: 600; }
.rename__btn--primary:hover { background: var(--brand); filter: brightness(1.05); }

/* ==================================================================
   Windows grow from whatever opened them
   The origin is set in script to the centre of the icon that was
   clicked; without one it falls back to the middle of the window.
   ================================================================== */
.window {
  transform-origin: var(--origin-x, 50%) var(--origin-y, 50%);
}

@keyframes window-open {
  from { opacity: 0; transform: scale(0.55); }
  to   { opacity: 1; transform: scale(1); }
}
@keyframes window-close {
  from { opacity: 1; transform: scale(1); }
  to   { opacity: 0; transform: scale(0.55); }
}

.window.is-opening { animation: window-open 0.24s cubic-bezier(0.2, 0.9, 0.3, 1); }
.window.is-closing { animation: window-close 0.2s cubic-bezier(0.4, 0, 0.8, 0.4) forwards; }

@media (prefers-reduced-motion: reduce) {
  .window.is-opening, .window.is-closing { animation: none; }
}

/* ==================================================================
   Focus mode — dim everything except the card being read
   ================================================================== */
body.is-focusing .widget:not(.is-focused) {
  opacity: 0.25;
  filter: saturate(0.7);
  transition: opacity 0.25s var(--ease), filter 0.25s var(--ease);
}
body.is-focusing .widget.is-focused {
  transform: scale(1.02);
  transition: transform 0.25s var(--ease);
  z-index: 40;
}

/* The start menu while a context menu is open over it: still visible, so
   the app being acted on stays in view, but clearly not the active layer. */
#start-menu.is-behind-menu {
  filter: blur(3px) saturate(0.85);
  opacity: 0.65;
  pointer-events: none;
  transition: filter 0.18s var(--ease), opacity 0.18s var(--ease);
}

/* ==================================================================
   Ambient layer — a tint over the wallpaper that follows the hour
   Sits above the wallpaper and below everything else, so the chosen
   image still shows through.
   ================================================================== */
#ambient-layer {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: soft-light;
  transition: background 8s linear, opacity 2s linear;
}

@media (prefers-reduced-motion: reduce) {
  #ambient-layer { transition: none; }
}
