/* MAC - the machine and its system: case, screen, menu bar, desktop,
   window chrome, dialogs. What belongs to an application lives in that
   application's own sheet.

   Standalone: this page shares neither styles.css nor common.js with the
   four card games. Everything inside the machine is a multiple of --u, the
   unit that scales the whole Mac with the browser window. Hairlines stay
   at a literal 1px so they never blur. */

/* The system face: ChicagoFLF, the public-domain Chicago released by
   Casady &amp; Greene, served from fonts/. Chicago 12, Damien Guard's
   FontStruct recreation (CC BY-SA 3.0), stands behind it as the fallback:
   a third narrower, measured on the same label (2.06 against 2.72 times
   the icon's width), and harder to read at icon size.
   The webfonts come FIRST in the stack, unlike everywhere else on the
   site, and under private names: the page is drawn for these exact
   bitmaps, and a visitor's installed font of the same name would
   silently reclothe the whole interface. Seen happen, both ways. */
@font-face {
  font-family: "ChicagoFLF Web";
  src: url('fonts/chicagoflf.ttf?v=1') format('truetype');
  font-display: swap;
}

@font-face {
  font-family: "Chicago 12 Web";
  src: url('fonts/chicago-12.woff2?v=1') format('woff2');
  font-display: swap;
}

:root {
  --chrome: "ChicagoFLF Web", "Chicago 12 Web", Geneva, Tahoma, Verdana, sans-serif;
}

* { box-sizing: border-box; }

html, body { margin: 0; height: 100%; }

body {
  background: radial-gradient(circle at 50% 40%, #3d3d42, #16161a 78%);
  font-family: var(--chrome);
  color: #000;
  display: flex;
  /* The case stands on the bottom of the window, as on a desk. */
  align-items: flex-end;
  justify-content: center;
  overflow: hidden;
}

/* ---- the machine ------------------------------------------------------- */

/* The case is the drawing itself, mac.webp (1376 x 1440): bevels, recess,
   bezel and floppy drive are all in the picture. The page only lays the
   live screen over the white of the tube, and the badge over the front.
   Both are placed in percentages of the picture, measured on its pixels. */
#mac {
  /* As large as the window lets it: the sides graze the edges, and the
     bottom of the case may run past the floor, never beyond the floppy
     drive. Its ink ends at 87.4 % of the picture's height, eject dot
     included, measured on the pixels; 89 % stay visible. */
  --mac-h: min(calc(100vh / 0.89), calc(99vw * 1440 / 1376));
  --u: calc(var(--mac-h) / 850);
  position: relative;
  width: calc(var(--mac-h) * 1376 / 1440);
  height: var(--mac-h);
  /* Standing on the floor when it fits, sunk through it when it does not:
     the overflow leaves by the bottom, and the screen keeps the top. */
  margin-bottom: min(0px, calc(100vh - var(--mac-h)));
  /* The drawing ends its top bevels on square light corners, which read
     as white spikes against the dark page: the two top corners are
     rounded off, the dark ground showing in the cut. */
  border-radius: calc(20 * var(--u)) calc(20 * var(--u)) 0 0;
  background: url('mac.webp?v=1') 0 0 / 100% 100% no-repeat;
  box-shadow: 0 calc(20 * var(--u)) calc(50 * var(--u)) rgba(0, 0, 0, .5);
}

/* The little square that carries the compass rose, where the maker's
   badge sits on the case. */
#mac-badge {
  position: absolute;
  left: 8.4%;
  bottom: 4%;
  width: 6.2%;
  aspect-ratio: 1;
  border-radius: calc(8 * var(--u));
  /* The beige of the case around it, read off the picture's pixels. */
  background: #e8d8c1;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .22);
  display: flex;
  align-items: center;
  justify-content: center;
}

#mac-badge svg {
  width: 74%;
  height: 74%;
  display: block;
}

/* ---- the screen -------------------------------------------------------- */

#screen {
  /* 23 units: the bar of the original takes 5.8 % of its 342-line tube. */
  --menubar: calc(23 * var(--u));
  --icon: calc(36 * var(--u));

  /* The white of the picture tube: x 169-1205, y 193-933 on the drawing,
     widened by a pixel so no white sliver of the picture shows past it. */
  position: absolute;
  left: 12.28%;
  top: 13.4%;
  width: 75.33%;
  height: 51.42%;
  overflow: hidden;
  border-radius: calc(17 * var(--u));
  background: #fff;
  font-size: calc(12 * var(--u));
  line-height: 1.35;
  user-select: none;
  -webkit-user-select: none;
  /* A breath of blur over everything the tube shows: phosphor is never
     pixel-sharp. Well under a pixel, so text stays readable. The same
     radius smears more on a coarse grid, so a plain screen gets less of
     it, and a dense one keeps the full breath. */
  filter: blur(calc(0.2 * var(--u)));
}

@media (min-resolution: 1.5dppx) {
  #screen { filter: blur(calc(0.4 * var(--u))); }
}

/* The screen draws its own arrow (below), so the native cursor goes away
   over it, whatever each control would ask for. The browser's focus ring
   goes with it: nothing on a 1984 tube outlines itself in gold. */
#screen, #screen * { cursor: none; }
#screen :focus { outline: none; }

/* Sized on the original: the arrow stands fifteen pixels on a 342-line
   tube, and the same share of this screen's height lands at 21 units. */
#mac-pointer {
  position: absolute;
  z-index: 65;
  width: calc(21 * var(--u));
  /* The tip of the arrow sits at (2,1) of its 16-unit box: the offset
     puts that tip exactly under the real pointer. */
  margin: calc(-1.3 * var(--u)) 0 0 calc(-2.6 * var(--u));
  pointer-events: none;
}

#mac-pointer svg { display: block; width: 100%; }

/* A light cathode-ray veil over everything the screen shows, after a
   close-up photograph of the real tube: horizontal scan lines, a whisper
   of vertical pixel structure, a faint cold cast, and a touch of shade
   toward the edges of the glass. Flat, no bending of the corners. */
#screen::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 70;
  pointer-events: none;
  border-radius: inherit;
  background:
    repeating-linear-gradient(0deg, rgba(10, 20, 40, .10) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(0, 0, 0, .03) 0 1px, transparent 1px 2px),
    linear-gradient(rgba(150, 200, 220, .16), rgba(150, 200, 220, .16)),
    radial-gradient(ellipse at center, transparent 62%, rgba(0, 0, 20, .12) 100%);
}

/* ---- menu bar ---------------------------------------------------------- */

#menubar {
  display: flex;
  align-items: center;
  height: var(--menubar);
  background: #fff;
  border-bottom: 1px solid #000;
  font-size: calc(17 * var(--u));
}

/* Each title centers its own line box: the inherited line-height is taller
   than the bar, and left to itself the text slid to the bottom edge. The
   bottom padding answers the face's own bias, whose ascent carries more
   air than its descent, measured at two pixels on the canvas. */
.menu-title {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  color: #000;
  padding: 0 calc(9 * var(--u)) calc(2 * var(--u));
  height: 100%;
  white-space: nowrap;
  display: flex;
  align-items: center;
}

.menu-title.glyph { padding: 0 calc(12 * var(--u)); }
.menu-title.glyph svg {
  width: calc(13 * var(--u));
  height: calc(13 * var(--u));
  display: block;
}
.menu-title.open { background: #000; color: #fff; }

/* ---- pull-down menus --------------------------------------------------- */

.dropdown {
  position: absolute;
  top: var(--menubar);
  z-index: 40;
  min-width: calc(150 * var(--u));
  background: #fff;
  border: 1px solid #000;
  box-shadow: calc(2 * var(--u)) calc(2 * var(--u)) 0 #000;
  padding: calc(3 * var(--u)) 0;
  font-size: calc(16 * var(--u));
}

.dropdown[hidden] { display: none; }

.dropdown button {
  appearance: none;
  display: block;
  position: relative;
  width: 100%;
  text-align: left;
  border: 0;
  background: none;
  font: inherit;
  color: #000;
  padding: calc(2 * var(--u)) calc(16 * var(--u));
  white-space: nowrap;
}

/* A greyed item keeps its ink and loses half its pixels to a white
   checker, the way the original dims text through a pattern. */
.dropdown button:disabled::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: repeating-conic-gradient(#fff 0% 25%, transparent 0% 50%);
  background-size: 2px 2px;
}

/* The item under the held pointer, marked by the script: with the pointer
   captured by the menu bar, :hover never reaches the items. */
.dropdown button.hot { background: #000; color: #fff; }

.dropdown hr {
  border: 0;
  border-top: 1px dotted #000;
  margin: calc(3 * var(--u)) 0;
}

/* ---- desktop ----------------------------------------------------------- */

#desktop {
  position: absolute;
  inset: var(--menubar) 0 0 0;
  background-color: #fff;
  background-image: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%);
  background-size: 2px 2px;
}

/* ---- the boot ---------------------------------------------------------- */

/* The startup screen covers everything, menu bar included: the dithered
   desk, the little machine, a word and the loading bar. */
#boot {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(14 * var(--u));
  background-color: #fff;
  background-image: repeating-conic-gradient(#000 0% 25%, #fff 0% 50%);
  background-size: 2px 2px;
}

#boot[hidden] { display: none; }

.boot-face { width: calc(34 * var(--u)); }

.boot-text { font-size: calc(15 * var(--u)); }

/* The word and the bar sit on white slabs, the dither showing between. */
.boot-text, .boot-bar { background: #fff; padding: calc(2 * var(--u)) calc(6 * var(--u)); }

.boot-bar {
  width: calc(110 * var(--u));
  height: calc(12 * var(--u));
  border: 1px solid #000;
  padding: calc(2 * var(--u));
}

.boot-bar i {
  display: block;
  height: 100%;
  background: #000;
  animation: boot-fill 1.25s steps(16, end) forwards;
}

@keyframes boot-fill {
  from { width: 0; }
  to   { width: 100%; }
}

.desk-icon {
  position: absolute;
  right: calc(14 * var(--u));
  width: calc(76 * var(--u));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(2 * var(--u));
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: #000;
  touch-action: none;
}

.desk-icon svg { width: var(--icon); height: var(--icon); display: block; }
.desk-icon .label {
  font-size: calc(11 * var(--u));
  line-height: 1.2;
  padding: 0 calc(3 * var(--u));
  background: #fff;
  /* The name overflows its icon rather than folding, as the Finder does. */
  white-space: nowrap;
}

#icon-app { top: calc(10 * var(--u)); }
#icon-note { top: calc(86 * var(--u)); }
#icon-draw { top: calc(162 * var(--u)); }
#icon-life { top: calc(238 * var(--u)); }
#icon-trash { bottom: calc(10 * var(--u)); }

/* The way out sits in the other corner, opposite the Trash. */
#icon-back {
  right: auto;
  left: calc(14 * var(--u));
  bottom: calc(10 * var(--u));
}

/* A selected icon is drawn in reverse, as the Finder draws it. */
.desk-icon.selected .label { background: #000; color: #fff; }
.desk-icon.selected svg { filter: invert(1); }

/* An icon thrown in the Trash leaves the desk. */
.desk-icon[hidden] { display: none; }

/* ---- the Trash's window ------------------------------------------------ */

#app-trash {
  padding: calc(16 * var(--u));
  min-width: calc(250 * var(--u));
}

#trash-items {
  display: flex;
  align-items: flex-start;
  gap: calc(18 * var(--u));
  min-height: calc(64 * var(--u));
}

.trash-item {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  width: calc(76 * var(--u));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(2 * var(--u));
}

.trash-item svg { width: var(--icon); height: var(--icon); display: block; }

.trash-item .label {
  font-size: calc(11 * var(--u));
  line-height: 1.2;
  padding: 0 calc(3 * var(--u));
  background: #fff;
  white-space: nowrap;
}

.trash-item.selected .label { background: #000; color: #fff; }
.trash-item.selected svg { filter: invert(1); }

/* The dotted outline of the zoom and of a drag: what the Finder moves is
   the outline, never the thing itself. */
.zoom-rect {
  position: absolute;
  z-index: 30;
  border: 1px dotted #000;
  pointer-events: none;
}

/* ---- the window -------------------------------------------------------- */

#window {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 20;
  background: #fff;
  border: 1px solid #000;
}

#window[hidden] { display: none; }

#titlebar {
  position: relative;
  height: calc(19 * var(--u));
  touch-action: none;
  border-bottom: 1px solid #000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #fff;
}

/* The stripes stop short of every edge, as on the original: they live on
   a pseudo-element inset by a white margin, and the title and close box
   sit above them. */
#titlebar::before {
  content: '';
  position: absolute;
  inset: calc(3 * var(--u)) calc(2 * var(--u));
  background-image: repeating-linear-gradient(
    180deg, #000 0 1px, #fff 1px calc(3 * var(--u)));
}

#titlebar .title {
  position: relative;
  background: #fff;
  padding: 0 calc(8 * var(--u));
  font-size: calc(12 * var(--u));
}

/* The close box sits in a white slot cut out of the stripes. */
#closebox {
  position: absolute;
  left: calc(8 * var(--u));
  top: 50%;
  transform: translateY(-50%);
  width: calc(11 * var(--u));
  height: calc(11 * var(--u));
  padding: 0;
  border: 1px solid #000;
  background: #fff;
  box-shadow: 0 0 0 calc(2.5 * var(--u)) #fff;
}

#closebox:active { background: #000; }

/* The body holds one root per application; the system shows the root of
   the one in front. Each root lays itself out. */
#wbody .app[hidden] { display: none; }

/* What an application wants kept in place but unseen: invisible, never
   removed, so the window does not change size from one stage to the next. */
.ghost { visibility: hidden; }

/* ---- dialogue ---------------------------------------------------------- */

#alert-layer {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
}

#alert-layer[hidden] { display: none; }

#alert {
  /* the About pins its memory line to this box's bottom corner */
  position: relative;
  background: #fff;
  border: calc(2 * var(--u)) solid #000;
  outline: 1px solid #fff;
  box-shadow: 0 0 0 1px #000;
  padding: calc(14 * var(--u));
  width: calc(300 * var(--u));
  font-size: calc(11.5 * var(--u));
  line-height: 1.45;
}

.alert-body { display: flex; gap: calc(12 * var(--u)); align-items: flex-start; }
/* The text takes all the room left by the icon: sized to its content, it
   let the leftover fall on its right, and nothing laid inside it could
   reach the dialog's right edge. */
#alert-text { flex: 1; min-width: 0; }
#alert-icon { flex: none; }
#alert-icon svg {
  display: block;
  width: calc(32 * var(--u));
  height: calc(32 * var(--u));
}
#alert-text p { margin: 0 0 calc(6 * var(--u)); }
#alert-text p:last-child { margin-bottom: 0; }
#alert-text .quiet { font-size: calc(10.5 * var(--u)); }

/* The furoshiki band of the About: seigaiha waves, staggered rows of
   black fans ringed in white, each row overlapping the one above by half
   a radius. Gradients cannot spill across their tiles, so the tile is an
   inline SVG that draws the overlap itself. */
#alert-text .furoshiki {
  height: calc(26 * var(--u));
  /* out through the dialog's padding, to a few pixels off its border */
  margin: calc(4 * var(--u)) calc(-10 * var(--u)) calc(8 * var(--u));
  border: 1px solid #000;
  background-color: #000;
  background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="32" height="16" viewBox="0 0 32 16"%3E%3Cdefs%3E%3Cg id="f"%3E%3Ccircle r="16" fill="%23000"/%3E%3Cg fill="none" stroke="%23fff" stroke-width="1.3"%3E%3Ccircle r="13.4"/%3E%3Ccircle r="10.8"/%3E%3Ccircle r="8.2"/%3E%3Ccircle r="5.6"/%3E%3Ccircle r="3"/%3E%3C/g%3E%3C/g%3E%3C/defs%3E%3Cuse href="%23f" x="0" y="-8"/%3E%3Cuse href="%23f" x="32" y="-8"/%3E%3Cuse href="%23f" x="16" y="0"/%3E%3Cuse href="%23f" x="0" y="8"/%3E%3Cuse href="%23f" x="32" y="8"/%3E%3Cuse href="%23f" x="16" y="16"/%3E%3Cuse href="%23f" x="0" y="24"/%3E%3Cuse href="%23f" x="32" y="24"/%3E%3C/svg%3E');
  background-size: 32px 16px;
}

/* The About's title: large, centered, the three letters spaced out; the
   indent gives back what the trailing letter-spacing steals from the
   centering. */
.about-title {
  text-align: center;
  font-size: calc(22 * var(--u));
  letter-spacing: calc(14 * var(--u));
  text-indent: calc(14 * var(--u));
}

/* The About's memory line: small, pinned to the dialog's bottom left
   corner, level with the OK button. */
.about-mem {
  position: absolute;
  left: calc(14 * var(--u));
  bottom: calc(18 * var(--u));
  font-size: calc(8.5 * var(--u));
}

#alert-text input {
  font: inherit;
  width: 100%;
  border: 1px solid #000;
  background: #fff;
  padding: calc(2 * var(--u)) calc(4 * var(--u));
}

.alert-buttons {
  display: flex;
  justify-content: flex-end;
  gap: calc(10 * var(--u));
  margin-top: calc(14 * var(--u));
}

#alert-ok, #alert-cancel, #note-ok {
  appearance: none;
  font: inherit;
  color: #000;
  background: #fff;
  border: calc(3 * var(--u)) solid #000;
  border-radius: calc(9 * var(--u));
  padding: calc(2 * var(--u)) calc(20 * var(--u));
}
#alert-ok:hover, #alert-cancel:hover, #note-ok:hover { background: #000; color: #fff; }

/* Cancel is not the default button: its outline stays thin, as on the
   original dialogs. */
#alert-cancel {
  border-width: 1px;
  padding: calc(2 * var(--u)) calc(14 * var(--u));
}

/* The rows of a picker dialog (MAC.openPicker): the chosen one is drawn
   in reverse, as a Finder list would draw it. */
.pick-list {
  border: 1px solid #000;
  margin: calc(6 * var(--u)) 0;
}

.pick-list .pick-row {
  appearance: none;
  display: block;
  width: 100%;
  border: 0;
  background: #fff;
  color: #000;
  font: inherit;
  text-align: left;
  padding: calc(3 * var(--u)) calc(6 * var(--u));
}

.pick-list .pick-row.picked { background: #000; color: #fff; }

/* The note: a smaller slab over the dialog, under the veil. */
#note-layer {
  position: absolute;
  inset: 0;
  z-index: 62;
  display: flex;
  align-items: center;
  justify-content: center;
}

#note-layer[hidden] { display: none; }

#note {
  background: #fff;
  border: calc(2 * var(--u)) solid #000;
  outline: 1px solid #fff;
  box-shadow: 0 0 0 1px #000;
  padding: calc(12 * var(--u));
  width: calc(190 * var(--u));
  font-size: calc(11.5 * var(--u));
  line-height: 1.45;
}

#note p { margin: 0; }

/* ---- narrow screens ---------------------------------------------------- */

/* A phone has no room for the case. The screen alone takes the width, and
   the machine around it is put away. */
@media (max-width: 700px) {
  /* No case on the phone, so nothing stands on the floor: the bare screen
     keeps to the middle. */
  body { align-items: center; }

  #mac {
    /* The screen keeps its shape but holds fewer of its own pixels, so the
       letters stay big enough for a thumb. */
    --u: calc(100vw / 460);
    width: 100vw;
    height: auto;
    margin-bottom: 0;
    background: none;
    box-shadow: none;
  }

  #mac-badge { display: none; }

  #screen {
    position: relative;
    left: auto;
    top: auto;
    width: 100vw;
    height: calc(404 / 460 * 100vw);
    border-radius: 0;
  }
}
