/* ═══════════════════════════════════════════════════════════════════
   makroOS 1.0 — krogoll.com
   Hand-written CSS. No framework, no preprocessor, no build step.

   Layout is built on an 8px grid because the typefaces are 8x8 and
   8x16 bitmap fonts: they only stay pixel-crisp at exact multiples of
   their native size. Do not use fractional font sizes here.
   ═══════════════════════════════════════════════════════════════════ */

/* ── Typefaces ─────────────────────────────────────────────────────
   The Ultimate Oldschool PC Font Pack v2.2 by VileR (int10h.org),
   CC BY-SA 4.0. See assets/fonts/LICENSE.txt.                      */

@font-face {
  font-family: "VGA";
  src: url("../assets/fonts/WebPlus_IBM_VGA_8x16.woff") format("woff");
  font-weight: normal;
  font-style: normal;
  font-display: block;
}

@font-face {
  font-family: "EGA";
  src: url("../assets/fonts/WebPlus_IBM_EGA_8x8.woff") format("woff");
  font-weight: normal;
  font-style: normal;
  font-display: block;
}

/* ── Palettes ──────────────────────────────────────────────────────
   Two authentic 1-bit / 4-bit display modes.                       */

/* Mind the advance widths, they are not the same:
     --font-ui   EGA 8x8   is square      -> 1 char == font-size wide
     --font-text VGA 8x16  is half-width  -> 1 char == font-size / 2 wide
   So --font-ui costs twice the horizontal room per character. Use it
   only for short chrome labels, never for prose or anything that has to
   fit a fixed-width box. */
:root {
  --menubar-h: 32px;
  --font-ui: "EGA", "Courier New", monospace;
  --font-text: "VGA", "Courier New", monospace;
}

/* 1-bit monochrome — early Macintosh / Windows 1.0 */
:root[data-theme="mono"] {
  --bg: #ffffff;
  --fg: #000000;
  --chrome: #000000;
  --accent: #000000;
  --sel-bg: #000000;
  --sel-fg: #ffffff;
  --desk-bg: #ffffff;
  --desk-ink: #000000;
}

/* IBM CGA, palette 1 high intensity: black / cyan / magenta / white */
:root[data-theme="cga"] {
  --bg: #000000;
  --fg: #ffffff;
  --chrome: #55ffff;
  --accent: #ff55ff;
  --sel-bg: #ff55ff;
  --sel-fg: #000000;
  --desk-bg: #000000;
  --desk-ink: #55ffff;
}

/* ── Reset ─────────────────────────────────────────────────────────*/

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  height: 100%;
}

body {
  overflow: hidden;
  background: var(--desk-bg);
  color: var(--fg);
  font: 16px/24px var(--font-text);
  /* Bitmap fonts must not be antialiased or they turn to mush. */
  -webkit-font-smoothing: none;
  -moz-osx-font-smoothing: unset;
  font-smooth: never;
  text-rendering: optimizeSpeed;
  -webkit-tap-highlight-color: transparent;
}

img,
svg {
  display: block;
  image-rendering: pixelated;
  shape-rendering: crispEdges;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

a {
  color: inherit;
  text-decoration: underline;
}

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ── Boot sequence ─────────────────────────────────────────────────*/

.boot {
  position: fixed;
  inset: 0;
  z-index: 900;
  padding: 24px 16px;
  background: #000;
  color: #aaaaaa;
  font: 16px/24px var(--font-text);
  cursor: pointer;
  overflow: hidden;
}

.boot.done {
  animation: boot-out 0.35s steps(3, end) forwards;
}

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

.boot-log {
  font: inherit;
  white-space: pre-wrap;
}

.boot-log b {
  color: #ffffff;
  font-weight: normal;
}

.boot-cursor::after {
  content: "\2588";
  animation: blink 1s steps(1, end) infinite;
}

/* The Windows 9x hand-off screen, kept in the BIOS greys rather than its
   original amber so it stays inside this site's palette. */
.halt {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 32px;
  padding: 24px;
  text-align: center;
}

/* Author-level display: grid above would otherwise beat the UA rule for
   the hidden attribute, exactly as .win[hidden] has to guard against. */
.halt[hidden] {
  display: none;
}

.halt-msg {
  color: #ffffff;
}

.halt-hint {
  animation: blink 1.4s steps(1, end) infinite;
}

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

/* ── Shell + menu bar ──────────────────────────────────────────────*/

.shell {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.menubar {
  display: flex;
  align-items: stretch;
  flex: 0 0 var(--menubar-h);
  padding: 0 8px;
  background: var(--bg);
  border-bottom: 1px solid var(--chrome);
  box-shadow: 0 1px 0 var(--chrome);
  font: 16px/16px var(--font-ui);
  position: relative;
  z-index: 500;
}

.menu-title {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 12px;
  white-space: nowrap;
}

.menu-title[aria-expanded="true"] {
  background: var(--sel-bg);
  color: var(--sel-fg);
}

.menubar-spacer {
  flex: 1;
}

/* Dotted rules between the menu titles. Drawn rather than typed as "|"
   so the dots land on the doubled EGA pixel grid: 2px on, 2px off over
   16px gives four of them. They sit outside the buttons so the open-menu
   highlight stops at the label rather than swallowing the separator. */
.menu-sep {
  align-self: center;
  width: 2px;
  height: 16px;
  background-image: repeating-linear-gradient(to bottom,
      currentColor 0 2px,
      transparent 2px 4px);
}

.clock {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 12px;
}

/* The date is a field of its own, so it gets two character cells of air.
   AM/PM is part of the time expression and keeps the base single cell,
   which is also why this is a margin rather than a wider gap. */
.clock-date {
  margin-right: 8px;
}

/* Blinking separator, so the clock is visibly live rather than a
   static decoration. */
.clock .colon {
  animation: blink 1s steps(1, end) infinite;
}

/* Pixel mark matching favicon.svg, minus its cyan/magenta panes.
   currentColor means it inverts with the open-menu highlight for free. */
.logo {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  fill: currentColor;
}

.logo-lg {
  width: 32px;
  height: 32px;
  margin: 0 auto 8px;
}

/* Symbol definitions only — never painted directly. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* ── Drop-down menus ───────────────────────────────────────────────*/

/* No padding: the items are cells that butt against the frame, so the
   menu border doubles as the outer wall of the first and last of them. */
.menu {
  position: absolute;
  top: var(--menubar-h);
  z-index: 600;
  min-width: 208px;
  background: var(--bg);
  border: 1px solid var(--chrome);
  box-shadow: 3px 3px 0 var(--chrome);
  font: 16px/16px var(--font-ui);
}

.menu button {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 6px 16px;
  text-align: left;
  white-space: nowrap;
}

.menu button:hover,
.menu button:focus-visible {
  background: var(--sel-bg);
  color: var(--sel-fg);
  outline: 0;
}

/* Every item is a cell divided from its neighbours: the menus draw no
   distinction between related and unrelated actions. */
.menu button+button {
  border-top: 1px solid var(--chrome);
}

/* Bullet marks the active option; reserve its width always so labels
   stay on the same left edge whether ticked or not. */
.menu .tick {
  width: 16px;
  visibility: hidden;
}

.menu button[aria-checked="true"] .tick {
  visibility: visible;
}

/* ── Desktop ───────────────────────────────────────────────────────*/

.desktop {
  position: relative;
  flex: 1;
  overflow: hidden;
  /* 50% dither, 2px cells. Fine enough to read as a shaded field rather
     than a pattern in its own right, and it lets the scanlines above it
     stay visible instead of fighting a coarser grid. */
  background-color: var(--desk-bg);
  background-image: conic-gradient(var(--desk-ink) 0 25%,
      var(--desk-bg) 0 50%,
      var(--desk-ink) 0 75%,
      var(--desk-bg) 0);
  background-size: 4px 4px;
}

/* ── Desktop icons ─────────────────────────────────────────────────*/

.icons {
  position: absolute;
  inset: 16px auto auto 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}

.icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  /* Wide enough for the longest label at 24px: "About Mark" needs 128px. */
  width: 144px;
  padding: 4px;
  font: 16px/16px var(--font-ui);
  color: var(--desk-ink);
  text-align: center;
}

.icon svg {
  width: 56px;
  height: 56px;
  color: var(--desk-ink);
}

.icon .icon-label {
  /* Half-width face: "About Mark" is 88px here versus 168px in EGA,
     which is the difference between fitting the icon and being clipped
     off the left edge of the screen. */
  font-family: var(--font-text);
  font-size: 24px;
  line-height: 24px;
  padding: 2px 4px;
  /* Solid backing so the label stays legible over the dither. */
  background: var(--desk-bg);
  white-space: nowrap;
}

.icon[aria-pressed="true"] svg {
  color: var(--sel-fg);
  background: var(--sel-bg);
}

.icon[aria-pressed="true"] .icon-label {
  background: var(--sel-bg);
  color: var(--sel-fg);
}

/* ── Windows ───────────────────────────────────────────────────────*/

.win {
  position: absolute;
  display: flex;
  flex-direction: column;
  min-width: 272px;
  max-width: calc(100% - 32px);
  max-height: calc(100% - 32px);
  background: var(--bg);
  color: var(--fg);
  /* Double hairline frame + hard offset shadow: no blur existed in 1985. */
  border: 1px solid var(--chrome);
  outline: 1px solid var(--chrome);
  outline-offset: 1px;
  box-shadow: 4px 4px 0 var(--chrome);
}

.win[hidden] {
  display: none;
}

.win-titlebar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 24px;
  padding: 0 6px;
  border-bottom: 1px solid var(--chrome);
  cursor: grab;
  touch-action: none;
  user-select: none;
}

.win.dragging .win-titlebar {
  cursor: grabbing;
}

/* Focused windows get the striped "active" title bar; unfocused ones
   go blank, exactly as System 1 and Windows 1.0 did. */
.win.focused .win-titlebar {
  background-image: repeating-linear-gradient(to bottom,
      var(--chrome) 0 1px,
      transparent 1px 3px);
}

.win-close {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  background: var(--bg);
  box-shadow: inset 0 0 0 1px var(--chrome);
  color: var(--chrome);
  font: 16px/1 var(--font-ui);
}

.win-close:hover,
.win-close:active {
  background: var(--sel-bg);
  color: var(--sel-fg);
  box-shadow: inset 0 0 0 1px var(--sel-bg);
}

.win-title {
  flex: 1;
  padding: 0 8px;
  overflow: hidden;
  background: var(--bg);
  font: 16px/16px var(--font-ui);
  white-space: nowrap;
  text-align: center;
  text-overflow: ellipsis;
}

/* Balances the close box, which sits on the right, so the title stays
   optically centred. */
.win-titlebar::before {
  content: "";
  flex: 0 0 18px;
}

.win-body {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.win-resize {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 16px;
  height: 16px;
  background-color: var(--bg);
  background-image: repeating-linear-gradient(135deg,
      var(--chrome) 0 1px,
      transparent 1px 4px);
  cursor: nwse-resize;
  touch-action: none;
}

/* ── Window content typography ─────────────────────────────────────*/

.win-body h1 {
  font: 16px/24px var(--font-ui);
  letter-spacing: 1px;
}

.win-body .subtitle {
  color: var(--chrome);
}

.win-body p+p {
  margin-top: 16px;
}

.win-body .small {
  font-size: 16px;
  color: var(--chrome);
}

.win-body .center {
  text-align: center;
}

.win-body code {
  font: inherit;
  padding: 0 4px;
  background: var(--sel-bg);
  color: var(--sel-fg);
}

.win-body strong {
  font-weight: normal;
  background: var(--sel-bg);
  color: var(--sel-fg);
  padding: 0 2px;
}

hr.dotted {
  height: 1px;
  margin: 16px 0;
  border: 0;
  background-image: repeating-linear-gradient(to right,
      var(--chrome) 0 2px,
      transparent 2px 4px);
}

.dialog-row {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

.glyph-warn {
  flex: 0 0 32px;
  height: 32px;
  border: 1px solid var(--chrome);
  font: 16px/30px var(--font-ui);
  text-align: center;
}

/* ── Loading dialog ────────────────────────────────────────────────*/

.loader {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 800;
  transform: translate(-50%, -50%);
  width: min(352px, calc(100% - 32px));
  padding: 16px;
  background: var(--bg);
  border: 1px solid var(--chrome);
  outline: 1px solid var(--chrome);
  outline-offset: 1px;
  box-shadow: 4px 4px 0 var(--chrome);
  font: 16px/24px var(--font-text);
  text-align: center;
}

.loader-msg {
  line-height: 16px;
}

.loader-bar {
  margin-top: 16px;
  color: var(--chrome);
  letter-spacing: 0;
  white-space: nowrap;
  overflow: hidden;
}

body.busy,
body.busy * {
  cursor: wait !important;
}

/* ── Taskbar (Windows 1.0 kept minimised windows in a bottom tray) ─*/

.taskbar {
  display: none;
  gap: 8px;
  flex: 0 0 32px;
  padding: 4px;
  background: var(--bg);
  border-top: 1px solid var(--chrome);
  box-shadow: 0 -1px 0 var(--chrome);
  font: 16px/16px var(--font-text);
  overflow-x: auto;
  scrollbar-width: none;
}

.taskbar.active {
  display: flex;
}

.taskbar::-webkit-scrollbar {
  display: none;
}

.taskbar button {
  padding: 4px 12px;
  border: 1px solid var(--chrome);
  white-space: nowrap;
}

.taskbar button[aria-current="true"] {
  background: var(--sel-bg);
  color: var(--sel-fg);
}

/* ── CRT scanline overlay ──────────────────────────────────────────
   Always on: it is part of the look, not an option.                */

.scanlines {
  position: fixed;
  inset: 0;
  z-index: 950;
  pointer-events: none;
  background: repeating-linear-gradient(to bottom,
      rgba(0, 0, 0, 0.26) 0 1px,
      transparent 1px 3px);
}

/* ── Mobile ────────────────────────────────────────────────────────
   The desktop metaphor degrades on purpose: icons become a grid and
   windows open full-screen, because dragging 300px windows around a
   phone screen is nobody's idea of a good time.                     */

@media (max-width: 767px) {
  .icons {
    inset: 16px;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(136px, 1fr));
    gap: 8px;
    align-content: start;
    align-items: start;
    justify-items: center;
  }

  .icon {
    width: 100%;
  }

  .win {
    inset: 0 !important;
    width: auto !important;
    height: auto !important;
    max-width: none;
    max-height: none;
    border: 0;
    outline: 0;
    box-shadow: none;
  }

  .win-titlebar {
    flex-basis: 32px;
    cursor: default;
  }

  .win-resize {
    display: none;
  }

  .sr-hide-sm {
    display: none;
  }

  .menu-title {
    padding: 0 10px;
  }

  /* Now that the clock is set in the full-width EGA face, all three of
     its fields no longer fit alongside the menu titles. It sheds them
     one at a time as the bar tightens, widest first, since the titles
     matter more than knowing the date. Measured: the bar needs 684px
     for all three fields, 416px without the date, 376px without the
     meridiem too. */
  .clock-date {
    display: none;
  }
}

@media (max-width: 439px) {
  .clock-meridiem {
    display: none;
  }
}

@media (max-width: 379px) {
  .clock {
    display: none;
  }
}

/* ── Reduced motion ────────────────────────────────────────────────*/

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

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