/* HamiltonOS — TempleOS-flavored CSS
 * Hand-rolled, no Tailwind, no preprocessor, no esbuild for CSS.
 * Source of truth: DESIGN.md in the project root.
 *
 * Aesthetic: TempleOS, in honor of Terry A. Davis.
 * Font: Beeb by AndyArmstrong (CC BY-SA 3.0, FontStruct).
 */

/* ============================================================
 * 1. Palette + semantic role colors
 * ============================================================ */

:root {
  /* TempleOS 16-color VGA palette */
  --vga-black:         #000000;
  --vga-blue:          #0000aa;
  --vga-green:         #00aa00;
  --vga-cyan:          #00aaaa;
  --vga-red:           #aa0000;
  --vga-magenta:       #aa00aa;
  --vga-brown:         #aa5500;
  --vga-light-gray:    #aaaaaa;
  --vga-dark-gray:     #555555;
  --vga-light-blue:    #5555ff;
  --vga-light-green:   #55ff55;
  --vga-light-cyan:    #55ffff;
  --vga-light-red:     #ff5555;
  --vga-light-magenta: #ff55ff;
  --vga-yellow:        #ffff55;
  --vga-white:         #ffffff;

  /* Semantic role colors */
  --desktop-bg:           var(--vga-light-gray);
  --window-bg:            var(--vga-light-gray);
  --window-fg:            var(--vga-black);
  --modal-bg:             var(--vga-white);

  --window-border:        var(--vga-light-blue);
  --window-border-focus:  var(--vga-yellow);
  --modal-border:         var(--vga-blue);

  --status-bar-bg:        var(--vga-blue);
  --status-bar-fg:        var(--vga-white);

  --section-header:       var(--vga-red);
  --link:                 var(--vga-blue);
  --comment:              var(--vga-green);
  --timestamp:            var(--vga-yellow);
  --prefix:               var(--vga-magenta);
  --error:                var(--vga-red);
  --separator:            var(--vga-dark-gray);

  --boot-bg:              var(--vga-black);
  --boot-fg:              var(--vga-white);
  --boot-ok:              var(--vga-light-green);
  --boot-warn:            var(--vga-yellow);
  --boot-info:            var(--vga-light-cyan);

  --panic-bg:             var(--vga-red);
  --panic-banner:         var(--vga-yellow);

  /* Spacing scale (8x8 grid + 4px half-step) */
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 8px;
  --space-4: 12px;
  --space-5: 16px;
  --space-6: 24px;
  --space-7: 32px;
}

/* ============================================================
 * 2. Font face — Beeb (CC BY-SA 3.0, AndyArmstrong, FontStruct)
 * ============================================================ */

@font-face {
  font-family: "Beeb";
  src: url("/assets/fonts/beeb.otf-3844105074b238201c5d34e1f32448dd.woff2?vsn=d") format("woff2"),
       url("/assets/fonts/beeb-f0a24be37c9bdc92d3f899579f9fdfee.otf?vsn=d") format("opentype"),
       url("/assets/fonts/beeb-b027805a0af5667717d9b36ea7a3a8f5.ttf?vsn=d") format("truetype");
  font-display: block;
}

/* ============================================================
 * 3. Reset + base
 * ============================================================ */

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

html, body {
  background: var(--desktop-bg);
  color: var(--vga-white);
  font-family: "Beeb", "Courier New", monospace;
  font-size: 14px;
  line-height: 1;
  image-rendering: pixelated;
  -webkit-font-smoothing: none;
  -moz-osx-font-smoothing: none;
  font-smooth: never;
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  cursor: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><polygon points="0,0 0,12 3,9 5,14 7,13 5,8 9,8" fill="white"/><polygon points="1,1 1,10 3,8 5,12 6,11 4,7 7,7" fill="black"/></svg>') 0 0, default;
}

/* Phoenix LiveView wraps the LV content in a <div data-phx-main>. Without
 * a rule here, the wrapper isn't a flex container and the .desktop's
 * flex: 1 has nothing to consume, so the desktop collapses to 0 height
 * (its children are all position: absolute). The whole hit-test area
 * around windows ends up being <body> instead of #desktop, which means
 * the desktop click-to-defocus listener never fires for clicks in the
 * apparent "background." Fix: make the wrapper a flex column that fills
 * the body, so .status-bar and .desktop become its flex children. */
body > [data-phx-main] {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

/* ============================================================
 * 4. Boot screen (BIOS-style overlay above the desktop)
 * ============================================================ */

.boot-screen {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--boot-bg);
  color: var(--boot-fg);
  font-size: 16px;
  line-height: 1.3;
  padding: var(--space-7) 48px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  opacity: 1;
  transition: opacity 400ms;
}
.boot-screen.fading {
  opacity: 0;
  pointer-events: none;
}
.boot-screen .boot-line {
  white-space: pre;
  opacity: 0;
}
/* Hold vertical space while the line is being typed character-by-character.
 * Without it, an empty <div> line collapses to 0 and the layout jumps as
 * each char is added. Scoped via :not(pre) so the ascii cross — which has
 * its own multi-line natural height — isn't given a 1lh min-height that
 * would let the flex algorithm shrink it below its content size. */
.boot-screen .boot-line:not(pre) {
  min-height: 1lh;
}
.boot-screen .boot-line.visible {
  opacity: 1;
}
.boot-screen .boot-line:empty::before {
  content: "\00a0";
}
.boot-screen .boot-header { color: var(--vga-yellow); margin-bottom: var(--space-2); }
.boot-screen .ok    { color: var(--vga-light-green); }
.boot-screen .warn  { color: var(--vga-yellow); }
.boot-screen .err   { color: var(--vga-light-red); }
.boot-screen .info  { color: var(--vga-light-cyan); }
.boot-screen .label { color: var(--vga-white); }
.boot-screen .ascii-art {
  color: var(--vga-yellow);
  white-space: pre;
  line-height: 1;
  margin: var(--space-6) 0 var(--space-3) 0;
  text-align: center;
}
.boot-screen .welcome-banner {
  text-align: center;
  color: var(--vga-yellow);
  font-size: 18px;
  margin-top: var(--space-2);
}
.boot-screen .welcome-tagline {
  text-align: center;
  color: var(--vga-light-cyan);
  margin-top: var(--space-1);
}
.boot-screen .boot-cursor {
  display: inline-block;
  width: 10px;
  height: 14px;
  background: var(--vga-white);
  vertical-align: text-bottom;
  animation: boot-cursor-blink 1s steps(2) infinite;
}
@keyframes boot-cursor-blink {
  50% {
    opacity: 0;
  }
}
.boot-screen .skip-hint {
  margin-top: auto;
  color: var(--vga-dark-gray);
  text-align: center;
  padding: var(--space-4);
  font-size: 14px;
}

/* ============================================================
 * 4b. Kernel panic screen (full-page BSOD for 404s + Easter eggs)
 * ============================================================ */

.panic-body {
  background: var(--panic-bg);
  margin: 0;
  height: 100vh;
}
.panic-screen {
  background: var(--panic-bg);
  color: var(--vga-white);
  font-family: "Beeb", "Courier New", monospace;
  font-size: 16px;
  line-height: 1.3;
  min-height: 100vh;
  padding: var(--space-5) 48px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  overflow-y: auto;
  gap: var(--space-4);
}
.panic-banner {
  color: var(--panic-banner);
  background: var(--vga-black);
  border: 3px solid var(--panic-banner);
  padding: var(--space-2) var(--space-6);
  font-size: 24px;
  text-align: center;
}
.panic-block {
  background: var(--vga-black);
  color: var(--vga-white);
  border: 3px solid var(--vga-white);
  padding: var(--space-4) var(--space-5);
  max-width: 720px;
  width: 100%;
}
.panic-line {
  white-space: pre-wrap;
  margin: 2px 0;
  word-break: break-word;
}
.panic-reason {
  color: var(--vga-light-red);
  font-size: 18px;
  margin-bottom: var(--space-4);
}
.panic-key {
  color: var(--vga-light-gray);
}
.panic-enoent {
  color: var(--vga-yellow);
}
.panic-stack-header {
  color: var(--vga-yellow);
  margin-top: var(--space-4);
  margin-bottom: var(--space-2);
}
.panic-stack {
  color: var(--vga-light-cyan);
  padding-left: var(--space-5);
}
.panic-ts {
  color: var(--vga-yellow);
  margin-top: var(--space-4);
}
.panic-help {
  color: var(--vga-light-gray);
  margin-top: var(--space-4);
  font-size: 14px;
}
.panic-actions {
  display: flex;
  gap: var(--space-5);
  justify-content: center;
}
.panic-btn {
  display: inline-block;
  background: var(--vga-light-gray);
  color: var(--vga-black);
  border: 3px solid var(--vga-white);
  padding: var(--space-2) var(--space-5);
  font-family: inherit;
  font-size: 18px;
  cursor: pointer;
  user-select: none;
  text-decoration: none;
}
.panic-btn::before { content: "[ "; }
.panic-btn::after  { content: " ]"; }
.panic-btn:hover {
  background: var(--vga-white);
}
.panic-credit {
  margin-top: auto;
  color: var(--vga-yellow);
  font-size: 12px;
  text-align: center;
  padding-top: var(--space-3);
  width: 100%;
}

/* ============================================================
 * 5. Status bar (top of screen, replaces menu bar)
 * ============================================================ */

.status-bar {
  flex-shrink: 0;
  height: 22px;
  background: var(--status-bar-bg);
  color: var(--status-bar-fg);
  display: flex;
  align-items: center;
  padding: 0 var(--space-3);
  border-bottom: 2px solid var(--vga-light-blue);
  gap: var(--space-5);
  user-select: none;
  font-size: 14px;
}
.status-bar .load    { color: var(--vga-light-red); }
.status-bar .name    { color: var(--vga-white); }
.status-bar .version { color: var(--vga-light-cyan); }
.status-bar .ts      { color: var(--vga-yellow); }
.status-bar .spacer  { flex: 1; }
.status-bar .running { color: var(--vga-light-cyan); }
.status-bar .running .bar-app { cursor: pointer; }
.status-bar .running .bar-app.active { color: var(--vga-yellow); }
.status-bar .stat    { color: var(--vga-light-green); }
.status-bar .help    { color: var(--vga-light-red); padding-left: var(--space-2); }

/* ============================================================
 * 6. Desktop area
 * ============================================================ */

.desktop {
  position: relative;
  flex: 1;
  background: var(--desktop-bg);
}

/* Desktop icons — colored glyph + black label, no boxed container */
.desktop-icon {
  position: absolute;
  width: 100px;
  text-align: center;
  user-select: none;
}
.desktop-icon .icon-glyph {
  display: block;
  font-size: 28px;
  line-height: 1;
  margin-bottom: var(--space-2);
  color: var(--vga-black);
  text-shadow: 1px 1px 0 var(--vga-white);
}
.desktop-icon.icon-finder           .icon-glyph { color: var(--vga-red); }
.desktop-icon.icon-terminal         .icon-glyph { color: var(--vga-blue); }
.desktop-icon.icon-about            .icon-glyph { color: var(--vga-magenta); }
.desktop-icon.icon-folder-about     .icon-glyph { color: var(--vga-yellow); }
.desktop-icon.icon-folder-blog      .icon-glyph { color: var(--vga-light-blue); }
.desktop-icon.icon-folder-etc       .icon-glyph { color: var(--vga-green); }
.desktop-icon.icon-folder-projects  .icon-glyph { color: var(--vga-light-magenta); }
.desktop-icon.icon-welcome          .icon-glyph { color: var(--vga-cyan); }
.desktop-icon.icon-secrets          .icon-glyph { color: var(--vga-light-red); }
.desktop-icon.icon-clippy           .icon-glyph { color: var(--vga-light-green); }
.desktop-icon.icon-tour             .icon-glyph { color: var(--vga-light-cyan); }
/* inline-block so the hover background hugs the text instead of filling
 * the full 100px container — otherwise the highlight extends well past
 * the visible label. The parent .desktop-icon has text-align: center,
 * which centers the inline-block horizontally. Padding adds a couple of
 * pixels of breathing room around the text inside the highlight. */
.desktop-icon .icon-label {
  display: inline-block;
  padding: 0 3px;
  font-size: 14px;
  color: var(--vga-black);
}

/* Clippy speech balloon. The Clippy hook positions this via inline
 * transform; we just style the chrome to match a HamiltonOS window
 * (gray bg + chunky double-line blue border) but compact, padded for
 * one or two lines of text, and pointer-events: none so it can't catch
 * clicks meant for elements behind it. */
.clippy-balloon {
  font-family: "Beeb", monospace;
  font-size: 14px;
  line-height: 1.25;
  color: var(--vga-black);
  background: var(--window-bg);
  border: 3px solid var(--window-border);
  box-shadow:
    inset 0 0 0 2px var(--vga-light-gray),
    inset 0 0 0 4px var(--window-border);
  padding: var(--space-2) var(--space-3);
  text-align: center;
  white-space: normal;
  word-break: break-word;
  cursor: pointer;
}

/* Chat input mode — visitor types a question for the agent. The wrapper
 * lays out the input + Ask button on a single row. The input borrows
 * the terminal hidden-input look (sunken inset, Beeb font), the button
 * borrows .btn (which is defined later in this file). */
.clippy-balloon-input-wrapper {
  display: flex;
  gap: var(--space-2);
  align-items: stretch;
}
.clippy-balloon-input {
  flex: 1;
  min-width: 0;
  font-family: "Beeb", monospace;
  font-size: 14px;
  color: var(--vga-black);
  background: var(--vga-white);
  border: 2px inset var(--vga-dark-gray);
  padding: var(--space-1) var(--space-2);
  outline: none;
}
.clippy-balloon-input:focus {
  background: var(--vga-light-cyan);
}
.clippy-balloon-submit {
  font-family: "Beeb", monospace;
  font-size: 14px;
  color: var(--vga-white);
  background: var(--vga-blue);
  border: 2px solid var(--vga-light-blue);
  padding: var(--space-1) var(--space-3);
  cursor: pointer;
  user-select: none;
}
.clippy-balloon-submit:hover {
  background: var(--vga-light-blue);
  color: var(--vga-yellow);
}
.clippy-balloon-submit:active {
  background: var(--vga-yellow);
  color: var(--vga-blue);
}

/* Thinking mode — three animated dots while the agent is mid-roundtrip.
 * The mode class on the root tightens padding so the dots don't look
 * lonely in a wide balloon. */
.clippy-balloon-thinking-mode {
  padding: var(--space-1) var(--space-3);
}
.clippy-balloon-thinking {
  font-family: "Beeb", monospace;
  font-size: 18px;
  color: var(--vga-blue);
  letter-spacing: 4px;
  animation: clippy-balloon-thinking-pulse 1.2s ease-in-out infinite;
}
@keyframes clippy-balloon-thinking-pulse {
  0%, 100% { opacity: 0.4; }
  50%      { opacity: 1; }
}

/* "click" hint — fades in after 3s on manual (click-to-dismiss)
 * balloons so the visitor knows the balloon is interactive. */
.clippy-balloon.clippy-balloon-hint::after {
  content: "[ click ]";
  display: block;
  text-align: center;
  color: var(--vga-dark-gray);
  font-size: 10px;
  margin-top: 2px;
  opacity: 0;
  animation: clippy-balloon-hint-fade 0.6s ease-in forwards;
}
@keyframes clippy-balloon-hint-fade {
  to { opacity: 0.6; }
}
.desktop-icon:hover .icon-label { background: var(--vga-black); color: var(--vga-white); }

/* Finder window — folder listing rows */
.finder-listing {
  font-family: "Beeb", monospace;
  font-size: 14px;
}
.finder-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-1) var(--space-2);
  cursor: pointer;
  user-select: none;
}
.finder-item:hover {
  background: var(--vga-blue);
  color: var(--vga-white);
}
.finder-glyph {
  display: inline-block;
  width: 28px;
  text-align: center;
}
.finder-folder .finder-glyph { color: var(--vga-green); }
.finder-file   .finder-glyph { color: var(--vga-yellow); }
.finder-item:hover .finder-glyph { color: var(--vga-white); }

/* ============================================================
 * 7. Window — chunky double-line border via outline + box-shadow trick
 * ============================================================ */

.window {
  position: absolute;
  /* WindowManager hook positions via transform: translate3d(x, y, 0) from
   * (top, left) = (0, 0). Resize sets width/height inline. Don't set
   * top/left here or the hook fights the cascade. */
  top: 0;
  left: 0;
  background: var(--window-bg);
  color: var(--window-fg);
  border: 3px solid var(--window-border);
  box-shadow:
    inset 0 0 0 2px var(--vga-light-gray),
    inset 0 0 0 4px var(--window-border);
  min-width: 240px;
  min-height: 120px;
  /* Hook will set z-index inline; this is the floor before mount. */
  z-index: 1;
  /* Stack the title bar / body / resize handle vertically so the body
   * fills the middle and the resize handle anchors to the bottom-right. */
  display: flex;
  flex-direction: column;
  /* Hidden until the WindowManager hook applies position + size + z, then
   * the hook sets inline `visibility: visible` (higher specificity than
   * this CSS rule, and not touched by LiveView morphdom because the server
   * template never sends it). This prevents the flash-at-origin race
   * between the server's first paint and the hook's first run. */
  visibility: hidden;
}
.window.focused {
  border-color: var(--window-border-focus);
  box-shadow:
    inset 0 0 0 2px var(--vga-light-gray),
    inset 0 0 0 4px var(--window-border-focus);
}

.window-title-bar {
  display: flex;
  align-items: center;
  background: var(--vga-light-gray);
  color: var(--vga-black);
  padding: 0 var(--space-2);
  height: 16px;
  user-select: none;
  border-bottom: 1px solid var(--window-border);
  font-size: 14px;
  gap: var(--space-2);
  flex-shrink: 0;
  cursor: grab;
  /* Disable native touch gestures on the drag handle so pointer events
   * fire continuously during a touch drag. */
  touch-action: none;
}
.window-title-bar:active { cursor: grabbing; }
.window.focused .window-title-bar { border-bottom-color: var(--window-border-focus); }
/* min-width: 0 + overflow lets the title shrink past its content size when
 * the title bar runs out of room (default flex min-width is auto, which
 * pins items to their content width and can push the close button past
 * the right edge). */
.window-title { color: var(--vga-light-red); white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.window-path { color: var(--vga-dark-gray); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.window-close {
  color: var(--vga-black);
  padding: 0 var(--space-1);
  cursor: pointer;
  /* Always sit at the right edge of the title bar. With the optional
   * .window-path present, this is redundant (path's flex:1 already
   * absorbs the space). Without it (e.g., the about modal), this pushes
   * the close button to the right instead of letting it float next to
   * the title text. */
  margin-left: auto;
}
.window-close::before { content: '['; }
.window-close::after { content: ']'; }
.window-body {
  padding: var(--space-2);
  font-size: 14px;
  line-height: 1.15;
  flex: 1;
  overflow: auto;
  min-height: 0;
}
/* Apps that paint their own background to the window edges (terminal,
 * future canvas-style apps) opt out of body padding via the Window
 * component's `flush` attr. We also clip overflow so the app's own
 * scroll containers can take over without fighting two scrollbars. */
.window-body--flush {
  padding: 0;
  overflow: hidden;
}

/* Resize handle — chunky bottom-right corner. Pointer events are wired
 * up by the WindowManager hook. touch-action: none same reason as the
 * title bar — keep the gesture continuous on touch. */
.window-resize-handle {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 14px;
  height: 14px;
  cursor: nwse-resize;
  touch-action: none;
  background:
    linear-gradient(135deg, transparent 50%, var(--window-border) 50%);
}
.window.focused .window-resize-handle {
  background:
    linear-gradient(135deg, transparent 50%, var(--window-border-focus) 50%);
}

/* ============================================================
 * 7a-safari. Safari window chrome — the "wrong decade" gag.
 *
 * A content file with `chrome: safari` opens in this chrome
 * instead of the canonical TempleOS window. Rounded corners,
 * traffic-light buttons, fake URL bar. Uses system-ui for the
 * chrome elements so the contrast with Beeb body text is
 * immediately visible. The mismatch IS the joke.
 * ============================================================ */
.safari-chrome {
  border: 1px solid #999;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
  background: #fff;
}
.safari-chrome.focused {
  border-color: #777;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
}

.safari-title-bar {
  background: linear-gradient(180deg, #e8e6e8, #d2d0d2);
  padding: 8px 12px;
  display: flex;
  align-items: center;
  position: relative;
  border-bottom: 1px solid #b0b0b0;
  cursor: grab;
  touch-action: none;
  flex-shrink: 0;
  user-select: none;
}
.safari-title-bar:active { cursor: grabbing; }

.safari-traffic-lights {
  display: flex;
  gap: 8px;
  z-index: 1;
}
.safari-btn {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  display: inline-block;
}
.safari-btn-close    { background: #ff5f57; border: 1px solid #e14942; cursor: pointer; }
.safari-btn-minimize { background: #febc2e; border: 1px solid #e0a028; }
.safari-btn-maximize { background: #28c840; border: 1px solid #1dad2b; }

.safari-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 13px;
  font-weight: 500;
  color: #333;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60%;
}

.safari-toolbar {
  background: #f6f6f6;
  padding: 6px 12px;
  border-bottom: 1px solid #ddd;
  flex-shrink: 0;
}
.safari-url-bar {
  background: #fff;
  border: 1px solid #c8c8c8;
  border-radius: 6px;
  padding: 4px 10px;
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 12px;
  color: #666;
  display: flex;
  align-items: center;
}

.safari-body {
  padding: 16px 20px;
  overflow: auto;
  flex: 1;
  background: #fff;
}

/* Override markdown styles for Safari content — system font, relaxed
 * spacing, so it reads like a real web page inside the fake browser. */
.safari-content {
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 15px;
  line-height: 1.6;
  color: #1d1d1f;
}
.safari-content h1 { font-size: 28px; font-weight: 700; margin: 0 0 12px; }
.safari-content h2 { font-size: 20px; font-weight: 600; margin: 16px 0 8px; }
.safari-content p { margin: 8px 0; }
.safari-content a { color: #0066cc; }
.safari-content code {
  background: #f0f0f0;
  padding: 2px 5px;
  border-radius: 3px;
  font-size: 13px;
}

/* Subtle resize handle for Safari chrome — inherits .window-resize-handle
 * positioning but overrides the TempleOS triangle with a lighter one. */
.safari-chrome .window-resize-handle {
  background: linear-gradient(135deg, transparent 50%, #ccc 50%);
  border-radius: 0 0 10px 0;
}
.safari-chrome.focused .window-resize-handle {
  background: linear-gradient(135deg, transparent 50%, #aaa 50%);
}

/* ============================================================
 * 7a-vista. Windows Vista File Explorer chrome.
 *
 * Aero glass title bar, navigation breadcrumbs, translucent UI.
 * Content files with `chrome: vista`.
 * ============================================================ */
.vista-chrome {
  border: 1px solid rgba(0, 0, 0, 0.3);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.3), inset 0 0 0 1px rgba(255, 255, 255, 0.15);
  background: #f1f1f1;
}
.vista-chrome.focused {
  border-color: rgba(0, 0, 0, 0.4);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4), inset 0 0 0 1px rgba(255, 255, 255, 0.2);
}

.vista-title-bar {
  background: linear-gradient(180deg, rgba(40, 54, 82, 0.9), rgba(20, 30, 48, 0.95));
  backdrop-filter: blur(12px);
  padding: 6px 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  cursor: grab;
  touch-action: none;
  user-select: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.vista-title-bar:active { cursor: grabbing; }
.vista-title {
  font-family: system-ui, "Segoe UI", sans-serif;
  font-size: 12px;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}
.vista-controls { display: flex; gap: 2px; }
.vista-ctrl-btn {
  width: 28px;
  height: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: system-ui, "Segoe UI", sans-serif;
  font-size: 11px;
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 3px;
  cursor: pointer;
}
.vista-ctrl-btn:hover { background: rgba(255, 255, 255, 0.25); }
.vista-btn-close:hover { background: rgba(220, 50, 50, 0.8); }

.vista-nav-bar {
  background: linear-gradient(180deg, #e8eef7, #d6dfe9);
  padding: 4px 8px;
  display: flex;
  align-items: center;
  gap: 6px;
  border-bottom: 1px solid #b8c4d0;
  flex-shrink: 0;
}
.vista-nav-buttons { display: flex; gap: 2px; }
.vista-nav-btn {
  width: 26px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  color: #456;
  background: linear-gradient(180deg, #fff, #e8eef4);
  border: 1px solid #a0b0c0;
  border-radius: 3px;
  cursor: default;
}
.vista-address-bar {
  flex: 1;
  background: #fff;
  border: 1px solid #a0b0c0;
  border-radius: 3px;
  padding: 2px 8px;
}
.vista-address {
  font-family: system-ui, "Segoe UI", sans-serif;
  font-size: 12px;
  color: #333;
}

.vista-body {
  padding: 16px 20px;
  overflow: auto;
  flex: 1;
  background: #fff;
}
.vista-content {
  font-family: system-ui, "Segoe UI", sans-serif;
  font-size: 14px;
  line-height: 1.5;
  color: #222;
}
.vista-content h1 { font-size: 24px; font-weight: 600; margin: 0 0 10px; color: #003399; }
.vista-content h2 { font-size: 18px; font-weight: 600; margin: 14px 0 6px; color: #003399; }
.vista-content p { margin: 6px 0; }
.vista-content a { color: #0066cc; }
.vista-content code {
  background: #f0f4f8;
  padding: 2px 4px;
  border-radius: 2px;
  font-size: 12px;
}

.vista-chrome .window-resize-handle {
  background: linear-gradient(135deg, transparent 50%, rgba(0, 0, 0, 0.15) 50%);
  border-radius: 0 0 8px 0;
}

/* ============================================================
 * 7a-win95. Windows 95 chrome.
 *
 * Chunky 3D borders, navy blue title bar, raised button controls.
 * Content files with `chrome: win95`.
 * ============================================================ */
.win95-chrome {
  border: 2px outset #dfdfdf;
  background: #c0c0c0;
  box-shadow: inset 1px 1px 0 #fff, inset -1px -1px 0 #808080;
  overflow: hidden;
}
.win95-chrome.focused { border-color: #dfdfdf; }

.win95-title-bar {
  background: linear-gradient(90deg, #000080, #1084d0);
  padding: 2px 3px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.win95-title-bar:active { cursor: grabbing; }
.win95-title {
  font-family: system-ui, "MS Sans Serif", sans-serif;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  padding-left: 2px;
}
.win95-controls { display: flex; gap: 1px; }
.win95-ctrl-btn {
  width: 16px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: system-ui, sans-serif;
  font-size: 9px;
  font-weight: 700;
  color: #000;
  background: #c0c0c0;
  border: 1px outset #dfdfdf;
  cursor: pointer;
}
.win95-ctrl-btn:active { border-style: inset; }
.win95-btn-close { margin-left: 2px; }

.win95-body {
  padding: 8px;
  overflow: auto;
  flex: 1;
  background: #fff;
  border: 2px inset #dfdfdf;
  margin: 2px;
}
.win95-content {
  font-family: system-ui, "MS Sans Serif", sans-serif;
  font-size: 13px;
  line-height: 1.4;
  color: #000;
}
.win95-content h1 { font-size: 18px; font-weight: 700; margin: 0 0 8px; }
.win95-content h2 { font-size: 15px; font-weight: 700; margin: 12px 0 6px; }
.win95-content p { margin: 4px 0; }
.win95-content a { color: #0000ff; }
.win95-content code { font-family: "Courier New", monospace; font-size: 12px; }

.win95-status-bar {
  font-family: system-ui, "MS Sans Serif", sans-serif;
  font-size: 11px;
  color: #000;
  background: #c0c0c0;
  border-top: 1px solid #808080;
  padding: 1px 4px;
  flex-shrink: 0;
}
.win95-chrome .window-resize-handle {
  background: linear-gradient(135deg, transparent 50%, #808080 50%);
}

/* ============================================================
 * 7a-xp-paint. Windows XP MS Paint chrome.
 *
 * Luna blue title bar, tool palette on the left, color palette
 * at the bottom. Content files with `chrome: xp-paint`.
 * ============================================================ */
.xp-paint-chrome {
  border: 2px solid #0054e3;
  border-radius: 8px 8px 0 0;
  overflow: hidden;
  background: #ece9d8;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.xp-paint-chrome.focused {
  border-color: #0054e3;
}

.xp-title-bar {
  background: linear-gradient(180deg, #0a6af5, #0054e3 45%, #0044bb 55%, #003399);
  padding: 4px 6px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
  cursor: grab;
  touch-action: none;
  user-select: none;
  border-radius: 6px 6px 0 0;
}
.xp-title-bar:active { cursor: grabbing; }
.xp-title {
  font-family: system-ui, "Tahoma", sans-serif;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
}
.xp-controls { display: flex; gap: 2px; }
.xp-ctrl-btn {
  width: 21px;
  height: 21px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: system-ui, sans-serif;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  border-radius: 3px;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.3);
}
.xp-btn-min, .xp-btn-max {
  background: linear-gradient(180deg, #3c8cf5, #2060d0);
}
.xp-btn-min:hover, .xp-btn-max:hover { background: linear-gradient(180deg, #5ca0ff, #3070e0); }
.xp-btn-close {
  background: linear-gradient(180deg, #e06050, #c03020);
  margin-left: 2px;
}
.xp-btn-close:hover { background: linear-gradient(180deg, #ff7060, #d04030); }

.xp-menu-bar {
  font-family: system-ui, "Tahoma", sans-serif;
  font-size: 12px;
  color: #000;
  background: #ece9d8;
  padding: 2px 4px;
  display: flex;
  gap: 2px;
  border-bottom: 1px solid #aca899;
  flex-shrink: 0;
}
.xp-menu-item {
  padding: 1px 6px;
  cursor: default;
}
.xp-menu-item:hover { background: #316ac5; color: #fff; }

.xp-workspace {
  display: flex;
  flex: 1;
  overflow: hidden;
}
.xp-tool-palette {
  width: 52px;
  background: #ece9d8;
  border-right: 1px solid #aca899;
  padding: 4px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  align-content: start;
  flex-shrink: 0;
}
.xp-tool {
  width: 22px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: system-ui, "Tahoma", sans-serif;
  font-size: 8px;
  color: #333;
  background: #ece9d8;
  border: 1px solid transparent;
  cursor: default;
}
.xp-tool:hover { border: 1px outset #dfdfdf; }

.xp-canvas {
  flex: 1;
  background: #fff;
  overflow: auto;
  padding: 12px 16px;
  border: 1px inset #aca899;
  margin: 2px;
}
.xp-paint-content {
  font-family: system-ui, "Tahoma", sans-serif;
  font-size: 13px;
  line-height: 1.5;
  color: #000;
}
.xp-paint-content h1 { font-size: 20px; font-weight: 700; margin: 0 0 8px; }
.xp-paint-content h2 { font-size: 16px; font-weight: 700; margin: 12px 0 6px; }
.xp-paint-content p { margin: 6px 0; }
.xp-paint-content a { color: #0000ff; }
.xp-paint-content code { font-family: "Courier New", monospace; font-size: 12px; }

.xp-color-palette {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #ece9d8;
  border-top: 1px solid #aca899;
  padding: 4px 8px;
  flex-shrink: 0;
}
.xp-active-colors {
  position: relative;
  width: 28px;
  height: 24px;
}
.xp-fg-color {
  width: 16px;
  height: 16px;
  border: 1px solid #808080;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}
.xp-bg-color {
  width: 16px;
  height: 16px;
  border: 1px solid #808080;
  position: absolute;
  bottom: 0;
  right: 0;
}
.xp-color-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1px;
}
.xp-color-swatch {
  width: 12px;
  height: 12px;
  border: 1px solid #808080;
  cursor: default;
}

.xp-paint-chrome .window-resize-handle {
  background: linear-gradient(135deg, transparent 50%, #aca899 50%);
}

/* ============================================================
 * 7b. Terminal app (lives inside a normal .window via the
 *     Terminal JS hook). Black background, light gray text,
 *     yellow blinking block cursor.
 * ============================================================ */

.terminal {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--vga-black);
  color: var(--vga-light-gray);
  font-family: "Beeb", "Courier New", monospace;
  font-size: 14px;
  line-height: 1.1;
  /* Fill the flush window-body. The body has padding: 0 in flush mode so
   * we don't need negative margins anymore. */
  height: 100%;
  padding: var(--space-2);
  /* No native text selection cursor on the terminal — we manage focus
   * via a hidden input. Selection still works via click-drag. */
  cursor: text;
}

/* Wraps both the output lines and the active prompt-line. Scrolls as a
 * single unit so the prompt naturally sits right after the last output
 * line — like a real terminal — instead of being pinned to the bottom of
 * the visible viewport. */
.terminal-scroll {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}

.terminal-output {
  /* No flex / overflow here — let .terminal-scroll do the scrolling. The
   * output is just a normal block whose children are the lines. */
}

.terminal-line {
  color: var(--vga-light-gray);
  /* pre-wrap preserves multi-spaces (so help columns and ls layouts stay
   * aligned) AND wraps long lines at the right edge of the window. */
  white-space: pre-wrap;
  word-break: break-word;
}

.terminal-line.terminal-echo {
  color: var(--vga-white);
}

.terminal-line.terminal-error {
  color: var(--vga-light-red);
}

.terminal-prompt-line {
  display: flex;
  flex-wrap: wrap;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--vga-white);
  padding-top: var(--space-1);
}

.terminal-prompt-cwd {
  color: var(--vga-light-green);
}

.terminal-prompt-input {
  color: var(--vga-white);
  white-space: pre;
}

.terminal-cursor {
  display: inline-block;
  background: var(--vga-yellow);
  width: 8px;
  height: 1em;
  margin-left: 1px;
  vertical-align: text-bottom;
  /* No animation by default — solid block when the window isn't focused.
   * Real terminals do this too: cursor stops blinking when focus leaves. */
}
.window.focused .terminal-cursor {
  animation: terminal-blink 1s steps(1) infinite;
}

@keyframes terminal-blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

/* The hidden input lives in the same container but is positioned
 * off-screen. All keystrokes go to it; the visible prompt mirrors
 * the value via the JS hook. We use absolute positioning + clip
 * instead of display:none so the input remains focusable. */
.terminal-hidden-input {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  opacity: 0;
  border: 0;
  padding: 0;
  margin: 0;
}

/* ============================================================
 * 8. Modal window (special chrome — About, boot completion)
 * ============================================================ */

.window.modal {
  background: var(--modal-bg);
  border: 2px solid var(--modal-border);
  box-shadow:
    inset 0 0 0 1px var(--vga-white),
    inset 0 0 0 2px var(--modal-border),
    inset 0 0 0 3px var(--vga-white),
    inset 0 0 0 4px var(--modal-border);
}
.window.modal .window-title-bar {
  background: var(--vga-white);
  border-bottom: 1px solid var(--modal-border);
}
.window.modal .window-title { color: var(--modal-border); }
.window.modal .window-body {
  background: var(--modal-bg);
  color: var(--vga-black);
}

/* ============================================================
 * 9. Section headers, separators, links, comments, timestamps, prefixes
 * ============================================================ */

.section-header {
  color: var(--section-header);
  font-weight: normal;
  margin: var(--space-2) 0 var(--space-1) 0;
}
.section-header::before { content: '----'; }
.section-header::after  { content: '----'; }

.section-break {
  border: none;
  border-top: 1px dashed var(--vga-black);
  margin: var(--space-2) 0;
}

/* Markdown body — rendered HTML from MDEx for Reader window content. */
.markdown-body {
  font-size: 14px;
  line-height: 1.4;
}
.markdown-body h1,
.markdown-body h2,
.markdown-body h3 {
  color: var(--section-header);
  font-weight: normal;
  margin: var(--space-4) 0 var(--space-2) 0;
}
.markdown-body h1 { font-size: 16px; }
.markdown-body h1::before { content: '----'; }
.markdown-body h1::after  { content: '----'; }
.markdown-body h2 { font-size: 14px; }
.markdown-body h2::before { content: '---'; }
.markdown-body h2::after  { content: '---'; }
.markdown-body h3 { font-size: 14px; }
.markdown-body p  { margin: var(--space-3) 0; }
.markdown-body ul,
.markdown-body ol { margin: var(--space-3) 0 var(--space-3) var(--space-5); }
.markdown-body li { margin: var(--space-1) 0; }
.markdown-body strong { font-weight: normal; color: var(--vga-blue); }
.markdown-body em     { font-style: normal; color: var(--vga-magenta); }
.markdown-body code   { color: var(--vga-magenta); }
.markdown-body pre {
  background: var(--vga-black);
  color: var(--vga-light-gray);
  padding: var(--space-3);
  margin: var(--space-3) 0;
  overflow-x: auto;
}
.markdown-body pre code { color: inherit; }
.markdown-body hr {
  border: none;
  border-top: 1px dashed var(--vga-black);
  margin: var(--space-4) 0;
}

.link {
  color: var(--link);
  text-decoration: underline;
  cursor: pointer;
}

.comment   { color: var(--comment); }
.ts        { color: var(--timestamp); }
.prefix    { color: var(--prefix); font-weight: normal; }
.err       { color: var(--error); }

/* ============================================================
 * 10. Buttons — chunky black border, light gray fill
 * ============================================================ */

.btn {
  display: inline-block;
  background: var(--vga-light-gray);
  color: var(--vga-black);
  border: 2px solid var(--vga-black);
  padding: 1px var(--space-3);
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
  user-select: none;
}
.btn::before { content: '[ '; }
.btn::after  { content: ' ]'; }
.btn:hover   { background: var(--vga-white); }

/* ============================================================
 * 11. About list (key/value rows in the About modal)
 * ============================================================ */

.about-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  text-align: left;
  font-size: 12px;
  line-height: 1.4;
  margin: var(--space-3) 0;
}
.about-list .row {
  display: flex;
  gap: var(--space-3);
}
.about-list .row .key {
  color: var(--vga-dark-gray);
  flex: 0 0 100px;
}
.about-list .row .val {
  color: var(--vga-black);
}

/* ============================================================
 * 12. Phoenix flash group (minimal, fits the aesthetic)
 * ============================================================ */

.flash-group {
  position: fixed;
  top: var(--space-7);
  right: var(--space-3);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.flash {
  background: var(--vga-light-gray);
  color: var(--vga-black);
  border: 2px solid var(--vga-black);
  padding: var(--space-2) var(--space-3);
  font-size: 14px;
  max-width: 320px;
}
.flash.info  { border-color: var(--vga-blue); }
.flash.error { border-color: var(--vga-red); color: var(--vga-red); }
.flash[hidden] { display: none; }
