/* ==========================================================================
   KALAN OS 5.1  --  pixel desktop
   Design rules, do not break these:
     * no border-radius anywhere
     * no smooth easing -- use steps() or nothing
     * everything sits on a 2px grid
     * no blur, no soft shadows (only hard 0-blur offset shadows)
   ========================================================================== */

:root {
  --ink: #0d0d16;
  --face: #c3c3d6;
  --face-lt: #e9e9f6;
  --face-dk: #7a7a94;
  --face-dkr: #43435c;
  --desk-a: #16162b;
  --desk-b: #1d1d38;
  --desk-c: #232348;
  --accent: #22d3ee;
  --bar: 34px;
  --u: 2px;

  --bevel-out: inset calc(var(--u) * -1) calc(var(--u) * -1) 0 var(--face-dkr),
    inset var(--u) var(--u) 0 var(--face-lt);
  --bevel-in: inset var(--u) var(--u) 0 var(--face-dkr),
    inset calc(var(--u) * -1) calc(var(--u) * -1) 0 var(--face-lt);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  border-radius: 0 !important;
}

/* The hidden attribute only sets display:none at user-agent priority, so any
   author rule with a display value (.start-menu, .desktop) silently
   overrode it and left those panels permanently on screen. Keep the attribute
   authoritative -- os.js toggles hidden to open and close panels. */
[hidden] {
  display: none !important;
}

html,
body {
  height: 100%;
  overflow: hidden;
  background: var(--ink);
  color: var(--face);
  font-family: 'VT323', 'Courier New', monospace;
  font-size: 18px;
  -webkit-font-smoothing: none;
  font-smooth: never;
  text-rendering: geometricPrecision;
  overscroll-behavior: none;
}

.pix {
  shape-rendering: crispEdges;
  image-rendering: pixelated;
  display: block;
}

.pixel-font {
  font-family: 'Press Start 2P', 'VT323', monospace;
}

/* ===================== BOOT ===================== */
.boot {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background: #05050a;
  color: #4ade80;
  padding: 6vh 5vw;
  display: flex;
  flex-direction: column;
  gap: 18px;
  cursor: pointer;
}

.boot.done {
  animation: boot-out 260ms steps(3) forwards;
}

@keyframes boot-out {
  to {
    opacity: 0;
    visibility: hidden;
  }
}

.boot-log {
  font: inherit;
  font-size: clamp(15px, 2.1vw, 24px);
  line-height: 1.35;
  white-space: pre-wrap;
  text-shadow: 0 0 6px #15803d, 0 2px 0 #052e16;
  flex: 1;
  overflow: hidden;
}

.boot-log .ok {
  color: #4ade80;
}

.boot-log .warn {
  color: #facc15;
}

.boot-bar-wrap {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: clamp(14px, 1.8vw, 20px);
}

.boot-bar {
  flex: 1;
  height: 22px;
  border: 2px solid #22d3ee;
  background: #05201f;
  padding: 3px;
  box-shadow: 0 0 0 2px #042020;
}

.boot-bar i {
  display: block;
  height: 100%;
  width: 0;
  background: repeating-linear-gradient(90deg, #22d3ee 0 10px, #0e7490 10px 14px);
}

.boot-pct {
  min-width: 5ch;
  color: #22d3ee;
  text-align: right;
}

.boot-skip {
  font-size: clamp(12px, 1.5vw, 16px);
  color: #3f6b52;
  animation: blink 1.1s steps(1) infinite;
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

/* ===================== DESKTOP ===================== */
.desktop {
  position: fixed;
  inset: 0;
  padding-bottom: var(--bar);
  isolation: isolate;
}

.wallpaper {
  position: absolute;
  inset: 0;
  background: var(--desk-a);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Crect width='8' height='8' fill='%2316162b'/%3E%3Crect width='4' height='4' fill='%231d1d38'/%3E%3Crect x='4' y='4' width='4' height='4' fill='%231d1d38'/%3E%3C/svg%3E");
}

.wallpaper-logo {
  position: absolute;
  left: 50%;
  top: 44%;
  transform: translate(-50%, -50%);
  text-align: center;
  pointer-events: none;
  user-select: none;
  opacity: 0.1;
}

.wallpaper-logo span {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: clamp(34px, 11vw, 132px);
  line-height: 1;
  letter-spacing: 0.02em;
  color: #7dd3fc;
  text-shadow: 6px 6px 0 #2a2a5e;
}

.wallpaper-sub {
  margin-top: 14px !important;
  font-size: clamp(11px, 2.4vw, 24px) !important;
  color: #c084fc !important;
  letter-spacing: 0.5em !important;
  text-shadow: 3px 3px 0 #2a2a5e !important;
}

.vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 45%,
      transparent 40%, rgba(5, 5, 15, 0.62) 100%);
}

.scanlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.14;
  background: repeating-linear-gradient(180deg,
      rgba(0, 0, 0, 0.5) 0 1px, transparent 1px 3px);
  mix-blend-mode: multiply;
}

/* ===================== DESKTOP ICONS ===================== */
/* .desktop reserves --bar of padding for the taskbar. These children are
   absolutely positioned, which resolves against the padding box, so they have
   to subtract the taskbar height themselves or they slide underneath it. */
.icons {
  position: absolute;
  inset: 12px 12px calc(var(--bar) + 12px) 12px;
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(6, minmax(0, 1fr));
  justify-content: start;
  gap: 6px 16px;
  align-content: start;
  overflow: hidden;
}

/* Fewer icons per column on short screens, so a row can never squeeze under
   104px and collide with the taskbar. */
@media (max-height: 700px) {
  .icons {
    grid-template-rows: repeat(5, minmax(0, 1fr));
  }
}

@media (max-height: 600px) {
  .icons {
    grid-template-rows: repeat(4, minmax(0, 1fr));
  }
}

@media (max-height: 480px) {
  .icons {
    grid-template-rows: repeat(3, minmax(0, 1fr));
  }
}

.dicon {
  position: relative;
  width: 96px;
  min-height: 0;
  /* Size to content rather than stretching to the 1fr grid row. A stretched
     item is ~110px tall, but the same icon once absolutely positioned is
     content-height, so the box would shrink under the cursor on pickup. */
  align-self: start;
  height: auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 5px 3px;
  background: none;
  border: 2px solid transparent;
  color: #e9e9f6;
  font: inherit;
  font-size: 17px;
  line-height: 1.05;
  text-align: center;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* Icons are draggable, so the browser must not claim the gesture for
     scrolling or native image dragging. */
  touch-action: none;
  -webkit-user-drag: none;
}

.dicon .art svg {
  -webkit-user-drag: none;
  user-select: none;
  pointer-events: none;
}

/* Lifted while being dragged, and parked by os.js once dropped. */
.dicon.dragging {
  z-index: 5;
  cursor: grabbing;
  background: #3a3a6e;
  border-color: var(--face-lt);
}

.dicon.placed {
  position: absolute;
}

.dicon .art {
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  filter: drop-shadow(2px 2px 0 rgba(0, 0, 0, 0.55));
  transition: transform 90ms steps(2);
}

.dicon .art svg {
  width: 100%;
  height: 100%;
}

.dicon .lbl {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
  text-shadow: 1px 1px 0 #000, 0 0 3px #000;
}

/* Solid blocks, not translucent washes. A translucent highlight picks up the
   wallpaper gradient behind it and reads as a soft glow, which is the one
   thing this design language never uses. */
.dicon:hover {
  border-color: #8a8ab5;
  background: #26264a;
}

.dicon:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.dicon.sel {
  border-color: var(--accent);
  background: #12414d;
}

/* Rubber-band selection box. Solid fill, dashed edge, no blur or round corners.
   Sits above the window layer (which tops out in the tens) but below the
   taskbar at 400, so the band stays readable even when swept over a window. */
.marquee {
  position: absolute;
  z-index: 390;
  pointer-events: none;
  background: rgba(34, 211, 238, 0.14);
  border: 2px dashed var(--accent);
}

/* Sweeping the background reads as a drag, not a click. */
.desktop.banding,
.desktop.banding .wallpaper,
.desktop.banding .icons {
  cursor: crosshair;
}

.dicon:active .art {
  transform: scale(0.85);
}

.dicon .playcount {
  position: absolute;
  right: 2px;
  top: 2px;
  padding: 0 4px;
  background: var(--ink);
  color: var(--accent);
  font-size: 14px;
  line-height: 16px;
  letter-spacing: 0.04em;
  box-shadow: 0 0 0 2px #10101f;
}

/* ===================== WINDOWS ===================== */
.window-layer {
  position: absolute;
  inset: 0 0 var(--bar) 0;
  pointer-events: none;
  overflow: hidden;
}

.win {
  position: absolute;
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  min-width: 260px;
  min-height: 180px;
  background: var(--face);
  border: 2px solid var(--ink);
  box-shadow: var(--bevel-out), 6px 6px 0 rgba(0, 0, 0, 0.45);
  animation: win-in 120ms steps(3);
}

@keyframes win-in {
  from {
    transform: scale(0.86);
    opacity: 0;
  }
}

.win.min {
  display: none;
}

.win.max {
  border: 0;
  box-shadow: none;
}

.win.max .win-title {
  padding-left: 6px;
}

.win.dragging,
.win.dragging * {
  user-select: none;
  cursor: grabbing !important;
}

.win-title {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 3px 0 5px;
  background: var(--face-dk);
  color: #16162b;
  cursor: grab;
  flex: 0 0 auto;
  user-select: none;
}

.win.active .win-title {
  background: var(--accent);
  color: #0b0b12;
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.35);
}

.win-title .wt-icon {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
}

.win-title .wt-icon svg {
  width: 100%;
  height: 100%;
}

.win-name {
  flex: 1;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: clip;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.win-btns {
  display: flex;
  gap: 2px;
  flex: 0 0 auto;
}

.wb {
  width: 18px;
  height: 16px;
  display: grid;
  place-items: center;
  background: var(--face);
  border: 0;
  box-shadow: var(--bevel-out);
  cursor: pointer;
  padding: 0;
}

.wb:active {
  box-shadow: var(--bevel-in);
}

.wb::before {
  content: '';
  display: block;
  background: var(--ink);
}

.wb.min::before {
  width: 8px;
  height: 3px;
  margin-top: 6px;
}

.wb.max::before {
  width: 9px;
  height: 9px;
  background: var(--ink);
  box-shadow: inset 0 0 0 2px var(--face);
}

/* hard-edged X, drawn as a clip-path so nothing anti-aliases */
.wb.close::after {
  content: '';
  width: 11px;
  height: 11px;
  background: var(--ink);
  clip-path: polygon(0 0, 26% 0, 50% 24%, 74% 0, 100% 0, 62% 50%, 100% 100%, 74% 100%, 50% 76%, 26% 100%, 0 100%, 38% 50%);
}

.wb.close:hover {
  background: #ef4444;
}

.wb.close:hover::after {
  background: #fff;
}

.win-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: #0b0b14;
}

.win-strip {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 22px;
  padding: 0 5px;
  background: var(--face-dk);
  color: #16162b;
  font-size: 16px;
  overflow: hidden;
}

.win-strip .cat {
  padding: 0 5px;
  background: var(--ink);
  color: var(--face);
  font-size: 14px;
  letter-spacing: 0.04em;
  flex: 0 0 auto;
}

.win-strip .msg {
  flex: 1;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  opacity: 0.85;
}

.win-strip .grow {
  flex: 1;
}

.load {
  flex: 0 0 auto;
  height: 6px;
  background: #2a2a45;
}

.load i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--accent);
  transition: width 140ms linear;
}

.win-frame {
  flex: 1;
  position: relative;
  min-height: 0;
  background: #0b0b14;
}

.win-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  background: #0b0b14;
}

.win-frame.loading::after {
  content: 'LOADING...';
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--face-dk);
  font-size: 20px;
  letter-spacing: 0.2em;
  background: repeating-linear-gradient(45deg,
      #0b0b14 0 8px, #10101f 8px 16px);
}

.win-error {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 20px;
  text-align: center;
  background: #16162b;
  color: #e9e9f6;
}

.win-error h3 {
  font-family: 'Press Start 2P', monospace;
  font-size: 11px;
  color: #ef4444;
  line-height: 1.6;
}

.win-error p {
  font-size: 17px;
  opacity: 0.8;
  max-width: 34ch;
}

.px-btn {
  font: inherit;
  font-size: 17px;
  padding: 4px 12px;
  background: var(--face);
  color: var(--ink);
  border: 0;
  box-shadow: var(--bevel-out);
  cursor: pointer;
}

.px-btn:hover {
  background: #fff;
}

.px-btn:active {
  box-shadow: var(--bevel-in);
}

.px-btn.alt {
  background: #1b1b33;
  color: var(--face);
  box-shadow: 2px 2px 0 #000, inset 1px 1px 0 #3d3d63,
    inset -1px -1px 0 #0a0a14;
}

.px-btn.alt:hover {
  background: #262645;
  color: #fff;
}

.px-btn.mini {
  flex: 0 0 auto;
  font-size: 15px;
  line-height: 18px;
  padding: 0 7px;
  color: #16162b;
}

.px-btn.mini:hover {
  background: #fff;
}

/* Eight handles, so a window can be grown from any side. The four corners
   keep the original hatched grip; the edges are thin strips. */
.win-grip {
  position: absolute;
  z-index: 3;
  touch-action: none;
}

.win-grip[data-dir="se"],
.win-grip[data-dir="ne"] {
  right: 0;
  width: 16px;
  height: 16px;
  background: repeating-linear-gradient(135deg,
      transparent 0 3px, rgba(13, 13, 22, 0.55) 3px 5px);
}

.win-grip[data-dir="se"],
.win-grip[data-dir="sw"] {
  bottom: 0;
  height: 16px;
}

.win-grip[data-dir="ne"] {
  top: 0;
  cursor: nesw-resize;
}

.win-grip[data-dir="se"] {
  cursor: nwse-resize;
}

.win-grip[data-dir="nw"],
.win-grip[data-dir="sw"] {
  left: 0;
  width: 16px;
  height: 16px;
  background: repeating-linear-gradient(45deg,
      transparent 0 3px, rgba(13, 13, 22, 0.55) 3px 5px);
}

.win-grip[data-dir="nw"] {
  top: 0;
  cursor: nwse-resize;
}

.win-grip[data-dir="sw"] {
  bottom: 0;
  cursor: nesw-resize;
}

.win-grip[data-dir="n"],
.win-grip[data-dir="s"] {
  left: 16px;
  right: 16px;
  height: 6px;
  cursor: ns-resize;
}

.win-grip[data-dir="n"] {
  top: 0;
}

.win-grip[data-dir="s"] {
  bottom: 0;
}

.win-grip[data-dir="w"],
.win-grip[data-dir="e"] {
  top: 16px;
  bottom: 16px;
  width: 6px;
  cursor: ew-resize;
}

.win-grip[data-dir="w"] {
  left: 0;
}

.win-grip[data-dir="e"] {
  right: 0;
}

/* Maximised windows keep their handles so an edge drag can restore them, but
   drop the hatching so a full-bleed window is not framed. */
.win.max .win-grip {
  background: none;
}

.win.resizing,
.win.resizing * {
  user-select: none;
}

/* ===================== TASKBAR ===================== */
.taskbar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--bar);
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 4px;
  background: var(--face);
  border-top: 2px solid var(--face-lt);
  box-shadow: inset 0 2px 0 var(--face-lt);
  z-index: 400;
}

.start-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 9px 0 7px;
  background: var(--face);
  border: 0;
  box-shadow: var(--bevel-out);
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.05em;
  cursor: pointer;
  flex: 0 0 auto;
}

.start-btn:active,
.start-btn[aria-expanded='true'] {
  box-shadow: var(--bevel-in);
}

.start-glyph {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
  background: conic-gradient(from 45deg,
      #ef4444 0 25%, #4ade80 0 50%, #60a5fa 0 75%, #facc15 0);
  image-rendering: pixelated;
}

.start-glyph::after {
  content: '';
  display: block;
  width: 4px;
  height: 4px;
  margin: 5px;
  background: var(--ink);
}

.task-items {
  flex: 1;
  display: flex;
  gap: 3px;
  overflow: hidden;
  min-width: 0;
}

.task-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  max-width: 168px;
  height: 26px;
  padding: 0 8px 0 5px;
  background: var(--face);
  border: 0;
  box-shadow: var(--bevel-in);
  color: #4a4a63;
  font: inherit;
  font-size: 17px;
  cursor: pointer;
}

.task-btn svg {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
}

.task-btn span {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.task-btn.active {
  box-shadow: var(--bevel-out);
  color: var(--ink);
  background: var(--face-lt);
  font-weight: 700;
}

.tray {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 26px;
  padding: 0 8px;
  flex: 0 0 auto;
  box-shadow: var(--bevel-in);
  color: #3a3a55;
  font-size: 17px;
}

.tray-count {
  letter-spacing: 0.04em;
  opacity: 0.75;
}

.tray-clock {
  min-width: 5ch;
  text-align: right;
  color: var(--ink);
  font-weight: 700;
}

/* ===================== MENUS ===================== */
.menu {
  position: absolute;
  z-index: 600;
  background: var(--face);
  border: 2px solid var(--ink);
  box-shadow: var(--bevel-out), 6px 6px 0 rgba(0, 0, 0, 0.45);
  color: var(--ink);
  padding: 3px;
}

.start-menu {
  left: 4px;
  bottom: calc(var(--bar) + 2px);
  width: 254px;
  display: flex;
  flex-direction: column;
}

.start-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
  width: 100%;
  padding: 6px 8px;
  margin-bottom: 3px;
  background: linear-gradient(90deg, #1d4ed8, #0e7490);
  color: #fff;
  font: inherit;
  text-align: left;
  border: 0;
  /* This is the arcade door. Nothing about it says "secret", but hovering it
     has to feel different from hovering a dead label. */
  cursor: pointer;
}

.start-head:hover,
.start-head:focus-visible {
  background: linear-gradient(90deg, #2563eb, #0891b2);
  outline: none;
  box-shadow: inset 0 0 0 2px #22d3ee, 0 0 12px rgba(34, 211, 238, 0.6);
}

.start-head:active {
  box-shadow: inset 0 0 0 2px #0b0b12;
}

.start-head-name {
  font-family: 'Press Start 2P', monospace;
  font-size: 13px;
  text-shadow: 2px 2px 0 #0b0b12;
}

.start-head-ver {
  font-size: 15px;
  opacity: 0.85;
}

.start-scroll {
  max-height: min(58vh, 460px);
  overflow-y: auto;
  scrollbar-color: var(--face-dkr) var(--face);
  scrollbar-width: thin;
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 4px 7px;
  background: none;
  border: 0;
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  text-align: left;
  cursor: pointer;
}

.menu-item:hover,
.menu-item:focus-visible {
  background: #1d4ed8;
  color: #fff;
  outline: none;
}

.menu-item .mi-icon {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
}

.menu-item .mi-icon svg {
  width: 100%;
  height: 100%;
}

.mi-glyph {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  background: var(--ink);
}

.mi-about {
  background: var(--ink);
  box-shadow: inset 0 0 0 3px #facc15;
}

/* 2x2 of blocks: icons back in their grid slots */
.mi-reset {
  background:
    linear-gradient(var(--ink) 0 0) 0 0 / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 10px 0 / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 0 10px / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 10px 10px / 6px 6px no-repeat;
}

/* four blocks with the right pair hollowed out, for Select all */
.mi-selectall {
  background:
    linear-gradient(var(--ink) 0 0) 0 0 / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 10px 0 / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 0 10px / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 10px 10px / 6px 6px no-repeat,
    linear-gradient(#c3c3d6 0 0) 0 0 / 6px 6px no-repeat,
    linear-gradient(#c3c3d6 0 0) 0 10px / 6px 6px no-repeat;
}

/* the same shape knocked out entirely, for Clear selection */
.mi-clearsel {
  background:
    linear-gradient(var(--ink) 0 0) 0 0 / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 10px 0 / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 0 10px / 6px 6px no-repeat,
    linear-gradient(var(--ink) 0 0) 10px 10px / 6px 6px no-repeat,
    linear-gradient(var(--face-dk) 0 0) 0 0 / 6px 6px no-repeat,
    linear-gradient(var(--face-dk) 0 0) 10px 0 / 6px 6px no-repeat,
    linear-gradient(var(--face-dk) 0 0) 0 10px / 6px 6px no-repeat,
    linear-gradient(var(--face-dk) 0 0) 10px 10px / 6px 6px no-repeat;
}

.mi-reboot {
  background: var(--ink);
  clip-path: polygon(0 0, 60% 0, 60% 30%, 100% 30%, 40% 100%, 40% 65%, 0 65%);
}

.mi-closeall {
  background: var(--ink);
  clip-path: polygon(0 0, 100% 0, 100% 35%, 35% 100%, 0 100%, 0 65%, 65% 0);
}

.ctx-menu {
  min-width: 172px;
}

/* Divider between the launch commands and the layout commands. A div, not a
   button, so it never joins the tab order or the click handlers. */
.mi-sep {
  height: 2px;
  margin: 3px 2px;
  background: var(--face-dkr);
  box-shadow: 0 1px 0 var(--face-lt);
}

/* ===================== BOOT-TIME MODAL CONTENT ===================== */
.about-body {
  flex: 1;
  overflow: auto;
  padding: 18px 20px;
  background: var(--face);
  color: var(--ink);
  font-size: 18px;
  line-height: 1.4;
}

.about-body h4 {
  font-family: 'Press Start 2P', monospace;
  font-size: 12px;
  margin: 18px 0 8px;
  color: #1d4ed8;
}

.about-body h4:first-child {
  margin-top: 0;
}

.about-body p {
  margin-bottom: 8px;
}

.about-body code {
  font-family: inherit;
  background: #a6a6c0;
  padding: 0 4px;
  box-shadow: inset 1px 1px 0 #8a8aa8;
}

.about-body ul {
  margin: 0 0 8px 20px;
}

.about-body li {
  margin-bottom: 3px;
}

.about-body .stat-row {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.stat {
  flex: 1 1 84px;
  padding: 6px 8px;
  background: #d5d5e6;
  box-shadow: var(--bevel-in);
  text-align: center;
}

.stat b {
  display: block;
  font-family: 'Press Start 2P', monospace;
  font-size: 15px;
  color: #1d4ed8;
}

.stat i {
  display: block;
  font-style: normal;
  font-size: 15px;
  color: #55557a;
  margin-top: 4px;
}

/* ===================== EASTER EGG: ARCADE HANDOFF ===================== */
/* Clicking KALAN cross-fades the whole desktop to arcade.png and hands this
   tab over to the arcade. One image, one opacity ramp, nothing else -- the
   image is the transition. */

.portal {
  position: fixed;
  inset: 0;
  z-index: 9500;
  background: #0a0502;
  opacity: 0;
  cursor: progress;
  user-select: none;
}

.portal img {
  display: block;
  width: 100%;
  height: 100%;
  /* The PNG is authored at whatever size it was exported at; cover keeps it
     filling the viewport without distorting it. */
  object-fit: cover;
}

.portal.fade {
  animation: portal-fade 1500ms linear forwards;
}

@keyframes portal-fade {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

/* Deliberately NOT shortened under prefers-reduced-motion. A cross-fade does
   not move anything across the screen, so it is not the kind of motion that
   setting exists to suppress -- and the image is the whole point of the click.
   It was reduced to 1ms before, which made the overlay snap to full opacity
   and the hand-off fire instantly, so the picture was never actually seen. */

/* ===================== CONFETTI ===================== */
.confetti {
  position: fixed;
  z-index: 800;
  width: 8px;
  height: 8px;
  pointer-events: none;
  animation: fall 900ms steps(12) forwards;
}

@keyframes fall {
  to {
    transform: translate(var(--dx), var(--dy)) rotate(360deg);
    opacity: 0;
  }
}

/* ===================== MOBILE ===================== */
@media (max-width: 720px) {
  :root {
    --bar: 40px;
  }

  .icons {
    grid-auto-flow: row;
    grid-template-rows: none;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    justify-content: stretch;
    align-content: start;
    gap: 12px;
    inset: 8px 8px calc(var(--bar) + 8px);
  }

  .dicon {
    width: 100%;
    /* min-height, not height: a fixed 88px clipped the longer game titles
       once the 40px art was added on top of a 3-line label. */
    height: auto;
    min-height: 88px;
    font-size: 15px;
  }

  .dicon .art {
    width: 40px;
    height: 40px;
  }

  .tray-count {
    display: none;
  }

  .start-menu {
    width: min(300px, calc(100vw - 8px));
  }

  .win {
    min-width: 0;
    min-height: 0;
  }

  .task-btn {
    max-width: 96px;
  }

  .wb.max {
    display: block;
  }

  /* Fingers need a wider target than a mouse does. */
  .win-grip[data-dir="n"],
  .win-grip[data-dir="s"] {
    left: 20px;
    right: 20px;
    height: 12px;
  }

  .win-grip[data-dir="w"],
  .win-grip[data-dir="e"] {
    top: 20px;
    bottom: 20px;
    width: 12px;
  }

  .win-grip[data-dir="se"],
  .win-grip[data-dir="ne"],
  .win-grip[data-dir="nw"],
  .win-grip[data-dir="sw"] {
    width: 22px;
    height: 22px;
  }
}

@media (max-height: 520px) {
  .wallpaper-logo {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {

  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    transition-duration: 1ms !important;
  }
}

/* The universal reset above flattens every animation to 1ms, and the arcade
   handoff is the one place that must not be flattened: arcade.png IS the
   transition, so a 1ms fade snaps the image to full opacity and the tab
   leaves without ever showing it. Specificity (0,2,0) beats the universal
   selector, so this wins even though both declarations are !important. */
@media (prefers-reduced-motion: reduce) {
  .portal.fade {
    animation-duration: 1500ms !important;
  }
}
