/* =========================================================================
   Everything's Computer — the fifteen skins
   Authored at 1:1 native OS pixels; style.css scales the whole stage by an
   integer factor. Nothing in here should use a fractional pixel value.

   Widget slots (index.html gives every skin the same three):
     .w-close  left of the title      .w-a .w-b  right of the title
   Each skin shows only the widgets that OS actually had.
   ========================================================================= */


/* ======================= SKIN — System 6 (1988) ==========================
   Measured from a System 6 screen recovered at native 512x342 (Infinite Mac
   at exactly 2x, so the 1-bit original came back intact — two colours, no
   interpolation). Body taken from the Finder's Copy dialog, title bar from
   an active Finder window.

   Modal frame, outside in:  1px black, 2px white, 2px black. That heavy
                             double band is what makes the Copy dialog read
                             the way it does.
   Title bar:                18px — 1px black, 3 blank rows, six 1px stripes
                             over 11 rows, 3 blank rows, 1px black. The
                             stripes run the full width and the centred title
                             punches a white hole in them, 7px either side.
                             No close box: this is a progress dialog, and the
                             Copy dialog it comes from has none. Descenders
                             drop out of that white panel onto the blank rows
                             below, exactly as they do on a real one.
   Body:                     content box is 330 - 2*(1+2+2) = 320 wide, 13px
                             in from the left. The bar and the button share
                             one row, vertically centred on each other, 12px
                             apart — same as the Copy dialog.
   Progress bar:             12px, 1px black frame, 228px in the capture, and
                             the fill is NOT solid black — it is a 75% dither
                             on a 4x2 tile, one white pixel per row offset by
                             two. Measured pixel by pixel off the Copy dialog.
   Buttons:                  20px tall, 60px wide, 1px black, ~4px radius, no
                             default ring — the Copy dialog's Cancel has none.
   Desktop:                  the 50% checkerboard, confirmed in the capture. */

[data-os="system6"] {
  --font: "Chicago", Geneva, monospace;
  --fsize: 16px; --lh: 16px;
  --dlg-w: 330px;
  --face: #fff; --text: #000;
  --title-h: 18px; --title-fg: #000;
  --pad: 13px; --gap: 15px;
  --bar-h: 12px; --btn-h: 20px; --btn-w: 60px;
  --notice-fg: #000;
}
[data-os="system6"] .screen {
  background-color: #808080;
  background: repeating-conic-gradient(#000 0 25%, #fff 0 50%) 0 0 / var(--dither) var(--dither);
}

/* 1px black, 2px white, 2px black. The rings would wrap all four sides, but
   .titlebar is opaque and full-bleed, so it covers the top run — leaving the
   band on the three sides the Copy dialog shows it on. */
[data-os="system6"] .dialog {
  border: 1px solid #000;
  background: #fff;
  padding: 0 4px 4px;
  box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4px #000, 1px 1px 0 #000;
}

/* The three blank rows top and bottom have to be opaque white — .dialog's own
   inset bands run underneath and would otherwise show through. So: white for
   the whole border box, stripes clipped AND originated to the content box, so
   the band is exactly 11 rows and starts on a dark one. */
[data-os="system6"] .titlebar {
  margin: 0 -4px;                        /* full bleed, back out through the padding */
  padding: 3px 0;
  border-bottom: 1px solid #000;
  background-color: #fff;
  background-image: repeating-linear-gradient(180deg, #000 0 1px, #fff 1px 2px);
  background-size: calc(100% - 2px) 11px; /* band sized and placed by hand: 1px */
  background-position: 1px 3px;           /* clear of the frame, starting dark */
  background-repeat: no-repeat;
}
/* No close box — this is a progress dialog, and the Copy dialog it is drawn
   from has none. The stripes run unbroken from the frame to the title. */
[data-os="system6"] .tb-c {
  justify-content: center; align-self: stretch; overflow: visible;
}
/* The white panel stays exactly as tall as the stripe band, but the glyphs
   have to be allowed out of it — in the capture the p of "Space" drops a row
   below the band, onto the blank rows underneath. .title clips by default. */
[data-os="system6"] .title {
  background: #fff; padding: 0 7px;      /* measured on this exact string */
  align-self: stretch; display: flex; align-items: center;
  overflow: visible;
}
[data-os="system6"] .titlebar  { overflow: visible; }

/* The Copy dialog runs the bar and the button on one row. */
[data-os="system6"] .content {
  padding: 13px 7px 9px 13px;            /* the capture's own asymmetric pad */
  display: flex; flex-wrap: wrap; align-items: center; column-gap: 12px;
}
[data-os="system6"] .message   { flex: 0 0 100%; }
[data-os="system6"] .progress  { flex: 1 1 0; min-width: 0; margin-bottom: 0; }
[data-os="system6"] .actions   { flex: 0 0 auto; padding: 0; }

[data-os="system6"] .track  { height: 12px; border: 1px solid #000; background: #fff; }
[data-os="system6"] .fill  {              /* 75% dither, 4x2 tile — not solid black */
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='2' shape-rendering='crispEdges'%3E%3Crect width='4' height='2' fill='%23000'/%3E%3Crect x='2' width='1' height='1' fill='%23fff'/%3E%3Crect y='1' width='1' height='1' fill='%23fff'/%3E%3C/svg%3E");
  background-size: 4px 2px;
}

[data-os="system6"] .btn {
  background: #fff; border: 1px solid #000;
  border-radius: 4px; width: 60px; padding: 0;   /* measured, not text-fitted */
}
[data-os="system6"] .btn:active  { background: #000; color: #fff; }
[data-os="system6"] .notice { font-family: "Geneva", Verdana, sans-serif; }
/* Two plates, not one. Black type on a 50% dither is unreadable, so the
   address gets a white box punched behind it — but the OS name underneath is
   hidden until the dialog is double-clicked, and a single box around both
   left an empty white strip sitting under the address whenever it was. The
   link takes its own plate (it is inline, so the box hugs the words) and the
   name takes another, which appears and goes with it because opacity takes
   the background too. */
[data-os="system6"] .notice a,
[data-os="system6"] .osname {
  background: #fff;
  padding: 2px 8px;
}
[data-os="system6"] .osname { width: fit-content; margin-inline: auto; }
/* The plate has to stay WHITE when the name is showing. The reveal fades the
   whole element, background included, which turned the box into a grey panel
   sitting on the dither — so here the element goes fully opaque and the type
   carries the fade itself. Same grey as before on screen, an opaque box under
   it. */
[data-os="system6"][data-osname-shown] .osname { opacity: 1; }
[data-os="system6"] .osname { color: rgba(0, 0, 0, .5); }



/* ======================= SKIN — System 7 (1991) ==========================
   Measured from two System 7 screen grabs: a Find dialog and an Installer
   progress window. System 7 on colour hardware is NOT the 1-bit look of
   System 6 — the whole frame is tinted, and there is not a dithered pixel
   in it.

   Window frame, outside in:  #000000, #CCCCFF, #BBBBBB, #7A7A99, #000000,
                              symmetric on all four sides.
   Title bar:                 #CCCCFF, two rows of #EEEEEE, twelve rows of
                              1px #777777 / 1px #EEEEEE stripes, #EEEEEE,
                              #A3A3D7, #7A7A99, then the #000000 separator.
   Progress bar:              1px black frame, #404040 fill, #CCCCFF track.
                              Solid — no dither, no barber pole.
   Buttons:                   white, 1px black, ~4px radius. The Installer's
                              Stop button carries no default ring, so neither
                              does this one; System 6 keeps its ring.
   The whole Find dialog uses just eight colours, all of them below.        */

[data-os="system7"] {
  --font: "Chicago", Geneva, monospace;
  --fsize: 16px; --lh: 16px;
  --dlg-w: 340px;
  --face: #fff; --text: #000;
  --title-h: 19px; --title-fg: #000;
  --pad: 14px; --gap: 15px;
  --bar-h: 14px; --btn-h: 20px; --btn-w: 68px;
  --notice-fg: #000;
}
[data-os="system7"] .screen {
  background-color: #bbb;
  background: repeating-conic-gradient(#ccc 0 25%, #aaa 0 50%) 0 0 / var(--dither) var(--dither);
}

/* The tinted band is padding on the sides and bottom only — above the content
   the title bar runs edge to edge, so the band must not appear there. Inset
   rings would ring all four sides, but .titlebar is an opaque child and paints
   over the top run, which is exactly the behaviour wanted. */
[data-os="system7"] .dialog {
  border: 1px solid #000;
  background: #000;                 /* the innermost row of the band */
  padding: 0 4px 4px;
  box-shadow: inset 0 0 0 1px #ccccff,
              inset 0 0 0 2px #bbbbbb,
              inset 0 0 0 3px #7a7a99,
              2px 2px 0 rgba(0,0,0,.4);
}

/* Rows 1-19 of the window. One repeating gradient for the stripe band, laid
   over a second that supplies the solid rows above and below it. */
[data-os="system7"] .titlebar {
  margin: 0 -4px;                   /* full bleed, back out through the padding */
  background-image:
    repeating-linear-gradient(180deg, #777 0 1px, #eee 1px 2px),
    linear-gradient(180deg, #ccccff 0 1px, #eee 1px 16px, #a3a3d7 16px 17px,
                            #7a7a99 17px 18px, #000 18px 19px);
  background-size: 100% 12px, auto;
  background-position: 0 3px, 0 0;
  background-repeat: no-repeat, no-repeat;
  box-shadow: inset 1px 0 0 #ccccff, inset -1px 0 0 #a3a3d7;
}
[data-os="system7"] .tb-c  { justify-content: center; align-self: stretch; }
/* The panel behind the title must NOT cover the bar's bevel: the #CCCCFF
   highlight row at the top and the #A3A3D7 / #7A7A99 / #000000 rows at the
   bottom run the full width of the bar, straight under the name. Stretching
   the panel and insetting it by those rows is what keeps the bevel unbroken. */
[data-os="system7"] .title {
  background: #eee; padding: 0 8px;
  align-self: stretch; display: flex; align-items: center;
  margin: 1px 0 3px;
}

[data-os="system7"] .content  { background: #fff; }

[data-os="system7"] .track  { height: 14px; border: 1px solid #000; background: #ccccff; }
[data-os="system7"] .fill  { background: #404040; }

[data-os="system7"] .btn {
  background: #fff; border: 1px solid #000;
  border-radius: 4px; padding: 0 14px;
}
[data-os="system7"] .btn:active  { background: #000; color: #fff; }
[data-os="system7"] .notice { font-family: "Geneva", Verdana, sans-serif; }
/* Two plates, not one. Black type on a 50% dither is unreadable, so the
   address gets a white box punched behind it — but the OS name underneath is
   hidden until the dialog is double-clicked, and a single box around both
   left an empty white strip sitting under the address whenever it was. The
   link takes its own plate (it is inline, so the box hugs the words) and the
   name takes another, which appears and goes with it because opacity takes
   the background too. */
[data-os="system7"] .notice a,
[data-os="system7"] .osname {
  background: #fff;
  padding: 2px 8px;
}
[data-os="system7"] .osname { width: fit-content; margin-inline: auto; }
/* The plate has to stay WHITE when the name is showing. The reveal fades the
   whole element, background included, which turned the box into a grey panel
   sitting on the dither — so here the element goes fully opaque and the type
   carries the fade itself. Same grey as before on screen, an opaque box under
   it. */
[data-os="system7"][data-osname-shown] .osname { opacity: 1; }
[data-os="system7"] .osname { color: rgba(0, 0, 0, .5); }



/* ================= SKIN — Mac OS 8 & 9 (1997-1999) =======================
   One skin for both. Platinum did not change between them in any way this
   dialog shows, so two skins that differed only in their desktop colour
   were two entries in the list for one piece of chrome. They are now one,
   and the desktop instead comes from the twenty-one flat Desktop Patterns
   that shipped in the 9.0.4 Appearance control panel, a different one each
   time the skin appears — which is closer to the truth anyway, since the
   colour behind a Platinum dialog was never fixed by the OS version.

   Measured from a "Copy to the Desktop" window recovered at its native
   352x213, and checked again against a second capture that came back at
   exactly 6x. Everything here is off those two.

   Frame:      1px #000 outline, then a 4px raised band (#dadada, bevelled
               #fff on its top and left, #b3b3b3 on its bottom and right),
               then a 1px #000 line round the content, which is #e7e7e7.
               1px hard black drop shadow.
   Title bar:  20px between the outline and that content rule: 1px #fff,
               2px face, a 12-row band of #fff/#969696 1px stripes inset 5px
               from each side, 4px face, 1px #b3b3b3. The title sits on a
               face-coloured pill punched through the stripes, centred on
               the WHOLE bar rather than on the space beside the widget.
   Widget:     only the windowshade box, flush against the frame's white
               column with 4px of face between it and the stripes.
   Progress:   14px overall — #c0c0c0 above and left, #fff below and right,
               a 1px black frame, and a 10-row well. Empty well is #a5a5a5 /
               8 rows #cdcdcd / #e7e7e7. The fill is a ten-row lit cylinder
               (#5454ad up to #ffffff and back down to #000072) capped with
               a black column and casting #777/#a5a5a5 ahead of itself.
   Buttons:    59x20, 3px radius, 1px black; inside that 1px face then 1px
               #fff on the top and left, 1px #969696 then 1px #c0c0c0 on the
               bottom and right. The Stop button carries no default ring.
   Desktops:   flat — no dither in either capture.                        */

[data-os="macos89"] {
  --font: "Chicago", Geneva, monospace;
  --fsize: 16px; --lh: 16px;
  --dlg-w: 292px;
  --face: #e7e7e7; --text: #000;
  --title-h: 20px; --title-fg: #000;
  --pad: 10px; --gap: 15px;
  --bar-h: 14px; --btn-h: 20px; --btn-w: 59px;
  --notice-fg: var(--desk-fg, #000);
}

[data-os="macos89"] .dialog {
  border: 1px solid #000; background: #dadada; padding: 0 4px 4px;
  box-shadow: inset 1px 1px 0 #fff, inset -1px -1px 0 #b3b3b3, 1px 1px 0 #000;
}

/* Full bleed across the padding, so it has to paint the frame's own
   highlight and shade on the three edges it covers. */
[data-os="macos89"] .titlebar {
  margin: 0 -4px; padding: 0 5px;
  background-color: #dadada;
  background-image: repeating-linear-gradient(180deg, #fff 0 1px, #969696 1px 2px);
  /* the band stops 4px short of the windowshade box, which is 13px wide and
     overhangs the content box by 2 — so 15px off the end of the band. */
  background-size: calc(100% - 15px) 12px;
  background-position: 0 3px;
  background-origin: content-box;
  background-repeat: no-repeat;
  /* first listed paints on top, so the right frame reads outside in:
     #b3b3b3, two rows of #dadada, then #fff against the content. */
  box-shadow: inset 0 1px 0 #fff, inset 1px 0 0 #fff,
              inset 0 -1px 0 #b3b3b3, inset -1px 0 0 #b3b3b3,
              inset -3px 0 0 #dadada, inset -4px 0 0 #fff;
}
/* The title is centred on the WHOLE bar, not on the space left over beside
   the widget — measured at 987.5 against a window centre of 990.5 on a 6x
   capture, i.e. dead centre. So the two end cells have to balance. */
[data-os="macos89"] .tb-l { flex: 1 1 0; min-width: 0; }
[data-os="macos89"] .tb-r { flex: 1 1 0; justify-content: flex-end; }
[data-os="macos89"] .tb-c { flex: 0 1 auto; justify-content: center; }
[data-os="macos89"] .title { background: #dadada; padding: 0 5px; }

/* Only the windowshade box — this window has no close box. Drawn pixel for
   pixel off the capture: 1px #a5a5a5 above and left, 1px #fff below and
   right, a 1px #3f3f3f frame with two dividers, and a 7x7 Platinum ramp
   from #b3b3b3 to #ffffff inside. A CSS diagonal gradient antialiases at
   this size, which is what made the old one look soft. */
[data-os="macos89"] .w-b {
  display: block; width: 13px; height: 13px;
  margin-right: -2px;                    /* flush against the frame's white */
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' shape-rendering='crispEdges'%3E%3Cpath fill='%233F3F3F' d='M0 0h13v13H0z'/%3E%3Cpath fill='%23A5A5A5' d='M0 0h12v1h-12zM0 1h1v1h-1zM0 2h1v1h-1zM0 3h1v1h-1zM10 3h1v1h-1zM0 4h1v1h-1zM10 4h1v1h-1zM0 5h1v1h-1zM0 6h1v1h-1zM10 6h1v1h-1zM0 7h1v1h-1zM0 8h1v1h-1zM10 8h1v1h-1zM0 9h1v1h-1zM10 9h1v1h-1zM0 10h1v1h-1zM3 10h8v1h-8zM0 11h1v1h-1z'/%3E%3Cpath fill='%23DADADA' d='M12 0h1v1h-1zM3 2h8v1h-8zM2 3h1v1h-1zM9 3h1v1h-1zM2 4h1v1h-1zM8 4h2v1h-2zM2 6h1v1h-1zM6 6h2v1h-2zM2 8h1v1h-1zM4 8h2v1h-2zM2 9h3v1h-3zM2 10h1v1h-1zM0 12h1v1h-1z'/%3E%3Cpath fill='%23FFFFFF' d='M12 1h1v1h-1zM2 2h1v1h-1zM12 2h1v1h-1zM12 3h1v1h-1zM12 4h1v1h-1zM12 5h1v1h-1zM12 6h1v1h-1zM12 7h1v1h-1zM12 8h1v1h-1zM9 9h1v1h-1zM12 9h1v1h-1zM12 10h1v1h-1zM12 11h1v1h-1zM1 12h12v1h-12z'/%3E%3Cpath fill='%23B3B3B3' d='M3 3h2v1h-2zM3 4h1v1h-1z'/%3E%3Cpath fill='%23C0C0C0' d='M5 3h2v1h-2zM4 4h2v1h-2zM3 6h1v1h-1z'/%3E%3Cpath fill='%23CDCDCD' d='M7 3h2v1h-2zM6 4h2v1h-2zM4 6h2v1h-2zM3 8h1v1h-1z'/%3E%3Cpath fill='%23E7E7E7' d='M8 6h2v1h-2zM6 8h2v1h-2zM5 9h2v1h-2z'/%3E%3Cpath fill='%23F3F3F3' d='M8 8h2v1h-2zM7 9h2v1h-2z'/%3E%3C/svg%3E") 0 0 / 13px 13px no-repeat;
}

/* The 1px black rule under the title bar and round the content is this
   border; the shadows are the frame band's inner bevel — #b3b3b3 above and
   left, #fff below and right. */
[data-os="macos89"] .content {
  border: 1px solid #000; background: #e7e7e7;
  box-shadow: -1px -1px 0 #b3b3b3, 1px 1px 0 #fff;
  display: flex; flex-wrap: wrap; align-items: center; column-gap: 13px;
}
[data-os="macos89"] .message { flex: 0 0 100%; }
[data-os="macos89"] .progress { flex: 1 1 0; min-width: 0; margin-bottom: 0; }
[data-os="macos89"] .actions { flex: 0 0 auto; padding: 0; }

/* padding keeps .fill clear of the black frame, which is an inset shadow —
   an opaque child would paint straight over it. */
[data-os="macos89"] .track {
  height: 14px; padding: 1px;
  border: 1px solid; border-color: #c0c0c0 #fff #fff #c0c0c0;
  box-shadow: inset 0 0 0 1px #000;
  background-image: linear-gradient(180deg, #a5a5a5 0 1px, #cdcdcd 1px 9px, #e7e7e7 9px 10px);
  background-origin: content-box; background-clip: content-box;
}
/* The Lavender ramp, measured row by row off the capture. It is the default
   because the Mac OS Default theme is what eight visits in ten land on; the
   other Variations arrive as --fill, generated by the head script. */
[data-os="macos89"] .fill {
  background: var(--fill, linear-gradient(180deg,
    #5454ad 0 1px, #8787d4 1px 2px, #b3b3f9 2px 3px, #dadafc 3px 4px,
    #ffffff 4px 5px, #dadafc 5px 6px, #b3b3f9 6px 7px, #8787d4 7px 8px,
    #5454ad 8px 9px, #000072 9px 10px));
  box-shadow: inset -1px 0 0 #000, 1px 0 0 #777777, 2px 0 0 #a5a5a5;
  animation: none;
}

[data-os="macos89"] .notice { font-family: "Geneva", Verdana, sans-serif; }
[data-os="macos89"] .btn {
  width: 59px; padding: 0;
  border: 1px solid #000; border-radius: 3px; background: #e7e7e7;
  box-shadow: inset 1px 1px 0 #e7e7e7, inset -1px -1px 0 #969696,
              inset 2px 2px 0 #fff, inset -2px -2px 0 #c0c0c0;
}
[data-os="macos89"] .btn:active {
  box-shadow: inset 1px 1px 0 #969696, inset -1px -1px 0 #e7e7e7,
              inset 2px 2px 0 #c0c0c0, inset -2px -2px 0 #fff;
}

/* The desktop is drawn fresh each time this skin comes up — see the head
   script in index.html. The fallback is the Mac OS Default periwinkle, which
   is also what the draw lands on eight times in ten. */
[data-os="macos89"] .screen { background: var(--desk, #636398); }


/* ========= SKIN — Mac OS 8.5b6 appearance themes (Platinum variants) =====
   8.5b6 shipped six Appearance themes that reskinned Platinum rather than
   recolouring it. Apple cut them before 8.5 shipped; three are here. They are
   variants of the Mac OS 8 & 9 skin — same markup, same geometry, different
   surfaces — which is what an appearance was, so they are written as
   overrides of it. The head script draws one for one appearance in a hundred
   and renames the skin while it is up; the desktop stays Gray Space, which is
   what every capture shows.

   The captures recover cleanly at 2x and the control panel is itself drawn at
   2x in them, so every value below is a real pixel halved. Where a widget is
   a vertical ramp it is written out one stop per source row rather than
   approximated with two colours — the Hi-Tech caption is 22 rows, its button
   20, its slider 10 — and where it is a 2D pattern it is the lifted tile: the
   Gizmo rod is the real 16x15 cell, seven columns of red, a blend column,
   seven of blue, a blend, each row its own measured pair. Drawing Board's
   paper is not periodic and cannot be either, so it is a real 150x70 patch
   mirrored into a 300x140 tile that repeats without a seam — img/db-paper.png,
   10 KB, and only ever fetched when this theme is the one that came up.   */

/* ---- Drawing Board ----------------------------------------------------
   Drafting paper, no bevel anywhere: every edge is a drawn line and every
   shadow a hatch. The button is the giveaway — face #cdc6b7 under a light
   #8b867e rule and over a heavy #282828 one, which is how you draw an
   elevation, not a control.                                              */

[data-os="macos89"][data-theme="drawing-board"] {
  --face: #e5ded7; --text: #000;
  --title-fg: #000;
}
[data-os="macos89"][data-theme="drawing-board"] .dialog {
  position: relative;
  border: 1px solid #55504a;
  background: url("../img/db-paper.png") 0 0 repeat, #e5ded7;
  box-shadow: none;
}
/* The hatched shadow this theme uses in place of every bevel. .stage is
   transformed and so makes the stacking context that keeps z-index -1 from
   falling through the page. */
[data-os="macos89"][data-theme="drawing-board"] .dialog::after {
  content: ""; position: absolute; z-index: -1;
  left: 5px; top: 5px; right: -5px; bottom: -5px;
  border: 1px solid #55504a;
  background: repeating-linear-gradient(45deg, #6d675f 0 1px, #e5ded7 1px 3px);
}
/* Registration mark, hanging outside the frame as it does on the real one. */
[data-os="macos89"][data-theme="drawing-board"] .dialog::before {
  content: ""; position: absolute; z-index: 1; pointer-events: none;
  left: -9px; top: -9px; width: 24px; height: 24px;
  background: url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='24'%20height='24'%20shape-rendering='crispEdges'><g%20stroke='%2355504a'%20stroke-width='1'%20fill='none'><path%20d='M6.5%206.5h11v11h-11z'/><path%20d='M12.5%200v24M0%2011.5h24'/></g></svg>") 0 0 / 24px 24px no-repeat;
}
[data-os="macos89"][data-theme="drawing-board"] .titlebar {
  background: url("../img/db-paper.png") 0 0 repeat, #e5ded7;
  box-shadow: none;
  border-bottom: 1px solid #55504a;
}
[data-os="macos89"][data-theme="drawing-board"] .title { background: none; }
[data-os="macos89"][data-theme="drawing-board"] .w-b {
  background: #e5ded7 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' shape-rendering='crispEdges'%3E%3Cpath fill='%2355504a' d='M0 0h13v1H0zM0 12h13v1H0zM0 0h1v13H0zM12 0h1v13h-1zM3 3h7v1H3zM3 6h7v1H3zM3 9h7v1H3z'/%3E%3C/svg%3E") 0 0 / 13px 13px no-repeat;
}
[data-os="macos89"][data-theme="drawing-board"] .content {
  border: 1px solid #55504a;
  background: url("../img/db-paper.png") 0 0 repeat, #e5ded7;
  box-shadow: none;
}
[data-os="macos89"][data-theme="drawing-board"] .track {
  border: 1px solid #55504a;
  box-shadow: none;
  background-image: none;
  background-color: #eee7d8;
}
[data-os="macos89"][data-theme="drawing-board"] .fill {
  background: repeating-linear-gradient(45deg, #55504a 0 1px, #eee7d8 1px 3px);
  box-shadow: none;
}
[data-os="macos89"][data-theme="drawing-board"] .btn {
  border: 0;
  border-radius: 0;
  color: #000;
  background:
    repeating-linear-gradient(45deg, #55504a 0 1px, #cdc6b7 1px 3px) right 0 top 1px / 7px calc(100% - 3px) no-repeat,
    #cdc6b7;
  box-shadow: inset 0 1px 0 #8b867e, inset 1px 0 0 #8b867e, inset -1px 0 0 #8b867e,
              inset 0 -1px 0 #686868, inset 0 -2px 0 #282828;
}
[data-os="macos89"][data-theme="drawing-board"] .btn:active {
  background: #b8b3a8;
  box-shadow: inset 0 2px 0 #282828, inset 0 1px 0 #686868, inset 0 -1px 0 #8b867e;
}

/* ---- Gizmo -------------------------------------------------------------
   Rebuilt from the theme file, like Hi-Tech. Gizmo on Curves is the loudest of
   the three: lit rods for a caption, a green ball and a blue one for the
   widgets, a yellow cable hanging down the side into a purple planter, and the
   window name on a black plaque with a serrated top.

   scen 128 "Gizmo on Curves": large system font Gadget, desktop pattern
   "Wiggly lines", highlight "Poppy" #ffcc66.

   Font:     Gadget, the face's own 12ppem bitmaps rendered from the suitcase —
             build/ttf-strike.py, then build/prop-font.py at 13 rows / 10.
   Desktop:  img/gz-wiggle.png IS "Wiggly lines", the theme's own 64x64 1-bit
             pattern out of the scenario record: #eeeeee on white.
   Rods:     ppat 6159 for the striped one (16x16, seven red columns and seven
             blue on a 16px pitch, each row its own pair) — a real tile, since
             no gradient can vary a cylinder per stripe. The green and purple
             rods are one column each, so those are per-row stops: ppat 6160
             and 6162.
   Widgets:  pxm# 200 and 210 are the balls, 16x16; the vine is 6177 at 14x38
             and the planter 6173 at 15x19, both taken in their active state.
             img/gz-parts.png carries the three that do not tile.
   Plaque:   pxm# 6155, a 64x8 comb — one row of teeth, two on and two off, over
             solid black. The name is #ffce00, out of the theme's own palette.
   Edges:    the right and bottom of a Gizmo window are a 4px rod striped in
             4px dashes, orange and grey. ppat 6156 is the vertical one and
             6157 its transpose; the ramp, inside to out, is 222222 888888
             444444 111111 for the grey dash and cc3300 ffcc00 ff9900 ff6600
             for the orange, which is what "Doc Win Bottom Corners" carries
             round the corner as well. Between the rod and the content sits a
             1px #777 rail. Measured off the reference: it is a 2x capture, so
             the 8px dash pitch reads as 16 there and the four ramp rows as
             eight — that is how the two ppats were identified.

   Simplified: the real window hangs its caption across the top edge, with the
   desktop showing between the rods and the frame, and runs the cable down both
   sides. Here the caption sits inside the frame and the cable runs down the
   left only — this dialog is a fifth the size of that control panel and the
   full arrangement would be all cable and no window.                        */

[data-os="macos89"][data-theme="gizmo"] {
  --font: "Gadget", "Chicago", monospace;
  --fsize: 13px; --lh: 13px;
  --face: #fff; --text: #000;
  --title-fg: #ffce00;
  --title-h: 22px;
  --bar-h: 22px; --btn-h: 21px; --btn-w: 64px;
  --pad: 12px; --gap: 14px;
  --notice-fg: #000;                     /* the desktop is white */
}
/* "Wiggly lines", at the 1:1 it was drawn for. */
[data-os="macos89"][data-theme="gizmo"] .screen {
  background-color: #fff;
  background-image: url("../img/gz-wiggle.png");
  background-size: calc(64px * var(--zoom)) calc(64px * var(--zoom));
}
/* Both of the things that hang off this box — the striped edge on the right and
   bottom, the cable on the left — are pseudo-elements behind it, which works
   because .stage carries the zoom transform and so makes the stacking context.
   Two hangers, two pseudo-elements, so the cable and its planter share one box
   and are two background layers of it. */
[data-os="macos89"][data-theme="gizmo"] .dialog {
  position: relative;
  /* The cable hangs 14px past the left edge and the striped rod 5px past the
     right. A margin buys them that room inside .stage, so they are inside the
     zoom transform, inside the review crop, and the dialog still sits centred
     over the address. */
  margin: 0 14px;
  border: 3px solid #000;
  border-radius: 10px;
  background: #fff;
  padding: 4px 8px 8px;
  box-shadow: none;
}
/* The striped edge: a 1px #777 rail against the frame, then the 4px rod, which
   is anchored to the outer edges so the two runs meet at the corner and the
   radius carries them round it the way "Doc Win Bottom Corners" does. */
[data-os="macos89"][data-theme="gizmo"] .dialog::before {
  content: "";
  position: absolute; z-index: -1;
  /* An absolutely positioned child is laid out against the padding box, so the
     3px frame has to come back out of every offset before the 5px of rail and
     rod is added on the two edges that carry it. */
  inset: -3px -8px -8px -3px;
  border-radius: 13px 18px 18px 13px;
  background:
    url("../img/gz-edge-v.png") right top / 4px 8px repeat-y,
    url("../img/gz-edge-h.png") left bottom / 8px 4px repeat-x,
    #777;
}
/* The cable, and the planter it ends in. */
[data-os="macos89"][data-theme="gizmo"] .dialog::after {
  content: "";
  position: absolute; z-index: -1;
  left: -14px; top: 10px; bottom: -13px; width: 15px;
  background:
    url("../img/gz-parts.png") -32px bottom / 47px 19px no-repeat,
    url("../img/gz-vine.png") left top / 14px 38px repeat-y;
}
/* ball | striped rod | plaque | green rod | ball. The two ends grow, so the
   plaque stays centred the way the control panel's does. */
[data-os="macos89"][data-theme="gizmo"] .titlebar {
  margin: 0;
  padding: 0;
  background: none;
  box-shadow: none;
  border: 0;
  align-items: center;
  gap: 0;
}
[data-os="macos89"][data-theme="gizmo"] .tb-l,
[data-os="macos89"][data-theme="gizmo"] .tb-r {
  flex: 1 1 0; min-width: 16px; height: 16px; gap: 0;
  background-repeat: repeat-x;
}
[data-os="macos89"][data-theme="gizmo"] .tb-l {
  background-image: url("../img/gz-rod.png");
  background-size: 16px 16px;
}
[data-os="macos89"][data-theme="gizmo"] .tb-r {
  justify-content: flex-end;
  background-image: linear-gradient(180deg,
    #003300 0px 1px,
    #005500 1px 2px,
    #006600 2px 3px,
    #008800 3px 4px,
    #00aa00 4px 5px,
    #00cc33 5px 6px,
    #00ee00 6px 7px,
    #66ff00 7px 8px,
    #00ee00 8px 9px,
    #00cc33 9px 10px,
    #00aa00 10px 11px,
    #008800 11px 12px,
    #007700 12px 13px,
    #006600 13px 14px,
    #005500 14px 15px,
    #003300 15px 16px);
}
[data-os="macos89"][data-theme="gizmo"] .tb-c { flex: 0 1 auto; align-self: stretch; }
/* pxm# 200 and 210, out of img/gz-parts.png — the green ball caps the rod and
   the blue one is the collapse widget. */
[data-os="macos89"][data-theme="gizmo"] .w-close,
[data-os="macos89"][data-theme="gizmo"] .w-b {
  display: block; flex: none;
  width: 16px; height: 16px;
  background: url("../img/gz-parts.png") no-repeat;
  background-size: 47px 19px;
}
[data-os="macos89"][data-theme="gizmo"] .w-close { background-position: 0 0; }
[data-os="macos89"][data-theme="gizmo"] .w-b { background-position: -16px 0; }
[data-os="macos89"][data-theme="gizmo"] .w-a { display: none; }
/* The plaque runs the full height of the band and carries the comb on top. */
[data-os="macos89"][data-theme="gizmo"] .title {
  color: #ffce00;
  padding: 5px 8px 4px;
  align-self: stretch;
  line-height: 13px;
  background:
    repeating-linear-gradient(90deg, #000 0 2px, transparent 2px 4px)
      left top / 4px 1px repeat-x,
    linear-gradient(#000, #000) left 1px / 100% calc(100% - 1px) no-repeat;
}
[data-os="macos89"][data-theme="gizmo"] .content {
  border: 0;
  background: #fff;
  box-shadow: none;
  padding-top: 4px;
}
/* A rod in a heavy black tube, the way the control panel draws its bar. */
[data-os="macos89"][data-theme="gizmo"] .track {
  height: 22px;
  padding: 3px;
  border: 0;
  border-radius: 11px;
  background: #000;
  box-shadow: none;
}
[data-os="macos89"][data-theme="gizmo"] .fill {
  border-radius: 8px;
  background: linear-gradient(180deg,
    #330033 0px 1px,
    #660066 1px 2px,
    #660066 2px 3px,
    #9900ff 3px 4px,
    #9933ff 4px 5px,
    #cc66ff 5px 6px,
    #cc99ff 6px 7px,
    #ffccff 7px 8px,
    #cc99ff 8px 9px,
    #cc66ff 9px 10px,
    #9933ff 10px 11px,
    #9900ff 11px 12px,
    #9900ff 12px 13px,
    #660066 13px 14px,
    #660066 14px 15px,
    #330033 15px 16px);
  box-shadow: none;
  animation: none;
}
/* Measured off the reference's "Save Theme..." button, which is 104x21 native.
   Two nested rings on a #ddd face: #ccc outside and #fff inside on the lit
   top-left, #888 outside and #aaa inside on the shaded bottom-right. Every one
   of those is in the theme's own plut 387, which is the check that the capture
   was read at 1:1 and not off by a resample. */
[data-os="macos89"][data-theme="gizmo"] .btn {
  border: 1px solid;
  border-color: #ccc #888 #888 #ccc;
  border-radius: 4px;
  background: #ddd;
  color: #000;
  box-shadow: inset 1px 1px 0 #fff, inset -1px -1px 0 #aaa;
}
[data-os="macos89"][data-theme="gizmo"] .btn:active,
[data-os="macos89"][data-theme="gizmo"] .btn:focus-visible {
  outline: 0;
  border-color: #888 #ccc #ccc #888;
  background: #aaa;
  box-shadow: inset 1px 1px 0 #777, inset -1px -1px 0 #ddd;
}


/* ---- Hi-Tech -----------------------------------------------------------
   Rebuilt from the theme file itself. Hami sent the three 1998 Appearance
   extensions; their resource forks carry the whole theme — the scenario
   record that names its fonts and its desktop, 122 pixel patterns, 183 named
   pixmaps of every widget. So the values below are Apple's own art rather
   than a reading of a screenshot, and where a screenshot is still the source
   it is the recovered 1:1 grid of Hami's two captures.

   scen 128 "Hi-Tech Neon" says: large system font Techno, small system font
   Geneva, desktop pattern "Dark Metal Floor", highlight "Light Blue" #7abdff.

   Font:     Techno — Hami has the suitcase, so this is the face's own 12ppem
             bitmaps rendered from it with its own hints rather than lifted
             off a screenshot. 93 glyphs, nothing drawn. See
             build/techno-render.py and build/prop-font.py.
   Desktop:  img/ht-plate.png IS "Dark Metal Floor" — the theme's own 128x128
             8-bit pattern, lifted out of the scenario's patt record, so it
             tiles at 1:1 exactly as it did on the desktop.
   Widgets:  the close and collapse boxes are pxm# 200 and 210, 12x12, both
             states, run-length as inline SVG. Concentric squares, a #191919
             edge above and left and a #666666 one below and right.
   Frame:    1px #386bd9, then an 8-row bead measured across both corner
             close-ups: #1e1e1e #4b4b4b #555555 #2b2b2b #151515 #3a3a3a
             #767676 to the face. A real extrusion, not an outline.
   Caption:  24px — 1px #2452c1, a 22-row ramp #bbbbbb to #020202, 1px
             #1e4cb8 — then #06193e, #0d0d0d, #363636 into the client.
   Name:     hard left in a #0a0a0a plaque with a #313131 top edge, flush to
             the bottom of the band, immediately after the close box.
   Button:   its own 21-row ramp, a #848484 highlight under a #545454 edge
             and a long fall to #0f0f0f. Pressed is the default button off
             the Save Theme sheet: a dark blue bead round a #2a64f6 face.
   Bar:      the measured 10-row cylinder, #020249 up to a #80b1f9 specular. */

[data-os="macos89"][data-theme="hi-tech"] {
  --font: "Techno", "Chicago", monospace;
  --fsize: 13px; --lh: 13px;              /* 13 = the cell, so it sits 1:1
                                            and the baseline stays on a pixel */
  --face: #4a4a4a; --text: #fff;
  --title-fg: #fff;
  --title-h: 23px;
  --notice-fg: #fff;                     /* the plate is nearly black */
}
/* "Dark Metal Floor", at the 1:1 it was drawn for. */
[data-os="macos89"][data-theme="hi-tech"] .screen {
  background-color: #232323;
  background-image: url("../img/ht-plate.png");
  background-size: calc(128px * var(--zoom)) calc(128px * var(--zoom));
}
/* The two end placards sit four rows below the top of the window and the
   window's outline steps down to meet them, so the top corners are notched
   rather than square. clip-path cuts the notch out of the frame; the caps
   carry their own blue rule across it. */
[data-os="macos89"][data-theme="hi-tech"] .dialog {
  border: 1px solid #386bd9;
  background: #4a4a4a;
  padding: 0 8px 8px;
  clip-path: polygon(0 4px, 11px 4px, 11px 0,
                     calc(100% - 24px) 0, calc(100% - 24px) 4px,
                     100% 4px, 100% 100%, 0 100%);
  box-shadow:
    inset 0 0 0 1px #1e1e1e,
    inset 0 0 0 2px #4b4b4b,
    inset 0 0 0 3px #555555,
    inset 0 0 0 4px #2b2b2b,
    inset 0 0 0 5px #151515,
    inset 0 0 0 6px #3a3a3a,
    inset 0 0 0 7px #767676,
    inset 0 0 0 8px #4a4a4a;
}
/* Full bleed to the frame: at this level the window has only two dark columns
   between the caption and its blue border, not the eight-row bead the client
   area gets. The ramp is the one measured off the 4x corner capture, which
   recovers at an exact integer scale — 1px of #4e82f1 and then 22 rows. */
[data-os="macos89"][data-theme="hi-tech"] .titlebar {
  margin: 0 -8px;
  padding: 0;
  position: relative;
  z-index: 1;                            /* the rule below hangs over .content */
  overflow: visible;
  background: linear-gradient(180deg,
    #4e82f1 0 1px,
    #d8d8d8 1px 2px,
    #ababab 2px 3px,
    #a3a3a3 3px 4px,
    #9a9a9a 4px 5px,
    #929292 5px 6px,
    #8a8a8a 6px 7px,
    #828282 7px 8px,
    #797979 8px 9px,
    #717171 9px 10px,
    #696969 10px 11px,
    #616161 11px 12px,
    #585858 12px 13px,
    #505050 13px 14px,
    #484848 14px 15px,
    #404040 15px 16px,
    #373737 16px 17px,
    #2f2f2f 17px 18px,
    #272727 18px 19px,
    #1f1f1f 19px 20px,
    #161616 20px 21px,
    #0e0e0e 21px 22px,
    #060606 22px 23px);
  box-shadow: none;
  border: 0;
  align-items: flex-start;
}
/* The blue rule and the two dark rows under the caption run a pixel PROUD of
   the caption on each side, crossing the frame rather than stopping inside it
   — which is what the corner close-up shows and what the inset shadow on
   .content could not do, since .content sits eight pixels in from the frame. */
[data-os="macos89"][data-theme="hi-tech"] .titlebar::after {
  content: "";
  position: absolute;
  left: -1px; right: -1px; top: 100%;
  height: 4px;
  background: linear-gradient(180deg,
    #06193e 0 1px, #1e4cb8 1px 2px, #040404 2px 3px, #1d1d1d 3px 4px);
}
/* img/ht-caps.png is the two ends lifted whole out of the corner captures. On
   the left, 19px: ten of empty placard — Hi-Tech's close box is off, so what is
   left is the pocket it sat in — then the blue divider and eight of plain
   window chrome before the name starts, which is the gap the reference shows.
   On the right, 23px carrying the collapse box, its well and the two dark
   columns that meet the frame. The placard and the collapse box sit three rows
   down and the window's outline steps to meet them, which is what the notch
   above is for; the divider and the chrome run the full height. */
[data-os="macos89"][data-theme="hi-tech"] .tb-l,
[data-os="macos89"][data-theme="hi-tech"] .tb-r {
  flex: none;                            /* Platinum lets these grow; here they
                                            are the width of their own art */
  gap: 0;
  height: 23px;
  background: url("../img/ht-caps.png") no-repeat;
  background-size: 42px 23px;
}
[data-os="macos89"][data-theme="hi-tech"] .tb-l { width: 19px; background-position: 0 0; }
[data-os="macos89"][data-theme="hi-tech"] .tb-r { width: 23px; background-position: -19px 0; }
[data-os="macos89"][data-theme="hi-tech"] .w-close,
[data-os="macos89"][data-theme="hi-tech"] .w-b { display: none; }
[data-os="macos89"][data-theme="hi-tech"] .tb-c {
  flex: 1 1 auto;
  justify-content: flex-start;
  align-items: stretch;
  align-self: stretch;
}
/* Hard left against the placard, and flush to the bottom of the band — the
   change Hami flagged: Platinum centres the name, Hi-Tech hangs it off the
   left in its own plaque. 19 rows of the caption's 22, flush to the bottom of
   the band, three pixels of black either side of the name's own advance and
   two above the cap — measured off the 4x plaque capture. */
[data-os="macos89"][data-theme="hi-tech"] .title {
  background: #0a0a0a;
  color: #fff;
  padding: 2px 3px 4px;
  margin: 4px 0 0;
  line-height: 13px;
  box-shadow: inset 0 1px 0 #1e1e1e,
              inset 1px 0 0 #1e1e1e, inset -1px 0 0 #1e1e1e;
}
[data-os="macos89"][data-theme="hi-tech"] .content {
  border: 0;
  background: #4a4a4a;
  box-shadow: none;                      /* the titlebar's ::after draws these */
  padding-top: 15px;
}
/* The bar is the theme's own: ppat 7514 is the empty trough — which is where
   the light rule through the unfilled part comes from, rows 5 to 7 of it — and
   ppat 7621 is the fill, one of the four frames of the sweep Apple animated,
   taken at rest. Both are 14 rows, and the ends are pxm# 520/521 for the
   trough and 525/526 for the fill, two columns each, which is what rounds the
   blue off rather than cutting it square. Round that, the frame the reference
   shows: #3d3d3d above and left, #484848 below and right. */
[data-os="macos89"][data-theme="hi-tech"] .track {
  height: 16px;
  padding: 1px;
  border: 0;
  box-shadow: inset 1px 1px 0 #3d3d3d, inset -1px -1px 0 #484848;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='14' shape-rendering='crispEdges'%3E%3Cpath fill='%23181818' d='M0 0h1v1h-1zM0 1h1v1h-1zM0 2h1v1h-1zM0 3h1v1h-1zM0 4h1v1h-1zM0 5h1v1h-1zM0 6h1v1h-1zM0 7h1v1h-1zM0 8h1v1h-1zM0 9h1v1h-1zM0 10h1v1h-1zM0 11h1v1h-1zM0 12h1v1h-1zM0 13h1v1h-1zM1 0h1v1h-1z'/%3E%3Cpath fill='%23080808' d='M1 1h1v1h-1zM1 2h1v1h-1zM1 3h1v1h-1zM1 4h1v1h-1zM1 5h1v1h-1zM1 6h1v1h-1zM1 7h1v1h-1zM1 8h1v1h-1zM1 9h1v1h-1zM1 10h1v1h-1zM1 11h1v1h-1zM1 12h1v1h-1z'/%3E%3Cpath fill='%23737373' d='M1 13h1v1h-1z'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='14' shape-rendering='crispEdges'%3E%3Cpath fill='%23181818' d='M0 0h1v1h-1zM1 0h1v1h-1z'/%3E%3Cpath fill='%23080808' d='M0 1h1v1h-1z'/%3E%3Cpath fill='%23292929' d='M0 2h1v1h-1zM0 3h1v1h-1zM0 4h1v1h-1zM0 5h1v1h-1zM0 6h1v1h-1zM0 7h1v1h-1zM0 8h1v1h-1zM0 9h1v1h-1zM0 10h1v1h-1zM0 11h1v1h-1zM0 12h1v1h-1z'/%3E%3Cpath fill='%23737373' d='M0 13h1v1h-1zM1 1h1v1h-1zM1 2h1v1h-1zM1 3h1v1h-1zM1 4h1v1h-1zM1 5h1v1h-1zM1 6h1v1h-1zM1 7h1v1h-1zM1 8h1v1h-1zM1 9h1v1h-1zM1 10h1v1h-1zM1 11h1v1h-1zM1 12h1v1h-1zM1 13h1v1h-1z'/%3E%3C/svg%3E"),
    linear-gradient(180deg,
    #181818 0px 1px,
    #080808 1px 2px,
    #181818 2px 3px,
    #181818 3px 4px,
    #080808 4px 5px,
    #393939 5px 6px,
    #5a5a5a 6px 7px,
    #313131 7px 8px,
    #000000 8px 9px,
    #101010 9px 10px,
    #181818 10px 11px,
    #101010 11px 12px,
    #292929 12px 13px,
    #737373 13px 14px);
  background-position: left top, right top, left top;
  background-size: 2px 14px, 2px 14px, auto 14px;
  background-repeat: no-repeat, no-repeat, repeat-x;
}
/* The blue starts one pixel inside the trough, so the trough's own left cap
   still shows beside it — the capture has a dark column between the frame and
   the start of the fill. */
[data-os="macos89"][data-theme="hi-tech"] .fill {
  margin: 0 1px;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='14' shape-rendering='crispEdges'%3E%3Cpath fill='%23181818' d='M0 0h1v1h-1zM1 0h1v1h-1z'/%3E%3Cpath fill='%23080808' d='M0 1h1v1h-1zM1 1h1v1h-1z'/%3E%3Cpath fill='%23000031' d='M0 2h1v1h-1zM0 10h1v1h-1zM1 11h1v1h-1z'/%3E%3Cpath fill='%23000041' d='M0 3h1v1h-1zM0 9h1v1h-1zM1 2h1v1h-1zM1 10h1v1h-1z'/%3E%3Cpath fill='%23000062' d='M0 4h1v1h-1zM1 3h1v1h-1z'/%3E%3Cpath fill='%230031CD' d='M0 5h1v1h-1zM0 7h1v1h-1zM1 4h1v1h-1zM1 8h1v1h-1z'/%3E%3Cpath fill='%230062FF' d='M0 6h1v1h-1zM1 5h1v1h-1zM1 7h1v1h-1z'/%3E%3Cpath fill='%230000BD' d='M0 8h1v1h-1zM1 9h1v1h-1z'/%3E%3Cpath fill='%23000020' d='M0 11h1v1h-1z'/%3E%3Cpath fill='%23292929' d='M0 12h1v1h-1zM1 12h1v1h-1z'/%3E%3Cpath fill='%23737373' d='M0 13h1v1h-1zM1 13h1v1h-1z'/%3E%3Cpath fill='%235294FF' d='M1 6h1v1h-1z'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='14' shape-rendering='crispEdges'%3E%3Cpath fill='%23181818' d='M0 0h1v1h-1zM1 0h1v1h-1z'/%3E%3Cpath fill='%23080808' d='M0 1h1v1h-1zM1 1h1v1h-1z'/%3E%3Cpath fill='%23000041' d='M0 2h1v1h-1zM0 10h1v1h-1zM1 3h1v1h-1zM1 9h1v1h-1z'/%3E%3Cpath fill='%23000062' d='M0 3h1v1h-1zM1 4h1v1h-1z'/%3E%3Cpath fill='%230031CD' d='M0 4h1v1h-1zM0 8h1v1h-1zM1 5h1v1h-1zM1 7h1v1h-1z'/%3E%3Cpath fill='%230062FF' d='M0 5h1v1h-1zM0 7h1v1h-1zM1 6h1v1h-1z'/%3E%3Cpath fill='%235294FF' d='M0 6h1v1h-1z'/%3E%3Cpath fill='%230000BD' d='M0 9h1v1h-1zM1 8h1v1h-1z'/%3E%3Cpath fill='%23000031' d='M0 11h1v1h-1zM1 2h1v1h-1zM1 10h1v1h-1z'/%3E%3Cpath fill='%23292929' d='M0 12h1v1h-1zM1 12h1v1h-1z'/%3E%3Cpath fill='%23737373' d='M0 13h1v1h-1zM1 13h1v1h-1z'/%3E%3Cpath fill='%23000020' d='M1 11h1v1h-1z'/%3E%3C/svg%3E"),
    linear-gradient(180deg,
    #181818 0px 1px,
    #080808 1px 2px,
    #000063 2px 3px,
    #0031ce 3px 4px,
    #0063ff 4px 5px,
    #5294ff 5px 6px,
    #7bbdff 6px 7px,
    #5294ff 7px 8px,
    #0063ff 8px 9px,
    #0031ce 9px 10px,
    #0000bd 10px 11px,
    #000042 11px 12px,
    #292929 12px 13px,
    #737373 13px 14px);
  background-position: left top, right top, left top;
  background-size: 2px 14px, 2px 14px, auto 14px;
  background-repeat: no-repeat, no-repeat, repeat-x;
  box-shadow: none;
}
[data-os="macos89"][data-theme="hi-tech"] .btn {
  border: 0;
  border-radius: 0;
  color: #fff;
  height: 22px;
  background: linear-gradient(180deg,
    #4b4b4b 0px 1px,
    #7d7d7d 1px 2px,
    #777777 2px 3px,
    #717171 3px 4px,
    #6c6c6c 4px 5px,
    #666666 5px 6px,
    #606060 6px 7px,
    #5b5b5b 7px 8px,
    #555555 8px 9px,
    #4f4f4f 9px 10px,
    #4a4a4a 10px 11px,
    #444444 11px 12px,
    #3e3e3e 12px 13px,
    #393939 13px 14px,
    #333333 14px 15px,
    #2e2e2e 15px 16px,
    #282828 16px 17px,
    #222222 17px 18px,
    #191919 18px 19px,
    #111111 19px 20px,
    #121212 20px 21px,
    #3b3b3b 21px 22px);
  box-shadow: inset 1px 0 0 #4b4b4b, inset 2px 0 0 rgba(255,255,255,.10),
              inset -1px 0 0 #3b3b3b, inset -2px 0 0 #1a1a1a;
}
/* This is the theme's DEFAULT button, not its pressed one: the theme file has
   both, as frme 566 ActiveDefaultPushbutton and frme 563 PressedPushbutton,
   and the blue bead is the former. Our dialog has one button and it is not a
   default button, so the bead is what the press wears — Hami's call.

   It GROWS: the bead is drawn round the button, not inside it, so four of its
   six rings hang outside the 59x22 box and the button reads as 67x30 while it
   is down. box-shadow does that without disturbing the layout, so nothing in
   the dialog moves. Rings, outward from the face: #2458e4 #030c7e #0106ab
   #0b25c4 #0106c4 #08086c, and the inner three are bevelled — the dark value
   above and left, a lighter one below and right. The label goes dark blue,
   #030c72, which is the same blue as the fifth ring. */
[data-os="macos89"][data-theme="hi-tech"] .btn:active,
[data-os="macos89"][data-theme="hi-tech"] .btn:focus-visible {
  outline: 0;
  background: #2a64f6;
  color: #030c72;
  border-radius: 2px;
  box-shadow:
    -1px -1px 0 0 #0106ab,                /* ring 4, outside, bevelled */
     1px  1px 0 0 #121ebe,
    0 0 0 2px #0b25c4,                    /* rings 3, 2, 1 — uniform */
    0 0 0 3px #0106c4,
    0 0 0 4px #08086c,
    inset  1px  1px 0 0 #030c7e,          /* rings 5 and 6, inside, bevelled */
    inset -1px -1px 0 0 #6c95f0,
    inset  2px  2px 0 0 #2458e4,
    inset -2px -2px 0 0 #346ef6;
}


/* ======================= SKIN — Newton OS (1993) ========================
   Modelled on the "How do I..." slip, at the proportions of the slips that
   sit in the lower third — Find and Assist. The reference captures are 1-bit
   and scaled, so this is read for structure; the LCD colour stays.

   Slip edge:   2px solid black, ~8px corner radius, and immediately inside
                it a 50% checkerboard band before the body starts. No drop
                shadow — the Newton guidelines forbid one.
   Title:       a solid black tab hanging from the top edge, centred, with
                the title knocked out of it in white bold. Not a title bar.
   Gauge:       Newton draws a progress bar as a thick solid black rule for
                the part that is done and a fine dotted rule for the part
                that is not — the Volume, Contrast and Battery gauges in the
                Extras drawer are all this. No trough, no outline.
   Cancel:      in Newton the X box IS cancel, so that is what the button
                is: a rounded 20px square with a 2px black outline and a
                bold X inside, bottom right. Pressed inverts, as it does on
                the device.                                               */

[data-os="newton"] {
  --font: "Geneva", Verdana, sans-serif;
  --fsize: 16px; --lh: 18px;
  --dlg-w: 300px;
  --face: #fbfcf4; --text: #000;
  --title-h: 0px; --title-fg: #fbfcf4;
  --pad: 16px; --gap: 16px;
  --bar-h: 9px; --btn-h: 20px; --btn-w: 20px;
  --notice-fg: #000;
  --dot: calc(4px * var(--zoom));
}
[data-os="newton"] .screen {
  background-color: #c9cfbe;
  background-image: radial-gradient(circle, #a7ae9a 20%, transparent 21%);
  background-size: var(--dot) var(--dot);
}

/* The checkerboard is the dialog's own background; .content covers all of it
   but the 3px the padding leaves showing. */
[data-os="newton"] .dialog {
  position: relative;
  border: 2px solid #000; border-radius: 9px;
  padding: 3px;
  background: repeating-conic-gradient(#000 0 25%, #fbfcf4 0 50%) 0 0 / 2px 2px;
}
[data-os="newton"] .content {
  background: #fbfcf4; border-radius: 5px;
  padding-top: 26px;                     /* clear of the tab */
}

/* Lifted out of the flow so it can straddle the top edge. */
[data-os="newton"] .titlebar {
  position: absolute; top: -2px; left: 2px; right: 2px;
  height: auto; z-index: 2;
  background: none; border: 0; overflow: visible;
  justify-content: center;
}
[data-os="newton"] .tb-c  { flex: 0 1 auto; justify-content: center; }
[data-os="newton"] .title {
  background: #000; color: #fbfcf4;
  font-weight: bold; font-size: 14px; line-height: 19px;
  padding: 0 9px;
}

/* Solid rule for what is done, dotted rule for what is not. */
[data-os="newton"] .track {
  height: 9px; border: 0; border-radius: 0; background: none;
  background-image: repeating-linear-gradient(90deg, #000 0 1px, transparent 1px 3px);
  background-size: 100% 1px;
  background-position: 0 4px;
  background-repeat: no-repeat;
}
[data-os="newton"] .fill {
  height: 5px; margin-top: 2px; border-radius: 0;
  background: #000;
}

[data-os="newton"] .actions  { justify-content: flex-end; padding: 0; }
[data-os="newton"] .btn {
  padding: 0; border: 2px solid #000; border-radius: 5px;
  font-size: 0; color: transparent;
  background: #fbfcf4
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' shape-rendering='crispEdges'%3E%3Cpath d='M1 1 L11 11 M11 1 L1 11' stroke='%23000' stroke-width='2' fill='none'/%3E%3C/svg%3E")
    center / 12px 12px no-repeat;
}
[data-os="newton"] .btn:active  { filter: invert(1); }


/* ======================= SKIN — Windows 3.1 (1992) ======================
   Re-read from Hami's 8x capture of File Manager's Search dialog. What was
   here before was a Program Manager GROUP WINDOW — a thin grey sizing border
   with minimise and maximise boxes. This page is a modal installer dialog, so
   what it wants is DLGMODALFRAME, and that is what the capture shows.

   The capture holds six colours and nothing else — #000000, #000080, #808080,
   #c0c0c0, #ffffff, and a single #ffff00 caret in the text field — every one
   a 16-colour VGA palette entry.

   Chrome, outside in, and identical to 3.0's row for row:
     1px black
     4px frame (3px on the top edge, as both captures have it)
     1px white ring around the whole client
     18px caption, then a 1px black rule under it
     an 18px system-menu box hard against the caption's left, with a 1px
     black edge on its right

   The one thing that separates the two is the frame and caption fill: 3.0
   dithers #000080 against #008080 at 16 colours, 3.1 paints solid #000080.
   The system-menu box is the same object in both, down to the pixel.

   Title is white, bold, and centred on the caption's remaining span rather
   than on the window — ink 223-265 of a 470px window whose caption runs
   26-462, so 244.0 against 244.0, not the window's own 234.5. That is what
   the flex centring in .tb-c does anyway.

   Body:     WHITE. A 3.1 dialog client is not the grey of its buttons.
   Progress: 3.1 shipped no progress control — Setup drew its own sunken box,
             which is what this is.
   Desktop:  flat #c0c0c0, as the captures have it.                        */

[data-os="win31"] {
  --font: "MS Sans Serif", Arial, sans-serif;
  /* px, not a ratio: 11 x 1.4 is 15.4, which makes .stage a fraction of a
     pixel tall and puts the centred dialog on a half pixel. */
  --fsize: 11px; --lh: 15px;
  --dlg-w: 320px;
  --face: #fff; --text: #000;
  --title-h: 20px; --title-bg: #000080; --title-fg: #fff;
  --pad: 12px; --gap: 12px;
  --bar-h: 16px; --btn-h: 23px; --btn-w: 75px;
  --notice-fg: #000;
}
[data-os="win31"] .screen  { background: #c0c0c0; }
[data-os="win31"] .notice  { line-height: 15px; }

/* The frame IS the padding: 1px black, then 4px of #000080 with the top edge
   a row short, exactly as 3.0 has it. */
[data-os="win31"] .dialog {
  border: 1px solid #000;
  padding: 3px 4px 4px;
  background: #000080;
}

/* .titlebar and .content each carry the half of the white ring that touches
   them; together they close it around the client. 20px = 1 white + 18 caption
   + 1 black rule.

   The rule is an inset shadow rather than a bottom border, for the reason
   given in the 3.0 block: a white left border meeting a black bottom border
   is a corner CSS mitres diagonally, and at 1px that comes out mid grey. An
   inset shadow is clipped to the padding box, so it lands on the same row
   already inset by the white columns and stays hard. */
[data-os="win31"] .titlebar {
  padding: 0;
  border: 1px solid #fff;
  border-bottom: 0;
  box-shadow: inset 0 -1px #000;
  background: #000080;
}
[data-os="win31"] .tb-l  { align-self: flex-start; gap: 0; }
[data-os="win31"] .tb-c  { justify-content: center; }
[data-os="win31"] .title  { font-weight: bold; }
[data-os="win31"] .content {
  background: #fff;
  border: 1px solid #fff;
  border-top: 0;
}

/* Same object as 3.0's, down to the pixel: an 18px square of the face grey
   carrying a 13x3 black slab hollowed white along its middle row, with a 1px
   #808080 shadow one pixel down and right of it. No bevel of its own — the
   caption's white ring is its top and left, the black rule its bottom, and
   the border-right below its right. Box-relative: black x2-14 y7-9, white
   x3-13 y8, shadow x15 y8-9 and x3-15 y10.

   A modal dialog has no minimise or maximise, so neither is drawn. */
[data-os="win31"] .w-close {
  display: block; flex: none;
  width: 19px; height: 18px;
  border-right: 1px solid #000;
  background: #c0c0c0 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' shape-rendering='crispEdges'%3E%3Cpath d='M2 7h13v3H2z'/%3E%3Cpath fill='%23ffffff' d='M3 8h11v1H3z'/%3E%3Cpath fill='%23808080' d='M15 8h1v2h-1zM3 10h13v1H3z'/%3E%3C/svg%3E") no-repeat 0 0;
}
[data-os="win31"] .w-a,
[data-os="win31"] .w-b  { display: none; }

/* The body is white, so the well takes the button grey — a white-on-white
   sunken box would have nothing to show for its bottom and right edges. */
[data-os="win31"] .track {
  height: 16px; padding: 1px; background: #c0c0c0;
  box-shadow: inset 1px 1px #808080, inset -1px -1px #fff;
}
[data-os="win31"] .fill  { background: #000080; }
[data-os="win31"] .btn  {                 /* grey, even though the body is white */
  background: #c0c0c0;
  box-shadow: inset -1px -1px #000, inset 1px 1px #fff, inset -2px -2px #808080;
}
[data-os="win31"] .btn:active {
  box-shadow: inset 1px 1px #808080, inset 2px 2px #c0c0c0;
  padding-top: 2px; padding-left: 2px;
}

/* ====================== SKIN — Windows 1.01 (1985) ======================
   Rebuilt from three 4x captures — the End Session window, the Run box and
   the MS-DOS Executive about box — every one an exact integer scale, so each
   value below is a real pixel and not a reading. Three colours in all three
   files and nothing else: #000000, #ffffff, #5555ff.

   1.0 draws two different things and this dialog is a mix of both, because
   the page needs a caption and 1.0's message boxes do not have one:

     the frame   from Run and the about box — 1px black, 1px white, 2px blue,
                 on all four sides
     the caption from End Session — a 1px black rule, 14 rows of solid blue,
                 another 1px black rule, with the title in a black block that
                 runs the full height of the band and is centred on the whole
                 bar. (The earlier pass had this band as an 8x8 blue/black
                 dither, read off a 640x350 EGA capture; these files show it
                 solid, and they are the reference now.)

   Buttons are the measured shape, cap by cap: 62x19 with a 1px outline and a
   four-row rounded end, which is what Cancel wears in both End Session and
   Run. The default button is the same shape drawn 64x21 with a 2px outline —
   Run's Ok and the about box's lone Ok are both that — so it is what focus
   gets here. The two sit in the same 64x21 box so nothing shifts when the
   ring appears. The caps are inline SVG at crispEdges rather than a
   border-radius, which would antialias its corners at every zoom.

   1.0 had no progress control at all, so the bar is invented — but its parts
   are 1.0's: the Run box's text field, 1px black on white, filled with the
   red the Clock's scroll bars are painted in.

   Desktop is 1.0's icon-area dither, measured at the foot of toastytech's
   executive capture: a 2x2 of green with cyan in one corner, three parts to
   one, normalised to this palette.

   One deliberate departure: 640x350 EGA pixels were about 1.37x taller than
   wide on a 4:3 monitor. This renders them square, as every other skin here
   renders its native pixels square, so the dialog is a little squatter than
   it was on glass.                                                        */

[data-os="win1"] {
  --font: "Win1System", monospace;
  --fsize: 12px; --lh: 12px;
  --dlg-w: 320px;
  --face: #fff; --text: #000;
  --title-h: 15px; --title-fg: #fff;
  --pad: 12px; --gap: 14px;
  --bar-h: 18px; --btn-h: 21px; --btn-w: 64px;
  --notice-fg: #000; --notice-fsize: 12px;
}

/* The icon-area dither. Sized in viewport space off --dither so it keeps its
   2px cell when the stage is zoomed. */
[data-os="win1"] .screen {
  background-color: #55ff55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2'%3E%3Cpath fill='%2355ffff' d='M0 0h1v1H0z'/%3E%3C/svg%3E");
  background-size: var(--dither) var(--dither);
}

/* The caption is the Clock window's whole top bar: it runs from black border
   to black border, so the frame does not start until below it. Everywhere
   else the frame is Run's, outside in — 1px black border, a 1px white ring
   just inside it, then 2px of blue, which is what the padding is filled
   with. The three white lines are inset shadows and the caption is opaque,
   so bleeding it across the padding covers the two that would otherwise run
   up beside it. */
[data-os="win1"] .dialog {
  border: 1px solid #000;
  padding: 0 3px 3px;
  background: #5555ff;
  box-shadow: inset 1px 0 0 #fff, inset -1px 0 0 #fff, inset 0 -1px 0 #fff;
}

/* 15px = 14 rows of blue + the 1px rule under them; the rule above is the
   dialog's own border. */
[data-os="win1"] .titlebar {
  margin: 0 -3px;
  padding: 0;
  border-bottom: 1px solid #000;
  background: #5555ff;
}
[data-os="win1"] .tb-l,
[data-os="win1"] .tb-r { align-items: stretch; align-self: stretch; gap: 0; }
[data-os="win1"] .tb-c { justify-content: center; align-items: stretch; align-self: stretch; }

/* The system-menu box and the size box, off the COMMAND window's caption.
   Both are 13px of white against the blue with a 1px black rule between them
   and the band, and they are the same overall width — which is what keeps the
   title centred on the whole bar rather than on the space left between them. */
[data-os="win1"] .w-close {
  display: block; flex: none; width: 14px; align-self: stretch;
  border-right: 1px solid #000;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='14' shape-rendering='crispEdges'%3E%3Cpath d='M2 2h9v2H2zM2 6h9v2H2zM2 10h9v2H2z'/%3E%3C/svg%3E") 0 0 / 13px 14px no-repeat;
}
[data-os="win1"] .w-b {
  display: block; flex: none; width: 14px; align-self: stretch;
  border-left: 1px solid #000;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='14' shape-rendering='crispEdges'%3E%3Cpath d='M0 6h8v2H0zM5 8h3v6H5z'/%3E%3C/svg%3E") 100% 0 / 13px 14px no-repeat;
}
/* The block runs the full 14 rows; the glyphs sit one row down from its top,
   which is where the capture puts them. */
[data-os="win1"] .title {
  background: #000;
  padding: 1px 1px 0;
  line-height: 12px;
}

[data-os="win1"] .content { background: #fff; }

/* Run's text field, doing duty as a progress trough, filled in the red the
   Clock window's scroll bars use — the one colour 1.0 puts inside a control
   rather than around one. */
[data-os="win1"] .track {
  height: 18px; padding: 1px;
  border: 1px solid #000; background: #fff;
}
[data-os="win1"] .fill { background: #ff5555; }

/* 62x19 drawn inside a 64x21 box, so the default ring can appear around it
   without moving anything. */
[data-os="win1"] .btn {
  height: 21px;
  /* The label sits high in the button: three rows under the top edge and six
     over the bottom, measured off the 4x Cancel. */
  padding: 0 6px;
  border: 0;
  border-radius: 0;
  line-height: 12px;
  background:
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='19'%20shape-rendering='crispEdges'><path%20fill='%23fff'%20d='M4%201h8v1H4M2%202h10v1H2M2%203h10v1H2M1%204h11v1H1M1%205h11v1H1M1%206h11v1H1M1%207h11v1H1M1%208h11v1H1M1%209h11v1H1M1%2010h11v1H1M1%2011h11v1H1M1%2012h11v1H1M1%2013h11v1H1M1%2014h11v1H1M2%2015h10v1H2M2%2016h10v1H2M4%2017h8v1H4'/><path%20d='M4%200h8v1H4M2%201h2v1H2M1%202h1v1H1M1%203h1v1H1M0%204h1v1H0M0%205h1v1H0M0%206h1v1H0M0%207h1v1H0M0%208h1v1H0M0%209h1v1H0M0%2010h1v1H0M0%2011h1v1H0M0%2012h1v1H0M0%2013h1v1H0M0%2014h1v1H0M1%2015h1v1H1M1%2016h1v1H1M2%2017h2v1H2M4%2018h8v1H4'/></svg>") 1px 1px / 12px 19px no-repeat,
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='19'%20shape-rendering='crispEdges'><path%20fill='%23fff'%20d='M0%201h8v1H0M0%202h10v1H0M0%203h10v1H0M0%204h11v1H0M0%205h11v1H0M0%206h11v1H0M0%207h11v1H0M0%208h11v1H0M0%209h11v1H0M0%2010h11v1H0M0%2011h11v1H0M0%2012h11v1H0M0%2013h11v1H0M0%2014h11v1H0M0%2015h10v1H0M0%2016h10v1H0M0%2017h8v1H0'/><path%20d='M0%200h8v1H0M8%201h2v1H8M10%202h1v1H10M10%203h1v1H10M11%204h1v1H11M11%205h1v1H11M11%206h1v1H11M11%207h1v1H11M11%208h1v1H11M11%209h1v1H11M11%2010h1v1H11M11%2011h1v1H11M11%2012h1v1H11M11%2013h1v1H11M11%2014h1v1H11M10%2015h1v1H10M10%2016h1v1H10M8%2017h2v1H8M0%2018h8v1H0'/></svg>") right 1px top 1px / 12px 19px no-repeat,
    linear-gradient(180deg, #000 0 1px, #fff 1px 18px, #000 18px 19px)
      13px 1px / calc(100% - 26px) 19px no-repeat;
}

/* The default button, filling the whole 64x21. */
[data-os="win1"] .btn:focus-visible {
  outline: 0;
  background:
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='21'%20shape-rendering='crispEdges'><path%20fill='%23fff'%20d='M5%202h7v1H5M3%203h9v1H3M3%204h9v1H3M2%205h10v1H2M2%206h10v1H2M2%207h10v1H2M2%208h10v1H2M2%209h10v1H2M2%2010h10v1H2M2%2011h10v1H2M2%2012h10v1H2M2%2013h10v1H2M2%2014h10v1H2M2%2015h10v1H2M3%2016h9v1H3M3%2017h9v1H3M5%2018h7v1H5'/><path%20d='M5%200h7v1H5M3%201h9v1H3M2%202h3v1H2M1%203h2v1H1M1%204h2v1H1M0%205h2v1H0M0%206h2v1H0M0%207h2v1H0M0%208h2v1H0M0%209h2v1H0M0%2010h2v1H0M0%2011h2v1H0M0%2012h2v1H0M0%2013h2v1H0M0%2014h2v1H0M0%2015h2v1H0M1%2016h2v1H1M1%2017h2v1H1M2%2018h3v1H2M3%2019h9v1H3M5%2020h7v1H5'/></svg>") 0 0 / 12px 21px no-repeat,
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='21'%20shape-rendering='crispEdges'><path%20fill='%23fff'%20d='M0%202h7v1H0M0%203h9v1H0M0%204h9v1H0M0%205h10v1H0M0%206h10v1H0M0%207h10v1H0M0%208h10v1H0M0%209h10v1H0M0%2010h10v1H0M0%2011h10v1H0M0%2012h10v1H0M0%2013h10v1H0M0%2014h10v1H0M0%2015h10v1H0M0%2016h9v1H0M0%2017h9v1H0M0%2018h7v1H0'/><path%20d='M0%200h7v1H0M0%201h9v1H0M7%202h3v1H7M9%203h2v1H9M9%204h2v1H9M10%205h2v1H10M10%206h2v1H10M10%207h2v1H10M10%208h2v1H10M10%209h2v1H10M10%2010h2v1H10M10%2011h2v1H10M10%2012h2v1H10M10%2013h2v1H10M10%2014h2v1H10M10%2015h2v1H10M9%2016h2v1H9M9%2017h2v1H9M7%2018h3v1H7M0%2019h9v1H0M0%2020h7v1H0'/></svg>") right top / 12px 21px no-repeat,
    linear-gradient(180deg, #000 0 2px, #fff 2px 19px, #000 19px 21px)
      12px 0 / calc(100% - 24px) 21px no-repeat;
}

[data-os="win1"] .btn:active {
  color: #fff;
  background:
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='19'%20shape-rendering='crispEdges'><path%20d='M4%200h8v1H4M2%201h10v1H2M1%202h11v1H1M1%203h11v1H1M0%204h12v1H0M0%205h12v1H0M0%206h12v1H0M0%207h12v1H0M0%208h12v1H0M0%209h12v1H0M0%2010h12v1H0M0%2011h12v1H0M0%2012h12v1H0M0%2013h12v1H0M0%2014h12v1H0M1%2015h11v1H1M1%2016h11v1H1M2%2017h10v1H2M4%2018h8v1H4'/></svg>") 1px 1px / 12px 19px no-repeat,
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='19'%20shape-rendering='crispEdges'><path%20d='M0%200h8v1H0M0%201h10v1H0M0%202h11v1H0M0%203h11v1H0M0%204h12v1H0M0%205h12v1H0M0%206h12v1H0M0%207h12v1H0M0%208h12v1H0M0%209h12v1H0M0%2010h12v1H0M0%2011h12v1H0M0%2012h12v1H0M0%2013h12v1H0M0%2014h12v1H0M0%2015h11v1H0M0%2016h11v1H0M0%2017h10v1H0M0%2018h8v1H0'/></svg>") right 1px top 1px / 12px 19px no-repeat,
    linear-gradient(180deg, #000 0 19px)
      13px 1px / calc(100% - 26px) 19px no-repeat;
}


/* ======================= SKIN — Windows 3.0 (1990) ======================
   Measured from toastytech's native 640x480 VGA captures — win30exit.png for
   the frame and caption, win30progman / win30fileman / win30help for the
   palette. Those three agree exactly, so the colours below are theirs.
   (win30exit.png's own PNG is encoded a shade off — #c6c6ce where the other
   three say #c0c4c8 — so geometry comes from it and colour does not.)

   PALETTE, second pass. The toastytech PNGs read #c0c4c8 / #5454a8 / #54a8a8,
   and three of them agreed, so those stood here for a while. They are wrong:
   none of the three is in the 16-colour VGA palette a 3.0 machine actually
   had, and Hami's 8x capture of the Search dialog contains six colours and
   nothing else — #000000, #000080, #008080, #808080, #c0c0c0, #ffffff, every
   one of them a hardware palette entry. The earlier captures were shifted
   somewhere in encoding. The canonical six are what is used below.

   What still separates 3.0 from 3.1 is the dither: at 16 colours the active
   caption and the modal frame are a 2x2 checker of #000080 and #008080, where
   3.1 paints solid #000080.

   Frame, outside in: 1px black, then 4px of that dither (3px on the top edge,
   as measured), then a 1px white highlight ring around the whole client, an
   18px caption carrying the same dither with an 18px system-menu box hard
   against its left, and a 1px black rule under the caption. Hami's capture
   agrees with all of that row for row.

   3.0 shipped no progress control, so as with 3.1 this is Setup's own sunken
   box rather than a control that existed.                                 */

[data-os="win30"] {
  --font: "MS Sans Serif", Arial, sans-serif;
  /* px, not a ratio: 11 x 1.4 is 15.4, which makes .stage a fraction of a
     pixel tall and puts the centred dialog on a half pixel. */
  --fsize: 11px; --lh: 15px;
  --dlg-w: 320px;
  --face: #c0c0c0; --text: #000;
  --title-h: 20px; --title-fg: #ffffff;
  --pad: 12px; --gap: 12px;
  --bar-h: 16px; --btn-h: 23px; --btn-w: 75px;
  --notice-fg: #ffffff;
}
[data-os="win30"] .screen  { background: #008080; }
[data-os="win30"] .notice  { line-height: 15px; }

/* The dither lives on .dialog, so the padding IS the modal frame. */
[data-os="win30"] .dialog {
  border: 1px solid #000;
  padding: 3px 4px 4px;
  background: repeating-conic-gradient(#000080 0 25%, #008080 0 50%) 0 0 / 2px 2px;
}

/* .titlebar and .content each carry the half of the white ring that touches
   them; together they close it around the client. 20px = 1 white + 18 caption
   + 1 black rule. */
/* The rule under the caption is an inset shadow rather than a bottom border.
   A white left border meeting a black bottom border is a corner CSS mitres
   diagonally, and on a 1px border that diagonal lands inside a single pixel
   and comes out mid grey — the capture has white there and no grey anywhere.
   An inset shadow is clipped to the padding box, so it lands on the same row
   the mitred border would have, already inset by the white columns, and stays
   hard. .w-close is then sized rather than stretched so the rule runs under
   the system-menu box too, as it does in the capture. */
[data-os="win30"] .titlebar {
  padding: 0;
  border: 1px solid #ffffff;
  border-bottom: 0;
  box-shadow: inset 0 -1px #000;
  background: repeating-conic-gradient(#000080 0 25%, #008080 0 50%) 0 0 / 2px 2px;
}
[data-os="win30"] .tb-l  { align-self: flex-start; gap: 0; }
[data-os="win30"] .tb-c  { justify-content: center; }
[data-os="win30"] .title  { font-weight: bold; }

/* System-menu box: an 18px square of the FACE grey — not the shadow grey, as
   this had it — carrying the minimise slab. The slab is a 13x3 black rectangle
   hollowed to white along its middle row, with a 1px #808080 shadow one pixel
   down and right of it. It needs no highlight or shadow of its own: the
   caption's white ring supplies its top and left, the black rule under the
   caption its bottom, and the border-right below its right.

   Read off Hami's 8x Search capture, box-relative: black x2-14 y7-9, white
   x3-13 y8, shadow x15 y8-9 and x3-15 y10. */
[data-os="win30"] .w-close {
  display: block; flex: none;
  width: 19px; height: 18px;
  border-right: 1px solid #000;
  background: #c0c0c0 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' shape-rendering='crispEdges'%3E%3Cpath d='M2 7h13v3H2z'/%3E%3Cpath fill='%23ffffff' d='M3 8h11v1H3z'/%3E%3Cpath fill='%23808080' d='M15 8h1v2h-1zM3 10h13v1H3z'/%3E%3C/svg%3E") no-repeat 0 0;
}

[data-os="win30"] .content {
  border: 1px solid #ffffff;
  border-top: 0;
  background: var(--face);
}

[data-os="win30"] .track {
  height: 16px; padding: 1px; background: #c0c0c0;
  box-shadow: inset 1px 1px #808080, inset -1px -1px #ffffff;
}
[data-os="win30"] .fill  { background: #000080; }

[data-os="win30"] .btn {
  background: #c0c0c0;
  box-shadow: inset -1px -1px #000, inset 1px 1px #ffffff, inset -2px -2px #808080;
}
[data-os="win30"] .btn:active {
  box-shadow: inset 1px 1px #808080, inset 2px 2px #c0c0c0;
  padding-top: 2px; padding-left: 2px;
}


/* ============== SKIN — Windows 95 (1995) + Windows 98 (1998) ============
   One rule set for both. 98 kept 95's chrome down to the pixel — four-tone
   bevels, left-aligned bold caption, the close button, and the chunked
   msctls_progress32 bar (12px of navy then a 2px gap, on a 14px pitch). Every
   selector below is written out for both slugs so the two cannot drift, and
   so no descendant selector can be silently rewritten by pairing them.

   Two things differ, both at the foot of this block:
     - the caption fill: 95 paints solid #000080, 98 shipped with the gradient
       enabled by default, #000080 running to #1084d0
     - nothing else

   Backdrop: the default desktop in both is exactly #008080, measured off
   win95desktop.png — and at full screen it shouts. What is here instead is
   the Windows 95 startup screen's own sky, row-averaged across the 640x400
   win95boot.png: #b9d7e7 at the top falling to #8da4bf. Still Windows 95's
   own colour, still the screen you actually stared at while it installed,
   but it lets the dialog sit on top of it rather than fight it. The notice
   goes black on it, as it already is on 3.1's grey desktop.

   Caption geometry measured from toastytech's 640x480 win98shut.png (18px
   caption, frame identical to 95's). That capture has gradient captions
   turned OFF, so 98's two gradient stops are Microsoft's documented defaults
   rather than pixels read out of it — the one reconstructed value here.   */

[data-os="win95"],
[data-os="win98"] {
  --font: "MS Sans Serif", Arial, sans-serif;
  --fsize: 11px; --lh: 1.4;
  --dlg-w: 330px;
  --face: #c0c0c0; --text: #000;
  --title-h: 18px; --title-bg: #000080; --title-fg: #fff;
  --pad: 10px; --gap: 12px;
  --bar-h: 16px; --btn-h: 23px; --btn-w: 75px;
  --notice-fg: #000;
  --chunk: 14px;               /* read by app.js so the fill snaps to whole chunks */
}

[data-os="win95"] .screen,
[data-os="win98"] .screen {
  background: linear-gradient(180deg, #b9d7e7 0%, #8da4bf 100%);
}

[data-os="win95"] .dialog,
[data-os="win98"] .dialog {
  padding: 3px;
  box-shadow: inset -1px -1px #0a0a0a, inset 1px 1px #dfdfdf,
              inset -2px -2px #808080, inset 2px 2px #fff;
}
[data-os="win95"] .titlebar,
[data-os="win98"] .titlebar  { padding: 0 2px 0 3px; }

[data-os="win95"] .title,
[data-os="win98"] .title  { font-weight: bold; }

[data-os="win95"] .w-b,
[data-os="win98"] .w-b {
  display: block; width: 16px; height: 14px; background: #c0c0c0;
  box-shadow: inset -1px -1px #0a0a0a, inset 1px 1px #fff,
              inset -2px -2px #808080, inset 2px 2px #dfdfdf;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='7'%3E%3Cpath d='M0 0h2v1H0zM5 0h2v1H5zM1 1h2v1H1zM4 1h2v1H4zM2 2h3v1H2zM3 3h1v1H3zM2 4h3v1H2zM1 5h2v1H1zM4 5h2v1H4zM0 6h2v1H0zM5 6h2v1H5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 4px 3px;
}
[data-os="win95"] .w-b:active,
[data-os="win98"] .w-b:active {
  box-shadow: inset 1px 1px #0a0a0a, inset -1px -1px #fff,
              inset 2px 2px #808080, inset -2px -2px #dfdfdf;
  background-position: 5px 4px;
}

[data-os="win95"] .track,
[data-os="win98"] .track {
  height: 16px; padding: 1px; background: #c0c0c0;
  box-shadow: inset 1px 1px #808080, inset -1px -1px #dfdfdf;
}
[data-os="win95"] .fill,
[data-os="win98"] .fill {
  background-image: linear-gradient(90deg, #000080 0 12px, transparent 12px);
  background-size: 14px 100%; background-repeat: repeat-x;
}

[data-os="win95"] .btn,
[data-os="win98"] .btn {
  box-shadow: inset -1px -1px #0a0a0a, inset 1px 1px #fff,
              inset -2px -2px #808080, inset 2px 2px #dfdfdf;
}
[data-os="win95"] .btn:active,
[data-os="win98"] .btn:active {
  box-shadow: inset 1px 1px #0a0a0a, inset -1px -1px #fff,
              inset 2px 2px #808080, inset -2px -2px #dfdfdf;
  padding-top: 2px; padding-left: 2px;
}

/* The only thing 98 changed. */
[data-os="win98"] .titlebar {
  background-image: linear-gradient(90deg, #000080 0%, #1084d0 100%);
}


/* ======================= SKIN — Windows XP (2001) =======================
   Luna, re-measured from Hami's 4x capture of the Run dialog — a clean integer
   scale, so native pixels were recovered rather than estimated, and most of
   this block's earlier guesses moved.

   CAPTION is 29 rows, not 27, and its gradient is inlined ROW BY ROW below:
   twenty stops in px, each one the colour actually sampled at that row. It is
   not a smooth ramp — there is a bright #3f97ff flare in rows 1-4, a flat
   #0054e3 plateau through the middle, then it brightens again to #026afe at
   rows 21-24 before dropping off sharply over the last two.

   FRAME is 3px and asymmetric, which the earlier single horizontal gradient
   could not express: #0734da / #166aee / #0855dd down the left, and
   #00138c / #001ea1 / #003edc up the right and bottom, outermost first. Two
   background layers, the bottom band painted over the sides.

   BUTTON measured on Cancel, native y144-164, so 21px rather than 23: a 1px
   #003c74 outline at 3px radius over a fill that runs #ffffff at the top to
   #f0f0eb at about 84%, then falls away through #ecebe6 and #e0ded4 to
   #d6d0c5 in the last two rows.

   Body is #ece9d8. The segmented green bar is unchanged — the Run dialog has
   no progress control to measure it against.                             */

[data-os="winxp"] {
  --font: Tahoma, "Tahoma Alt", Verdana, sans-serif;
  --fsize: 11px; --lh: 1.5;
  --dlg-w: 360px;
  --face: #ece9d8; --text: #000;
  --title-h: 29px; --title-fg: #fff;
  --pad: 12px; --gap: 12px;
  --bar-h: 14px; --btn-h: 21px; --btn-w: 75px;
  --notice-fg: #fff;
  --chunk: 10px;
}
/* Flat #004E98 — the documented Luna desktop colour, which is what XP shows
   behind the wallpaper and what the desktop is with Bliss removed. The earlier
   backdrop here was an invented sky-over-hill gradient standing in for the
   photograph; a colour XP actually used beats an impression of one it did. */
[data-os="winxp"] .screen  { background: #004e98; }
[data-os="winxp"] .stage  { -webkit-font-smoothing: antialiased; }
[data-os="winxp"] .dialog {
  border-radius: 6px 6px 0 0;
  padding: 0 3px 3px;
  background-image:
    linear-gradient(180deg, transparent 0 calc(100% - 3px),
      #0048f1 calc(100% - 3px) calc(100% - 2px),
      #001ea1 calc(100% - 2px) calc(100% - 1px),
      #00138c calc(100% - 1px) 100%),
    linear-gradient(90deg,
      #0734da 0 1px, #166aee 1px 2px, #0855dd 2px calc(100% - 3px),
      #003edc calc(100% - 3px) calc(100% - 2px),
      #001ea1 calc(100% - 2px) calc(100% - 1px),
      #00138c calc(100% - 1px) 100%);
  box-shadow: 0 10px 28px rgba(0,0,0,.45);
}
/* The caption is NOT the gradient edge to edge. Luna carries the window frame
   up through it: three columns down each side, dark navy, which is why the
   sides read as one continuous edge from the rounded corner to the bottom of
   the window. Painting the caption ramp all the way out instead left the frame
   apparently starting below the caption — a step where the two met, which is
   the seam Hami spotted.

   So six 1px columns, lifted row by row off the 8x Run capture and merged into
   runs wherever consecutive rows agreed within 8 — a handful of stops each
   rather than 29, with no measured row more than 8 off its own value. Left and
   right are NOT mirrors: the frame is lit from the top left, so the right side
   is markedly darker, exactly as the body's frame below it is. The bottom rows
   of every column hold their colour while the caption ramp falls away beneath
   them, and that is what actually closes the join.

   The top five rows sit inside the 6px corner cut and are clipped away by the
   radius, so they simply carry row 5's colour. */
[data-os="winxp"] .titlebar {
  margin: 0 -3px; padding: 0 5px 0 6px;
  border-radius: 6px 6px 0 0;
  font-family: "Trebuchet MS", Tahoma, "Tahoma Alt", sans-serif;
  font-weight: bold; font-size: 13px;
  text-shadow: 1px 1px #0f1089;
  /* One stop per measured row of the 29. */
  background:
    linear-gradient(180deg, #0032c1 0 7px, #001ca9 7px 10px, #0018ab 10px 11px,
      #001abc 11px 15px, #0021d0 15px 21px, #001bcf 21px 29px)
      left top / 1px 100% no-repeat,
    linear-gradient(180deg, #004adc 0 6px, #0033c4 6px 12px, #0038d6 12px 18px,
      #003be1 18px 29px)
      left 1px top / 1px 100% no-repeat,
    linear-gradient(180deg, #004bcd 0 6px, #003ecd 6px 12px, #0043e1 12px 19px,
      #004aea 19px 27px, #003be0 27px 29px)
      left 2px top / 1px 100% no-repeat,
    linear-gradient(180deg, #0032c1 0 6px, #0025b8 6px 9px, #0023ca 9px 16px,
      #002ada 16px 19px, #0038e9 19px 28px, #002edc 28px 29px)
      right 2px top / 1px 100% no-repeat,
    linear-gradient(180deg, #0032c1 0 6px, #0025a9 6px 14px, #0029b3 14px 17px,
      #002dba 17px 20px, #0031c2 20px 29px)
      right 1px top / 1px 100% no-repeat,
    linear-gradient(180deg, #0015a0 0 7px, #000e7d 7px 15px, #00148e 15px 29px)
      right top / 1px 100% no-repeat,
    linear-gradient(180deg,
    #0058ee 0 1px,  #3f97ff 1px 2px,  #2b90ff 2px 3px,  #0372ff 3px 4px,
    #0365f1 4px 5px, #005ce9 5px 6px, #0058e6 6px 7px,  #0054e3 7px 10px,
    #0055e5 10px 14px, #0055ea 14px 16px, #0058ee 16px 17px,
    #005bf2 17px 18px, #005af5 18px 19px, #0060f9 19px 20px,
    #0164f9 20px 21px, #026afe 21px 25px, #0065fd 25px 26px,
    #0060fc 26px 27px, #004de3 27px 28px, #0043cf 28px 29px);
}
[data-os="winxp"] .content  { background: #ece9d8; }
[data-os="winxp"] .w-b {
  display: grid; place-items: center; width: 21px; height: 21px;
  border-radius: 3px;
  background: linear-gradient(180deg, #f4a79c 0%, #e05a45 38%, #c4301c 56%, #ec8672 100%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.6);
}
[data-os="winxp"] .w-b::before {
  content: ""; width: 11px; height: 11px;
  background:
    linear-gradient(45deg,  transparent 42%, #fff 42% 58%, transparent 58%),
    linear-gradient(-45deg, transparent 42%, #fff 42% 58%, transparent 58%);
}
[data-os="winxp"] .w-b:active  { filter: brightness(.88); }
[data-os="winxp"] .track {
  height: 14px; border: 1px solid #686868; border-radius: 4px;
  background: #fff; padding: 1px 2px 1px 0;
  box-shadow: inset 0 0 1px 0 #686868;
}
[data-os="winxp"] .fill {
  border-radius: 2px;
  background-image:
    repeating-linear-gradient(to right, transparent 0 8px, #fff 8px 10px),
    linear-gradient(to bottom, #acedad 0%, #7be47d 14%, #4cda50 28%, #2ed330 42%,
                               #42d845 57%, #76e275 71%, #8fe791 85%, #fff 100%);
}
[data-os="winxp"] .btn {
  border: 1px solid #003c74;
  border-radius: 3px;
  color: #000;
  background: linear-gradient(180deg,
    #ffffff 0%, #f6f6f4 32%, #f0f0eb 84%, #ecebe6 89%,
    #e0ded4 95%, #d6d0c5 100%);
}
[data-os="winxp"] .btn:active {
  background: linear-gradient(180deg,
    #d6d0c5 0%, #e0ded4 6%, #ecebe6 12%, #f0f0eb 20%, #f6f6f4 70%, #ffffff 100%);
}
[data-os="winxp"] .notice  { text-shadow: 0 1px 2px rgba(0,0,0,.6); }


/* ================= SKIN — BeOS Release 3 (1998) =========================
   Measured from Hami's PCem captures: the panel, the frame and the progress
   bar off a clean 4x of the Scroll Bar preferences window — every column pair
   and row pair identical, so native pixels were recovered exactly rather than
   eyeballed — and the tab off five 8x captures of window title tabs, all five
   of which came back at purity 1.000 and agree on every number below.

   Palette: desktop #336698, panel #d8d8d8, tab #ffcb00, and the frame greys
   #989898 / #888888 / #606060 with #ffffff and #efefef as highlights. There
   is no black anywhere in BeOS chrome, which the documentation does not say
   and a reconstruction from it gets wrong.

   WINDOW FRAME is a 2px bevel, and it is asymmetric:
     top + left     1px #989898 then 1px #ffffff
     bottom + right 1px #606060 then 1px #888888
   Measured at x0-2 and at the last two columns and rows of the panel.

   TAB, 20 rows, stops at the title — a tab, not a bar, which is the whole
   silhouette of a BeOS window. It has its own bevel:
     top + left  1px #989898 then 1px #ffff50   (a much lighter yellow)
     right       1px #af7b00 then 1px #606060
   Yellow means active; the inactive windows in the same captures wear grey.

   CLOSE BOX, 14x14 at the tab's left, is inlined below pixel for pixel. It is
   a square engraved into the tab — #b78200 outside, #ffff3f inside — holding a
   dithered diagonal that runs #ffec21 at the top left through #ffcb00 to
   #eab500 at the bottom right. Five colours, none of them guessable, which is
   why it is a run-length SVG rather than a border and a gradient.

   PROGRESS BAR, from the Tracker Status window copying screen23.tga:
     trough   1px #b8b8b8 then 1px #606060, sunk
     fill     #3296ff, 1px #86c1ff along its top, 1px #1d5897 along its bottom
     interior 9 rows, 11px overall
   BStatusBar's documented default fill is rgb(50,150,255) — #3296ff — so the
   reconstruction had that one colour right and everything around it wrong.

   BUTTON, "Defaults" at native x16-91, y267-289, so 23px tall: a #606060 ring,
   then #efefef and two rows of #ffffff coming down the top and left, and
   #989898 then #d8d8d8 going up the bottom and right, over a #e8e8e8 face —
   note the face is NOT the panel grey.

   FONT is a stand-in and has to be — the captures prove the titles are
   anti-aliased outline text rather than a strike, so there is nothing to
   harvest. Which face, and why FreeSans at 12px rather than the Liberation
   this skin used to use, is measured in css/style.css.                    */

[data-os="beos3"] {
  /* Two faces, because R3 uses two: the tab title is cap 9 and bold and stays
     on the outline face, everything else is the cap-7 strike lifted off the
     Installer. The strike sits 1:1 at 10px and nowhere else. */
  --font: "BeSwiss", "Swis721Alt", Helvetica, Arial, sans-serif;
  --fsize: 10px; --lh: 13px;
  --title-fsize: 12px;
  --dlg-w: 340px;
  --face: #d8d8d8; --text: #000;
  --title-h: 20px; --title-fg: #000;
  /* 18 + the 1px border puts the text 19px in from the window's edge, which is
     where the Installer capture has it, and leaves the 13px of clear between
     the groove and the work area that the same capture measures. */
  --pad: 18px; --gap: 14px;
  --bar-h: 11px; --btn-h: 23px; --btn-w: 84px;
  --notice-fg: #fff;
}
[data-os="beos3"] .screen  { background: #336698; }

/* R3's UI face keeps its anti-aliasing, and it keeps it as GEOMETRY: a pixel
   the capture covers four tenths of is a rectangle four tenths of the way
   across its cell, which the browser then rasterises to that grey in whatever
   colour the text is, over whatever is behind it. A hinter would undo all of
   that — it snaps edges to the pixel grid, which is exactly what those
   rectangles are not doing — so hinting is turned off wherever that face is
   used. Measured on the six lines the captures give in full, this takes the
   worst error on any pixel from five tenths to one. The tab title is an
   ordinary outline face and is left alone. */
[data-os="beos3"] .dialog,
[data-os="beos3"] .notice { text-rendering: geometricPrecision; }
[data-os="beos3"] .title  { text-rendering: auto; }

/* No background on .dialog: the tab has to meet the desktop, not a full-width
   strip of panel grey. */
[data-os="beos3"] .dialog  { background: none; }

[data-os="beos3"] .titlebar {
  /* The tab IS this element: inline-flex so it shrinks to its title instead of
     running the width of the window, which is the whole BeOS silhouette.
     Measured on the Applications tab, native rows 9-28 — 20 rows, a #989898
     edge on the top and left, #ffff50 just inside it, and #af7b00 then #606060
     closing the right end. No bottom edge: it merges into the panel, which is
     what margin-bottom does. */
  display: flex;
  width: fit-content;              /* shrink-wrap without the inline baseline
                                      gap that inline-flex leaves underneath */
  height: 20px;
  /* Two columns of yellow clear before the close box — the same two the tab
     leaves above it and below it — sitting inside the 1px edge and the 1px
     highlight, which is why this is 3 and not 2. The right side has no clear
     of its own: the title's own margin runs up to the #af7b00 the inset shadow
     paints on the last column but one. */
  padding: 0 1px 0 3px;
  background: #ffcb00;
  color: #000;
  border: 1px solid #989898;
  border-bottom: 0;
  border-right-color: #606060;
  box-shadow: inset 1px 1px 0 #ffff50, inset -1px 0 0 #af7b00;
  margin-bottom: -1px;
  overflow: visible;
  position: relative; z-index: 1;
}
/* A BeOS tab carries a close box and nothing else — the zoom box belongs to
   windows that can be zoomed, and an alert cannot be. Measured across five
   tabs, the title starts at column 37 in every one of them whatever it says,
   because the tab is sized to fit: 2 for the edge and the highlight, 2 of
   clear, the 14px box, 2 more of clear, then the title's own 17px margin. It
   keeps 16 on the far side, which is the same margin rounded the other way —
   BeOS centres the title in what the box leaves and lands half a pixel left. */
[data-os="beos3"] .tb-l  { flex: none; width: 16px; gap: 0; }
[data-os="beos3"] .tb-r  { display: none; }
[data-os="beos3"] .tb-c  { flex: 0 1 auto; justify-content: center; padding: 0 15px 0 16px; }
/* The baseline lands on the tab's 14th row, three above the close box's last —
   the box is deep enough to hold the descenders, not the baseline. */
[data-os="beos3"] .title  {
  font-family: "Swis721Alt", Helvetica, Arial, sans-serif;
  font-weight: bold; position: relative; top: 1px;
}

/* 14x14, engraved into the tab, 2px of yellow clear on every side. Inlined
   pixel for pixel — five colours, none of them derivable from the others. */
[data-os="beos3"] .w-close {
  display: block; flex: none;
  width: 14px; height: 14px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' shape-rendering='crispEdges'%3E%3Cpath fill='%23b78200' d='M0 0h13v1H0zM0 1h1v1H0zM0 2h1v1H0zM12 2h1v1H12zM0 3h1v1H0zM12 3h1v1H12zM0 4h1v1H0zM12 4h1v1H12zM0 5h1v1H0zM12 5h1v1H12zM0 6h1v1H0zM12 6h1v1H12zM0 7h1v1H0zM12 7h1v1H12zM0 8h1v1H0zM12 8h1v1H12zM0 9h1v1H0zM12 9h1v1H12zM0 10h1v1H0zM12 10h1v1H12zM0 11h1v1H0zM12 11h1v1H12zM0 12h1v1H0zM2 12h11v1H2zM0 13h1v1H0z'/%3E%3Cpath fill='%23b88200' d='M13 0h1v1H13z'/%3E%3Cpath fill='%23ffff3f' d='M1 1h13v1H1zM1 2h2v1H1zM4 2h1v1H4zM13 2h1v1H13zM1 3h1v1H1zM3 3h1v1H3zM13 3h1v1H13zM1 4h2v1H1zM13 4h1v1H13zM1 5h1v1H1zM13 5h1v1H13zM1 6h1v1H1zM13 6h1v1H13zM1 7h1v1H1zM13 7h1v1H13zM1 8h1v1H1zM13 8h1v1H13zM1 9h1v1H1zM13 9h1v1H13zM1 10h1v1H1zM13 10h1v1H13zM1 11h1v1H1zM13 11h1v1H13zM1 12h1v1H1zM13 12h1v1H13zM1 13h13v1H1z'/%3E%3Cpath fill='%23ffec21' d='M3 2h1v1H3zM5 2h6v1H5zM2 3h1v1H2zM4 3h4v1H4zM9 3h1v1H9zM11 3h1v1H11zM3 4h4v1H3zM8 4h1v1H8zM10 4h1v1H10zM2 5h4v1H2zM7 5h1v1H7zM2 6h3v1H2zM6 6h1v1H6zM2 7h2v1H2zM5 7h1v1H5zM2 8h1v1H2zM4 8h1v1H4zM2 9h2v1H2zM2 10h1v1H2zM4 10h1v1H4zM3 11h1v1H3z'/%3E%3Cpath fill='%23eab500' d='M11 6h1v1H11zM9 7h3v1H9zM8 8h1v1H8zM10 8h2v1H10zM7 9h1v1H7zM9 9h3v1H9zM7 10h5v1H7zM6 11h6v1H6z'/%3E%3C/svg%3E") 0 0 / 14px 14px;
}

/* 2px asymmetric frame: #989898 then #ffffff down the top and left, #606060
   then #888888 up the bottom and right. The tab sits on the top edge.

   Then a groove around the work area, off the R3.1 Installer window recovered
   at native 344x185. A pixel of panel clear inside the frame, then THREE 1px
   rectangles, which is what makes it read as cut into the panel rather than
   drawn on it:

       sunken   dark on the top and left, white on the bottom and right
       flat     the same grey all the way round
       raised   white on the top and left, dark on the bottom and right

   The capture's greys are a lighter set than this skin's — its panel is
   #e2e2e2 against #d8d8d8 and its frame runs #b2b2b2/#818181 against
   #989898/#606060 — so the three rings are taken by their ORDER in that
   capture's ladder (#cacaca > #b2b2b2 > #898989) rather than by value, which
   lands them on the three greys this skin already has between white and its
   own frame. Mixing one capture's palette into another's is how a skin ends up
   with two families of grey in it.

   Listed innermost first, because the earlier shadow paints over the later
   one, so each 1px band is what the one before it leaves uncovered. */
[data-os="beos3"] .content {
  background: #d8d8d8;
  border: 1px solid;
  border-color: #989898 #606060 #606060 #989898;
  box-shadow:
    inset  1px  1px 0 #fff,     inset -1px -1px 0 #888,      /* frame */
    inset  2px  2px 0 #d8d8d8,  inset -2px -2px 0 #d8d8d8,   /* clear */
    inset  3px  3px 0 #b8b8b8,  inset -3px -3px 0 #fff,      /* sunken */
    inset  4px  4px 0 #989898,  inset -4px -4px 0 #989898,   /* flat   */
    inset  5px  5px 0 #fff,     inset -5px -5px 0 #888;      /* raised */
}

[data-os="beos3"] .track {
  height: 11px;
  background: #d8d8d8;
  border-top: 1px solid #b8b8b8;
  border-left: 1px solid #b8b8b8;
  box-shadow: inset 1px 1px 0 #606060, inset -1px -1px 0 #efefef;
}
[data-os="beos3"] .fill {
  background: #3296ff;
  box-shadow: inset 0 1px 0 #86c1ff, inset 0 -1px 0 #1d5897;
  animation: none;
}

/* Off the Installer's "Options" button at native 89x23. The frame is neither
   symmetric nor a stack of rings: #797979, then #eeeeee, then TWO rows of
   #ffffff coming down the top and left; #797979, then #aaaaaa, then ONE row of
   #cacaca coming up the bottom and right; over an #eeeeee face. That row of
   face colour between the outline and the white is what makes a BeOS button
   look inflated rather than merely bevelled.

   It is an image because two things here are past a box-shadow. The corners
   are CUT — all four outermost pixels are panel, a one pixel radius done by
   leaving the pixel out, where border-radius: 1px would have the browser
   anti-alias a curve into a face that has no grey in it. And the bevel MITRES:
   the white's second row stops a column short at the top right and its second
   column a row short at the bottom left, where it meets the shadow on the
   diagonal, and stacked shadows give square corners. 9x9 sliced 4, built by
   build/beos-button.py. */
[data-os="beos3"] .btn {
  background: #eee; color: #000;
  /* padding-box, or the face would paint under the border and fill in the four
     corners the frame deliberately leaves out */
  background-clip: padding-box;
  border: 4px solid transparent;
  border-image: url("../img/beos-btn.png") 4 stretch;
  border-radius: 0;
  /* The capture puts the label's baseline 15 rows below the top edge and 7
     above the bottom, and two pixels of top padding put it there — a button
     centres its text in its CONTENT box, so the padding moves it half what it
     is worth. Hami's eye says a pixel higher than that, which is 14 and 8, so
     the padding comes off again. Our label has no descender where the
     capture's "Options" has a p, which is the likeliest reason it read low. */
  padding: 0 8px;
}
[data-os="beos3"] .btn:active { border-image: url("../img/beos-btn-down.png") 4 stretch; }


/* ======================= SKIN — NeXTSTEP 1.0 (1989) =====================
   Release 1.0, 18 September 1989, on the original MegaPixel Display.

   Was labelled 2.0 while it was being built, on nothing better than a guess
   at which release the first captures came from. Every reference Hami has
   sent since — the Power Off panel, the Workspace menu, the window titles,
   the two legal-notice panels, the resize bar and the close box — is 1.0, so
   the skin is 1.0 and there is no separate 2.0. 2.0 changed very little of
   this chrome anyway; 3.0 is where the colour display arrives, and that has
   always been its own skin below.

   Captures recovered at native 1120x832 and 447x231 (both exactly 2x, both
   back with exactly four values — so the MegaPixel Display's 2-bit greyscale
   survived intact): NX_WHITE #fff, NX_LTGRAY #aaa, NX_DKGRAY #555,
   NX_BLACK #000 (AppKit graphics.h). Anything wanting a fifth tone is
   dithered.

   Modelled on the Workspace alert panel, with a real title bar on it.

   Window:       1px black outline, flat #aaa face — an alert panel has no
                 bevel down its sides and no drop shadow. A resize bar along
                 the bottom: an incised #555-over-#fff line, 6 rows of face,
                 three segments with 28px grips.
   Title bar:    21px, and identical on the alert and on File Viewer/Info:
                 1px #aaa highlight, a 19px black slab, 1px #555 shadow,
                 then a 1px black rule under the whole thing. Title is
                 white, bold, centred on the WHOLE bar. Close box at the
                 right, 14x14, 4px in from the border.
   Buttons:      79x24. Bevel is 1px #fff top and left; bottom and right
                 are 1px #555 with 1px #000 outside it. 10px apart, 8px
                 in from the right edge, 10px up from the bottom.
   Wells:        the incised line under the alert's header is #555 over
                 #fff, so a sunken box is dark-grey top-left, white
                 bottom-right. That is the progress trough.
   Desktop:      #555, flat.                                              */

[data-os="next10"] {
  /* Three faces, because the Power Off panel uses three: a cap-11 body, a
     cap-9 button label and a bold cap-14 heading. Each sits 1:1 at the pixel
     size it was struck at and nowhere else. */
  --font: "NXBody", Helvetica, Arial, sans-serif;
  --fsize: 14px; --lh: 18px;
  --dlg-w: 330px;
  --face: #aaa; --text: #000;
  --title-h: 22px; --title-fg: #fff;   /* 1 hi + 19 slab + 1 shadow + 1 rule */
  --pad: 16px; --gap: 14px;
  --bar-h: 14px; --btn-h: 24px; --btn-w: 73px;
  --notice-fg: #fff;
}
[data-os="next10"] .screen  { background: #555; }

[data-os="next10"] .dialog  { border: 1px solid #000; background: #aaa; }
/* The resize bar along the bottom, off a capture recovered at native 208x15.
   Reading down: a 1px #555 over a 1px #fff — an incised line, the same
   engraving the vertical dividers and the return arrow use — then 6 rows of
   face, then the window's own black border, which .dialog already draws.

   Three segments. The grips are 28px and the middle takes the rest, split by
   the same two-pixel groove standing on end: #555 then #fff, dark to the
   left, which is the same light direction as the horizontal one above it.

   It is a pseudo-element rather than markup because no other skin has one,
   and it is a background rather than a stack of children because at 8px tall
   the whole thing is six flat rules and two grooves. */
[data-os="next10"] .dialog::after {
  content: ""; display: block; height: 8px;
  background:
    linear-gradient(90deg, #555 0 1px, #fff 1px 2px) 28px 2px / 2px 6px no-repeat,
    linear-gradient(90deg, #555 0 1px, #fff 1px 2px) right 28px top 2px / 2px 6px no-repeat,
    linear-gradient(#555 0 1px, #fff 1px 2px, #aaa 2px 8px);
}

/* 1px #aaa highlight top and left, 1px #555 shadow right, and the black rule
   under the bar is the border-bottom — 21 + 1 = the 22 rows in the capture. */
[data-os="next10"] .titlebar {
  background: #000; font-weight: bold;
  border-bottom: 1px solid #000;
  box-shadow: inset 1px 1px 0 #aaa, inset -1px -1px 0 #555;
}
[data-os="next10"] .tb-c  { justify-content: center; }
/* The title is centred on the WHOLE bar, so the empty left slot has to
   balance the close box on the right — 14px of button and 3px of margin —
   or the title sits half a button left of centre, which measured as exactly
   8.5px and is visible as soon as you look for it. */
[data-os="next10"] .tb-l  { width: 17px; }
/* The close box, off a top-right corner recovered at native 23x28. NeXTSTEP
   puts it on the RIGHT, so it takes the .w-a slot rather than .w-close — the
   slot names in this file are positions, not meanings.

   14x14, and the bevel is the plain one: #fff along the top and left, #555
   along the bottom and right, #aaa face. The corners go to the LIGHT side in
   the capture — the top row is white all the way to its right end and the
   bottom row starts on a white pixel — which is what an inset #fff drawn
   after the #555 gives, so the shadow pair is ordered accordingly.

   It sits 4px in from the window's black right border: 1px of #555 titlebar
   shadow and 3px of slab. */
[data-os="next10"] .tb-r .w-a {
  display: block; width: 14px; height: 14px; margin-right: 3px;
  background: #aaa;
  box-shadow: inset -1px -1px 0 #555, inset 1px 1px 0 #fff;
}
/* The X is 12x12 and two-toned — a black diagonal with #555 down one side of
   it, which is how a 1-bit machine implies a stroke lying between pixels. It
   is the capture's own bitmap, pixel for pixel, not a drawn cross. */
[data-os="next10"] .tb-r .w-a::before {
  content: ""; display: block; width: 12px; height: 12px; margin: 1px 0 0 1px;
  background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' shape-rendering='crispEdges'><path fill='%23555' d='M2 1h1v1H2zM9 1h1v1H9zM1 2h1v1H1zM3 2h1v1H3zM8 2h1v1H8zM10 2h1v1H10zM2 3h1v1H2zM4 3h1v1H4zM7 3h1v1H7zM9 3h1v1H9zM3 4h1v1H3zM5 4h2v1H5zM8 4h1v1H8zM4 5h1v1H4zM7 5h1v1H7zM4 6h1v1H4zM7 6h1v1H7zM3 7h1v1H3zM5 7h2v1H5zM8 7h1v1H8zM2 8h1v1H2zM4 8h1v1H4zM7 8h1v1H7zM9 8h1v1H9zM1 9h1v1H1zM3 9h1v1H3zM8 9h1v1H8zM10 9h1v1H10zM2 10h1v1H2zM9 10h1v1H9z'/><path fill='%23000' d='M1 1h1v1H1zM10 1h1v1H10zM2 2h1v1H2zM9 2h1v1H9zM3 3h1v1H3zM8 3h1v1H8zM4 4h1v1H4zM7 4h1v1H7zM5 5h2v1H5zM5 6h2v1H5zM4 7h1v1H4zM7 7h1v1H7zM3 8h1v1H3zM8 8h1v1H8zM2 9h1v1H2zM9 9h1v1H9zM1 10h1v1H1zM10 10h1v1H10z'/></svg>") 0 0 / 12px 12px no-repeat;
}
/* A window title is a fourth face again: bold, cap 9 — not the cap-14 bold the
   alert heading uses. Helvetica Bold, and LIFTED: 30 of its 32 glyphs are cut
   out of nine 8x window titles and two lines of prose. Only the C and the E
   are drawn, because no capture carries either letter in this face.

   Getting there took two goes, and the first is worth recording because the
   lesson was not the one it looked like. Nineteen letters came out of eight
   titles, the rest came off a strike, and the result read heavier at "Ev" and
   "Com" than in between — which looked like proof that half a face lifted is
   worse than a whole one substituted, and that parked attempt is still in
   build/nxtitle-lifted.json. It was not the real fault. Two things were: the
   letters touch in a face this bold so no blank column separates them, and
   cutting each LINE INTO WORDS FIRST — word gaps are 3-4px where letter gaps
   are 0-1 — turned an intractable search into several small ones; and the
   face is registered at weight normal, so asking for bold made the browser
   synthesise it by smearing every glyph a pixel right. That smear, not the
   patchwork, is what made the title look wrong. With both fixed the face came
   out whole, and there is no stand-in left in it to mix.

   The backing strike underneath the two drawn glyphs is Nimbus Sans Bold —
   the same Helvetica — struck 1-BIT, which is the aliased edge NeXTSTEP's own
   screen fonts have: not one grey pixel anywhere on that machine. Its size is
   chosen by measurement rather than by name: at 12ppem it lands on the
   capture's cap height of 9 and its x-height of 7. A literal 14pt — 14ppem at
   the 72dpi NeXTSTEP treated its screen as — comes out cap 11, two rows
   taller than the captures themselves. */
[data-os="next10"] .title {
  font-family: "NXTitle", Helvetica, Arial, sans-serif;
  font-size: 12px;
  /* The face IS the bold one, and it is registered at weight normal — so
     asking for bold here makes the browser synthesise it by smearing every
     glyph a pixel right, which fills in the gaps between a W's diagonals and
     closes the space between every pair of letters. It is the difference
     between reproducing these captures exactly and not. */
  font-weight: normal;
}

[data-os="next10"] .content  { padding: 16px 8px 10px; }
/* An alert's own line is set in the heading face — bold, cap 14 — not in the
   body it explains itself with. The panel shows that face as the two words
   "Power Off" and nothing else, which is seven letters, so the same call as
   the title bar applies: a whole face substituted beats seven letters lifted
   and the rest borrowed. Nimbus Sans Bold struck 1-bit, at the ppem that lands
   on the capture's cap height of 14; the seven that were lifted are kept in
   build/nxhead-lifted.json for when there is enough of that face to use. */
/* The alert's own line, in the face NeXTSTEP sets its menus in — cap 9, an
   x-height of 6, one pixel of stem — lifted whole off an 8x Workspace menu:
   "Window", "Edit", "Files", "View", "Optical", "Utilities", "Hide", "Log Out".
   Each menu item is its own word on its own row, so the letters cut on blank
   columns and nothing had to be enumerated; 24 of them, at 0.231px worst
   spacing residual. Only the comma is not the capture's.

   font-weight matters here for the same reason it does on the title: the face
   is registered at normal, so asking for bold makes the browser smear every
   glyph a pixel right and close every gap between letters. */
[data-os="next10"] .message  {
  text-align: left;
  font-family: "NXMenu", Helvetica, Arial, sans-serif;
  font-size: 12px; line-height: 16px; font-weight: normal;
}

/* Real borders, not inset shadows — .fill is an opaque child and would paint
   straight over a shadow on the top and left edges. */
[data-os="next10"] .track  {                            /* sunken well */
  height: 14px; background: #aaa;
  border: 1px solid #fff; border-top-color: #555; border-left-color: #555;
}
[data-os="next10"] .fill  { background: #000; }

[data-os="next10"] .actions  { padding: 0; }
/* Button labels are a size down again from the body — cap 9. */
/* 73x24, off a Cancel button recovered at native 83x37. The padding is not
   symmetric and cannot be: measured from the button's own edges the label's
   first inked column sits 8px in, and the arrow's last inked column 5px from
   the far edge.

   Those are INK positions, and CSS pads the advance box, so neither number is
   the padding. The C carries a 1px bearing of its own, so 7px of padding puts
   its ink at 8. And the l ends 2px short of its advance — that 2px is already
   part of the gap to the arrow, so the arrow's own margin is 5 to make the 7
   the capture shows. Get either wrong and the button is 2px too wide, which
   is exactly what it was.

   7 + 41 (the label's advance) + 5 + 15 (the arrow) + 5 = 73, so the content
   fills --btn-w exactly and the base rule's text-align has no slack to act
   on. A longer label would grow past it, which is the right behaviour.

   The 1px on the top is the same story vertically: the capture puts the
   label's ink 7 rows down and the arrow's 6, both ending on the same row,
   and a line box centred in 24px lands them a pixel high. Note that this
   number and the arrow's vertical-align are COUPLED — the arrow is the
   tallest thing on the line, so hanging it below the baseline changes where
   the baseline sits and moves the label with it. It is on the baseline
   (vertical-align: 0) because that is what makes its bottom row and the
   label's bottom row the same one, which is what the capture shows. */
[data-os="next10"] .btn {
  font-family: "NXBtn", Helvetica, Arial, sans-serif;
  font-size: 12px; font-weight: normal;
  padding: 1px 5px 0 7px;
  background: #aaa; border: 0;
  box-shadow: inset 1px 1px 0 #fff, inset -1px -1px 0 #000, inset -2px -2px 0 #555;
}
/* The return arrow that marks the default button, lifted from the Cancel
   button of the same panel: 15x10, three colours — black, the #555 shadow up
   its top left and the #ffffff highlight down its bottom right, which is the
   same engraving the panel's own bevels use. */
[data-os="next10"] .btn::after {
  content: ""; display: inline-block; vertical-align: 0;
  margin-left: 5px; width: 15px; height: 10px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='10' shape-rendering='crispEdges'%3E%3Cpath fill='%23000' d='M10 0h4v1H10zM4 1h2v1H4zM10 1h1v1H10zM3 2h1v1H3zM10 2h1v1H10zM2 3h1v1H2zM6 3h5v1H6zM1 4h1v1H1zM0 5h1v1H0zM1 6h1v1H1zM2 7h1v1H2zM3 8h1v1H3zM4 9h1v1H4z'/%3E%3Cpath fill='%23555' d='M14 0h1v1H14zM4 2h2v1H4zM3 3h1v1H3zM5 3h1v1H5zM2 4h1v1H2zM1 5h1v1H1z'/%3E%3Cpath fill='%23fff' d='M14 1h1v1H14zM14 2h1v1H14zM14 3h1v1H14zM14 4h1v1H14zM14 5h1v1H14zM14 6h1v1H14zM5 7h10v1H5zM5 8h1v1H5zM5 9h1v1H5z'/%3E%3C/svg%3E") 0 0 / 15px 10px no-repeat;
}
[data-os="next10"] .btn:active  {                       /* the bevel inverts */
  box-shadow: inset 1px 1px 0 #000, inset 2px 2px 0 #555, inset -1px -1px 0 #fff;
}
/* The address and the OS name under the dialog, in the smallest of NeXTSTEP's
   five faces — cap 7, x-height 5, the size it sets its legal notices in. 48 of
   its letters were lifted whole off two of those notices; see the NXLegal note
   in style.css for the two characters that are not the panels' own.

   line-height is given in whole pixels rather than left on .notice's 1.4,
   which at 9px is 12.6 and would put the stage on a fraction of a pixel — the
   thing that softens a bitmap face at any zoom but 1. */
[data-os="next10"] .notice {
  font-family: "NXLegal", Helvetica, Arial, sans-serif;
  font-size: 9px; line-height: 13px; font-weight: normal;
}


/* ======================= SKIN — NeXTSTEP 3.0 (1992) =====================
   Measured from a Release 3.0 screen recovered at native 1120x832 (the
   capture was exactly 2x). The key window's chrome is bit-for-bit what
   1.0 draws — 1px black outline, 1px #aaa highlight, a 19px black slab,
   1px #555 shadow, 1px black rule — so this skin inherits [[next10]]'s
   geometry and changes only what 3.0 actually changed:

   Workspace:   #555574 now that the hardware is in colour, not #555.
   Non-key bar: 3.0 is the release that greys an inactive title bar
                (#aaa face, #fff highlight) instead of blacking every
                window. Ours is the key window, so it stays black.
   Otherwise:   identical to 1.0 by measurement, and left that way — this
                one is a panel, and a panel gets no resize bar and no close
                box, so it keeps the plain window 1.0 draws.               */

[data-os="next30"] {
  --font: "Helv", Helvetica, Arial, sans-serif;
  --fsize: 12px; --lh: 1.45;
  --dlg-w: 330px;
  --face: #aaa; --text: #000;
  --title-h: 22px; --title-fg: #fff;
  --pad: 16px; --gap: 14px;
  --bar-h: 14px; --btn-h: 24px; --btn-w: 79px;
  --notice-fg: #fff;
}
[data-os="next30"] .screen  { background: #555574; }

[data-os="next30"] .dialog  { border: 1px solid #000; background: #aaa; }

[data-os="next30"] .titlebar {
  background: #000; font-weight: bold;
  border-bottom: 1px solid #000;
  box-shadow: inset 1px 1px 0 #aaa, inset -1px -1px 0 #555;
}
[data-os="next30"] .tb-c  { justify-content: center; }

[data-os="next30"] .content  { padding: 16px 8px 10px; }
[data-os="next30"] .message  { text-align: center; }

[data-os="next30"] .track {
  height: 14px; background: #aaa;
  border: 1px solid #fff; border-top-color: #555; border-left-color: #555;
}
[data-os="next30"] .fill  { background: #000; }

[data-os="next30"] .actions  { padding: 0; }
[data-os="next30"] .btn {
  background: #aaa; border: 0;
  box-shadow: inset 1px 1px 0 #fff, inset -1px -1px 0 #000, inset -2px -2px 0 #555;
}
[data-os="next30"] .btn:active {
  box-shadow: inset 1px 1px 0 #000, inset 2px 2px 0 #555, inset -1px -1px 0 #fff;
}


/* ======================= SKIN — OPENSTEP 4.0 (1996) =====================
   NeXTSTEP 3.0's window, with the two things OPENSTEP's own boot panel is
   remembered for. Measured from that panel, recovered at native 451x292.

   Progress bar:  13px overall and unlike anything else here — a sunken well
                  (#555 top and left, #fff bottom and right) with a second
                  1px black line inside the top and left only. The trough is
                  ruled like a tape measure: a 1px #555 tick every 13px,
                  2 rows tall, growing to 3 rows every 26px and 5 rows every
                  52px, all anchored to the left edge of the well. The fill
                  is flat #555 and 9 rows tall in a 10-row well, so the
                  bottom row of the trough shows under it.
   Type:          the panel sets its status line in an italic serif rather
                  than Helvetica. Left as a system face — Palatino on a Mac,
                  Georgia elsewhere — so it costs no download.
   Workspace:     #555574, same as 3.0.                                    */

[data-os="openstep4"] {
  --font: "Helv", Helvetica, Arial, sans-serif;
  --fsize: 12px; --lh: 1.45;
  --dlg-w: 330px;
  --face: #aaa; --text: #000;
  --title-h: 22px; --title-fg: #fff;
  --pad: 16px; --gap: 14px;
  --bar-h: 13px; --btn-h: 24px; --btn-w: 79px;
  --notice-fg: #fff;
}
[data-os="openstep4"] .screen  { background: #555574; }

[data-os="openstep4"] .dialog  { border: 1px solid #000; background: #aaa; }

[data-os="openstep4"] .titlebar {
  background: #000; font-weight: bold;
  border-bottom: 1px solid #000;
  box-shadow: inset 1px 1px 0 #aaa, inset -1px -1px 0 #555;
}
[data-os="openstep4"] .tb-c  { justify-content: center; }

[data-os="openstep4"] .content  { padding: 16px 8px 10px; }
[data-os="openstep4"] .message {
  text-align: center;
  font-family: Palatino, "Palatino Linotype", "Book Antiqua", Georgia, serif;
  font-style: italic; font-size: 14px;
}

/* padding holds the black inner line clear of .fill, which is opaque; the
   three tick rulers ride in the content box, under the fill. */
[data-os="openstep4"] .track {
  height: 13px; padding: 1px 0 0 1px;
  border: 1px solid #fff; border-top-color: #555; border-left-color: #555;
  box-shadow: inset 1px 1px 0 #000;
  background-color: #aaa;
  background-image:
    repeating-linear-gradient(90deg, #555 0 1px, transparent 1px 52px),
    repeating-linear-gradient(90deg, #555 0 1px, transparent 1px 26px),
    repeating-linear-gradient(90deg, #555 0 1px, transparent 1px 13px);
  background-size: 100% 5px, 100% 3px, 100% 2px;
  background-position: 0 4px, 0 6px, 0 7px;
  background-repeat: no-repeat, no-repeat, no-repeat;
  background-origin: content-box;
  background-clip: content-box;
}
[data-os="openstep4"] .fill  { height: 9px; background: #555; }

[data-os="openstep4"] .actions  { padding: 0; }
[data-os="openstep4"] .btn {
  background: #aaa; border: 0;
  box-shadow: inset 1px 1px 0 #fff, inset -1px -1px 0 #000, inset -2px -2px 0 #555;
}
[data-os="openstep4"] .btn:active {
  box-shadow: inset 1px 1px 0 #000, inset 2px 2px 0 #555, inset -1px -1px 0 #fff;
}
[data-os="openstep4"] .notice {
  font-family: Palatino, "Palatino Linotype", "Book Antiqua", Georgia, serif;
  font-style: italic;
}


/* ======================= SKIN — AmigaOS 1.3 (1988) ======================
   Measured from a System Request requester recovered at its native
   377x182 — the capture came back in exactly the four Workbench colours,
   so every value here is off it: blue #0055AA, white, black, orange
   #FF8800. Flat; there is not a single bevel in 1.x. The screen is 640x256
   with tall pixels, which is why Topaz is used in its 8x16 aspect-corrected
   form.

   The thing this skin had backwards: a 1.3 requester is a WHITE window with
   BLUE text, not blue with white text.

   Title bar:  20px of white with the title left-aligned in blue, and the
               rest filled by two 4px blue rules — 4 white, 4 blue, 4 white,
               4 blue, 4 white. Two depth gadgets at the right, traced pixel
               for pixel: overlapping squares, one black filled and one blue
               outlined, swapped between the two.
   Panel:      a 2px blue rule under the title bar, 2px of white, then the
               message panel's own 2px blue border.
   Buttons:    a 2px orange ring, 2px of white, a 2px blue ring, white fill
               and blue text. 56x30 in the capture.
   Progress:   1.3 had no progress control. This is the Workbench disk gauge
               — orange in a blue-ruled well, which is where the fourth
               colour is actually used.                                    */

[data-os="amiga13"] {
  --font: "Topaz13", monospace;
  --fsize: 16px; --lh: 16px;
  --dlg-w: 328px;
  --face: #fff; --text: #0055aa;
  --title-h: 22px; --title-fg: #0055aa;
  --pad: 12px; --gap: 14px;
  --bar-h: 16px; --btn-h: 30px; --btn-w: 88px;
  --notice-fg: #fff;
}
[data-os="amiga13"] .screen  { background: #0055aa; }
[data-os="amiga13"] .dialog  { background: #fff; padding: 0 2px 2px; }

/* 4 white, 4 blue, 4 white, 4 blue, 4 white, then the 2px rule beneath. */
[data-os="amiga13"] .titlebar {
  margin: 0 -2px; padding: 0;
  background: #fff;
  background-image: linear-gradient(180deg,
    transparent 0 4px, #0055aa 4px 8px, transparent 8px 12px,
    #0055aa 12px 16px, transparent 16px 20px);
  border-bottom: 2px solid #0055aa;
}
[data-os="amiga13"] .tb-c  { justify-content: flex-start; }
[data-os="amiga13"] .title  { background: #fff; padding: 0 4px; }
[data-os="amiga13"] .tb-r  { gap: 0; }
[data-os="amiga13"] .w-a, [data-os="amiga13"] .w-b {
  display: block; height: 20px; background-repeat: no-repeat;
  background-color: #fff;                 /* opaque, so the rules stop here */
  border-left: 2px solid #0055aa;
}
[data-os="amiga13"] .w-a  {                /* both gadgets sit at the RIGHT */
  width: 23px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='21' height='20' shape-rendering='crispEdges'%3E%3Cpath fill='%230055AA' d='M2 2h14v1h-14zM2 3h14v1h-14zM2 4h2v1h-2zM14 4h2v1h-2zM2 5h2v1h-2zM14 5h2v1h-2zM2 6h2v1h-2zM6 6h8v1h-8zM17 6h3v1h-3zM2 7h2v1h-2zM6 7h1v1h-1zM2 8h2v1h-2zM2 9h2v1h-2zM6 9h1v1h-1zM2 10h2v1h-2zM6 10h1v1h-1zM2 11h2v1h-2zM2 12h4v1h-4zM2 13h4v1h-4zM6 15h1v1h-1zM6 16h1v1h-1z'/%3E%3Cpath fill='%23000000' d='M14 6h3v1h-3zM7 7h13v1h-13zM6 8h14v1h-14zM7 9h13v1h-13zM7 10h13v1h-13zM6 11h14v1h-14zM6 12h14v1h-14zM6 13h14v1h-14zM6 14h14v1h-14zM7 15h13v1h-13zM7 16h13v1h-13zM6 17h14v1h-14z'/%3E%3C/svg%3E");
  background-position: 0 0; background-size: 21px 20px;
}
[data-os="amiga13"] .w-b {
  width: 24px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='20' shape-rendering='crispEdges'%3E%3Cpath fill='%230055AA' d='M0 0h1v1h-1zM0 1h1v1h-1zM0 2h1v1h-1zM3 2h1v1h-1zM0 3h1v1h-1zM3 3h1v1h-1zM0 4h1v1h-1zM3 4h1v1h-1zM7 4h14v1h-14zM0 5h1v1h-1zM7 5h14v1h-14zM0 6h1v1h-1zM3 6h1v1h-1zM7 6h2v1h-2zM19 6h2v1h-2zM0 7h1v1h-1zM3 7h1v1h-1zM7 7h2v1h-2zM19 7h2v1h-2zM0 8h1v1h-1zM7 8h2v1h-2zM19 8h2v1h-2zM0 9h1v1h-1zM3 9h1v1h-1zM7 9h2v1h-2zM19 9h2v1h-2zM0 10h1v1h-1zM3 10h1v1h-1zM7 10h2v1h-2zM19 10h2v1h-2zM0 11h1v1h-1zM7 11h2v1h-2zM19 11h2v1h-2zM0 12h1v1h-1zM3 12h1v1h-1zM7 12h2v1h-2zM19 12h2v1h-2zM0 13h1v1h-1zM3 13h1v1h-1zM7 13h2v1h-2zM19 13h2v1h-2zM0 14h1v1h-1zM7 14h2v1h-2zM19 14h2v1h-2zM0 15h1v1h-1zM7 15h2v1h-2zM19 15h2v1h-2zM0 16h1v1h-1zM7 16h14v1h-14zM0 17h1v1h-1zM7 17h14v1h-14zM0 18h1v1h-1zM0 19h1v1h-1z'/%3E%3Cpath fill='%23000000' d='M4 2h13v1h-13zM4 3h13v1h-13zM4 4h3v1h-3zM3 5h4v1h-4zM4 6h3v1h-3zM4 7h3v1h-3zM3 8h4v1h-4zM4 9h3v1h-3zM4 10h3v1h-3zM3 11h4v1h-4zM4 12h3v1h-3zM4 13h3v1h-3z'/%3E%3C/svg%3E");
  background-position: 0 0; background-size: 22px 20px;
}

[data-os="amiga13"] .content {
  background: #fff; border: 2px solid #0055aa; margin: 2px;
}
[data-os="amiga13"] .track {
  height: 16px; border: 2px solid #0055aa; background: #fff;
}
[data-os="amiga13"] .fill  { background: #ff8800; }
[data-os="amiga13"] .btn {
  background: #fff; color: #0055aa; padding: 0 10px;
  border: 2px solid #ff8800;
  box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4px #0055aa;
}
[data-os="amiga13"] .btn:active {
  background: #0055aa; color: #fff;
  box-shadow: inset 0 0 0 2px #0055aa, inset 0 0 0 4px #fff;
}


/* ======================= SKIN — AmigaOS 2.0 (1990) ======================
   Taken from a Workbench 2.x error requester. That capture was resampled to
   a non-integer size, so this is read for structure and set in 2.0's own
   pens, with one value measured off it because it came back flat and
   consistent: the title-bar blue is #6880AC.

   Pens:       BACKGROUND #aaaaaa, TEXT/SHADOW #000000, SHINE #ffffff,
               FILL #6880ac. 2.0 shades semantically — raised means you can
               press it, recessed means it is only telling you something.
   Title bar:  solid blue, 20px, title in BLACK and left-aligned, a 1px
               white shine along the top of the window above it and a 1px
               black rule beneath. Depth gadget at the right.
   Body:       a 50% white-on-grey checkerboard, with the message sitting in
               a RECESSED panel — black on its top and left, white on its
               bottom and right, flat grey inside.
   Buttons:    raised the other way about: 1px white on the top and left,
               2px black on the bottom and right, black text on grey.
   Backdrop:   1px horizontal hatch of #aaaaaa and #999999.               */

[data-os="amiga20"] {
  --font: "Topaz20", monospace;
  --fsize: 16px; --lh: 16px;
  --dlg-w: 328px;
  --face: #aaa; --text: #000;
  --title-h: 21px; --title-bg: #6880ac; --title-fg: #000;
  --pad: 10px; --gap: 14px;
  --bar-h: 16px; --btn-h: 24px; --btn-w: 88px;
  --notice-fg: #000;
}
[data-os="amiga20"] .screen {
  background-color: #aaa;
  background-image: repeating-linear-gradient(180deg, #aaa 0 1px, #999 1px 2px);
}
[data-os="amiga20"] .dialog {
  background: #aaa; padding: 0 2px 2px;
  box-shadow: inset 0 1px 0 #fff, inset 1px 0 0 #fff, inset -1px 0 0 #000,
              inset 0 -1px 0 #000;
}
[data-os="amiga20"] .titlebar {
  margin: 0 -2px; padding: 0 2px;
  background: #6880ac;
  border-bottom: 1px solid #000;
  box-shadow: inset 0 1px 0 #fff;
}
[data-os="amiga20"] .tb-c  { justify-content: flex-start; padding-left: 4px; }
[data-os="amiga20"] .tb-r  { gap: 0; }
/* Flat: the depth gadget has no bevel and no grey box round it. It is two
   overlapping squares with 2px black outlines drawn straight onto the blue —
   the back one filled blue, the front one white — behind a 1px black then
   1px white divider. */
[data-os="amiga20"] .w-b {
  display: block; position: relative; width: 24px; height: 20px;
  background: #6880ac;
  border-left: 1px solid #fff;
  box-shadow: -1px 0 0 #000;
}
[data-os="amiga20"] .w-b::before  {        /* back square */
  content: ""; position: absolute; left: 3px; top: 2px; width: 12px; height: 11px;
  border: 2px solid #000; background: #6880ac;
}
[data-os="amiga20"] .w-b::after  {         /* front square */
  content: ""; position: absolute; left: 8px; top: 7px; width: 12px; height: 11px;
  border: 2px solid #000; background: #fff;
}

/* The checkerboard is the requester's own ground; the message sits in a
   recessed well on flat grey. */
[data-os="amiga20"] .content {
  padding: 4px;
  background-color: #aaa;
  background-image: repeating-conic-gradient(#fff 0 25%, #aaa 0 50%);
  background-size: 2px 2px;
}
[data-os="amiga20"] .message {
  background: #aaa; padding: 8px;
  box-shadow: inset 1px 1px 0 #000, inset -1px -1px 0 #fff;
  margin-bottom: 10px;
}
[data-os="amiga20"] .progress  { margin: 0 0 10px; }
[data-os="amiga20"] .track {
  height: 16px; padding: 1px; background: #aaa;
  box-shadow: inset 1px 1px 0 #000, inset -1px -1px 0 #fff;
}
[data-os="amiga20"] .fill  { background: #6880ac; }
[data-os="amiga20"] .btn {
  background: #aaa; color: #000;
  box-shadow: inset 1px 1px 0 #fff, inset -2px -2px 0 #000;
}
[data-os="amiga20"] .btn:active {
  box-shadow: inset 2px 2px 0 #000, inset -1px -1px 0 #fff;
}


/* ======================= SKIN — RISC OS 3 (1992) ========================
   Measured from four RISC OS 3.11 screens captured at their native 640x480,
   in the Wimp's own 16-colour palette — 17 colours in the file, and every
   one of them exact.

   Window:      1px black outline, body #d4d4d4, backdrop #7f7f7f. Square
                corners; the rounded ends and vertical hatch this skin used
                to have are not in RISC OS 3 at all.
   Title bar:   19px between two 1px black rules, and SOLID — #e9e9aa cream
                when the window has input focus, #aaaaaa when it does not.
                No hatch, no stripes. Title is black and centred, with the
                close icon 3px in from the left border.
   Progress:    the Wimp has no progress control, and the free-space window
                does not fake one with a trough — the bar IS the value: a
                black-outlined rectangle 10px tall (1px rule, 8px of colour,
                1px rule) drawn only as wide as it has got to. At 7MB of
                504MB it collapses to two black columns and nothing else.
                Free space is #00bf00, total is #00157f.
   Buttons:     cream #e9e9aa with a 1px black outline, 24px tall, and no
                second ring — the Save dialog's OK has none.
   Type:        the Wimp's own System font, not Helvetica. It is fixed
                pitch and drawn 8 screen pixels wide by 16 tall, the 16
                rows being an 8-row bitmap doubled vertically — so the
                pixels are not square, which no ordinary bitmap font will
                give you. build/riscos-font.py harvests the glyphs out of
                the captures and builds it; at 16px it lands 1:1.         */

[data-os="riscos3"] {
  --font: "RiscOS", "Courier New", monospace;
  --fsize: 16px; --lh: 16px;
  --dlg-w: 340px;
  --face: #d4d4d4; --text: #000;
  --title-h: 20px; --title-fg: #000;
  --pad: 12px; --gap: 12px;
  --bar-h: 10px; --btn-h: 24px; --btn-w: 84px;
  --notice-fg: #000;
}
[data-os="riscos3"] .screen  { background: #7f7f7f; }

[data-os="riscos3"] .dialog  { border: 1px solid #000; background: #d4d4d4; }

[data-os="riscos3"] .titlebar {
  background: #e9e9aa;                 /* focused; #aaa is the unfocused bar */
  border-bottom: 1px solid #000;
}
/* Two icon cells hard against the left of the bar, each 19px square with a
   1px black divider after it — the back icon (two overlapping windows) then
   the close icon (RISC OS's bowtie). Both traced pixel for pixel off a 3x
   capture. The title is centred on what is left, not on the whole bar. */
[data-os="riscos3"] .tb-l  { align-self: stretch; gap: 0; }
[data-os="riscos3"] .tb-l::before,
[data-os="riscos3"] .w-close {
  content: ""; display: block; flex: none;
  width: 20px; height: 19px; border-right: 1px solid #000;  /* border-box */
  background-repeat: no-repeat; background-size: 19px 19px;
}
[data-os="riscos3"] .tb-l::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19' shape-rendering='crispEdges'%3E%3Cpath fill='%23000000' d='M2 2h11v1h-11zM2 3h1v1h-1zM12 3h1v1h-1zM2 4h1v1h-1zM12 4h1v1h-1zM2 5h1v1h-1zM12 5h1v1h-1zM2 6h1v1h-1zM6 6h11v1h-11zM2 7h1v1h-1zM6 7h1v1h-1zM16 7h1v1h-1zM2 8h1v1h-1zM6 8h1v1h-1zM16 8h1v1h-1zM2 9h1v1h-1zM6 9h1v1h-1zM16 9h1v1h-1zM2 10h1v1h-1zM6 10h1v1h-1zM16 10h1v1h-1zM2 11h1v1h-1zM6 11h1v1h-1zM16 11h1v1h-1zM2 12h5v1h-5zM16 12h1v1h-1zM6 13h1v1h-1zM16 13h1v1h-1zM6 14h1v1h-1zM16 14h1v1h-1zM6 15h1v1h-1zM16 15h1v1h-1zM6 16h11v1h-11z'/%3E%3Cpath fill='%232A2A2A' d='M3 3h9v1h-9zM3 4h9v1h-9zM3 5h9v1h-9zM3 6h3v1h-3zM3 7h3v1h-3zM3 8h3v1h-3zM3 9h3v1h-3zM3 10h3v1h-3zM3 11h3v1h-3z'/%3E%3C/svg%3E");
}
[data-os="riscos3"] .w-close {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19' shape-rendering='crispEdges'%3E%3Cpath fill='%23000000' d='M5 3h3v1h-3zM11 3h3v1h-3zM4 4h1v1h-1zM8 4h1v1h-1zM10 4h1v1h-1zM14 4h1v1h-1zM3 5h1v1h-1zM9 5h1v1h-1zM15 5h1v1h-1zM3 6h1v1h-1zM15 6h1v1h-1zM3 7h1v1h-1zM15 7h1v1h-1zM4 8h1v1h-1zM14 8h1v1h-1zM5 9h1v1h-1zM13 9h1v1h-1zM4 10h1v1h-1zM14 10h1v1h-1zM3 11h1v1h-1zM15 11h1v1h-1zM3 12h1v1h-1zM15 12h1v1h-1zM3 13h1v1h-1zM9 13h1v1h-1zM15 13h1v1h-1zM4 14h1v1h-1zM8 14h1v1h-1zM10 14h1v1h-1zM14 14h1v1h-1zM5 15h3v1h-3zM11 15h3v1h-3z'/%3E%3C/svg%3E");
}
[data-os="riscos3"] .tb-c  { justify-content: center; }

/* No trough. The bar is the value: outline and fill, nothing behind it. */
[data-os="riscos3"] .track  { height: 10px; background: none; }
[data-os="riscos3"] .fill {
  background: #00bf00;
  box-shadow: inset 0 0 0 1px #000;
}

[data-os="riscos3"] .actions  { padding: 0; }
[data-os="riscos3"] .btn  { background: #e9e9aa; border: 1px solid #000; }
[data-os="riscos3"] .btn:active  { background: #000; color: #e9e9aa; }
/* ================ SKIN — RISC OS 3 Newlook (1996) =======================
   RISC OS 3.6's optional 3D theme, measured from toastytech's native 640x480
   riscosnewlook.png. Nothing here is shared with the RISC OS 3 skin above
   except the window's black outline: Newlook threw out the flat cream title
   bar and the chunky System font in one go.

   Palette is the RISC OS grey ramp, read off the capture: #f0f0f0, #d0d0d0,
   #b0b0b0, #909090, #707070, #505050. Window face is #d0d0d0.

   Title bar, measured on the "Screen" window (x210-513, y74-93): a 1px black
   rule, 18 rows of caption, another 1px black rule. The caption is a raised
   2px bevel — #f0f0f0 then #d0d0d0 coming down the top and left, #505050 then
   #909090 going up the bottom and right — and the tool icons at the left are
   the same bevel again, 21px wide, each closed off by a 1px black rule.

   The caption face is NOT flat. It is a stipple, 58% #b0b0b0, 30% #d0d0d0 and
   5% #f0f0f0, and it does not repeat inside 102px of clean caption, so it is a
   noise fill rather than a small tile. What is inlined below is a real 32x14
   patch lifted out of the capture at x404,y77 — measured pixels, not generated
   noise — tiled. Tiling is the one liberty: the original does not repeat, this
   does every 32px. At 1x that is invisible; it is the reason the patch is 32
   wide rather than 8.

   Text is the SAME System font as RISC OS 3, not an outline face. Checked
   rather than assumed, after an earlier pass got this wrong: the caption's
   "Screen" sits on an exact 8px pitch (x358, 366, 374, 382, 390, 398) and every
   glyph row is doubled, which is the Wimp System font's 8x8-drawn-as-8x16 and
   nothing else. 3.5 onwards CAN draw titles in an outline font; this build does
   not, so riscos.woff2 it is.

   Approximated, not measured: the close and back glyphs are the flat ones from
   the RISC OS 3 skin sitting on Newlook's bevel. Newlook redrew them with
   their own shading, which the capture has at 11px and this does not.       */

[data-os="riscosnew"] {
  --font: "RiscOS", "Courier New", monospace;
  --fsize: 16px; --lh: 16px;
  --dlg-w: 336px;
  --face: #d0d0d0; --text: #000;
  --title-h: 20px; --title-fg: #000;
  /* 18 + the 1px border puts the text 19px in from the window's edge, which is
     where the Installer capture has it, and leaves the 13px of clear between
     the groove and the work area that the same capture measures. */
  --pad: 18px; --gap: 14px;
  --bar-h: 14px; --btn-h: 26px; --btn-w: 88px;
  --notice-fg: #fff;
}
[data-os="riscosnew"] .screen  { background: #707070; }

[data-os="riscosnew"] .dialog  { border: 1px solid #000; background: #d0d0d0; }

/* 1px black top rule is the .dialog border; this carries the bottom one. */
[data-os="riscosnew"] .titlebar {
  padding: 0;
  border-bottom: 1px solid #000;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='14'%3E%3Cpath fill='%23b0b0b0' d='M0 0h32v14H0z'/%3E%3Cpath fill='%23d0d0d0' d='M0 0h1v1H0zM3 0h1v1H3zM16 0h1v1H16zM18 0h3v1H18zM29 0h3v1H29zM5 1h1v1H5zM14 1h1v1H14zM17 1h4v1H17zM28 1h1v1H28zM31 1h1v1H31zM0 2h1v1H0zM6 2h1v1H6zM15 2h1v1H15zM17 2h4v1H17zM23 2h1v1H23zM31 2h1v1H31zM1 3h1v1H1zM4 3h1v1H4zM8 3h2v1H8zM14 3h3v1H14zM18 3h1v1H18zM20 3h1v1H20zM28 3h1v1H28zM30 3h1v1H30zM6 4h5v1H6zM14 4h1v1H14zM16 4h3v1H16zM4 5h1v1H4zM6 5h1v1H6zM8 5h3v1H8zM13 5h1v1H13zM15 5h2v1H15zM28 5h1v1H28zM1 6h1v1H1zM7 6h4v1H7zM14 6h3v1H14zM18 6h1v1H18zM24 6h1v1H24zM1 7h4v1H1zM6 7h1v1H6zM8 7h4v1H8zM13 7h1v1H13zM31 7h1v1H31zM1 8h2v1H1zM4 8h1v1H4zM9 8h1v1H9zM11 8h3v1H11zM25 8h1v1H25zM28 8h1v1H28zM30 8h1v1H30zM0 9h2v1H0zM3 9h3v1H3zM10 9h3v1H10zM15 9h1v1H15zM17 9h1v1H17zM19 9h1v1H19zM21 9h1v1H21zM23 9h3v1H23zM1 10h2v1H1zM11 10h1v1H11zM15 10h1v1H15zM17 10h2v1H17zM20 10h4v1H20zM25 10h2v1H25zM28 10h1v1H28zM30 10h1v1H30zM6 11h1v1H6zM8 11h1v1H8zM11 11h1v1H11zM14 11h2v1H14zM17 11h1v1H17zM19 11h1v1H19zM22 11h3v1H22zM26 11h2v1H26zM2 12h1v1H2zM6 12h1v1H6zM8 12h1v1H8zM10 12h1v1H10zM12 12h2v1H12zM15 12h2v1H15zM18 12h2v1H18zM21 12h2v1H21zM25 12h2v1H25zM1 13h1v1H1zM3 13h1v1H3zM5 13h3v1H5zM11 13h2v1H11zM14 13h1v1H14zM17 13h1v1H17zM19 13h1v1H19zM21 13h1v1H21zM23 13h2v1H23zM26 13h2v1H26z'/%3E%3Cpath fill='%23f0f0f0' d='M2 0h1v1H2zM5 0h2v1H5zM25 0h1v1H25zM6 1h1v1H6zM24 1h1v1H24zM2 2h1v1H2zM4 2h2v1H4zM3 3h1v1H3zM20 5h1v1H20zM30 6h1v1H30zM12 7h1v1H12zM25 7h1v1H25zM3 8h1v1H3z'/%3E%3C/svg%3E") 0 0 / 32px 14px;
  box-shadow: inset 1px 1px 0 #f0f0f0, inset -1px -1px 0 #505050,
              inset 2px 2px 0 #d0d0d0, inset -2px -2px 0 #909090;
}
[data-os="riscosnew"] .tb-l  { align-self: stretch; gap: 0; }
[data-os="riscosnew"] .tb-c  { justify-content: center; }

/* Two tool icons, each its own raised bevel closed off by a black rule.
   Measured at x211-228 and x230-247: an 18px cell, a 2px bevel — #f0f0f0 then
   #d0d0d0 down the top and left, #505050 then #909090 up the bottom and right
   — over a #b0b0b0 face, then a 1px black rule.

   The glyphs are the actual 14x12 bitmaps out of the capture, which is what
   the first pass got wrong. LEFT is BACK: two overlapping window outlines,
   engraved #505050 on their top-left edges and #f0f0f0 on their bottom-right
   so they read as cut into the icon. RIGHT is CLOSE: a shaded saltire, not a
   cross inside a box. Both run-length encoded per colour, crispEdges. */
[data-os="riscosnew"] .tb-l::before,
[data-os="riscosnew"] .w-close {
  content: ""; display: block; flex: none;
  width: 19px; align-self: stretch;
  border-right: 1px solid #000;
  background-color: #b0b0b0;
  background-repeat: no-repeat;
  background-position: 2px 3px;
  background-size: 14px 12px;
  box-shadow: inset 1px 1px 0 #f0f0f0, inset -1px -1px 0 #505050,
              inset 2px 2px 0 #d0d0d0, inset -2px -2px 0 #909090;
}
[data-os="riscosnew"] .tb-l::before {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='12' shape-rendering='crispEdges'%3E%3Cpath fill='%23505050' d='M1 0h7v1H1zM1 1h1v1H1zM1 2h1v1H1zM1 3h1v1H1zM4 3h7v1H4zM1 4h1v1H1zM4 4h1v1H4zM1 5h1v1H1zM4 5h1v1H4zM1 6h1v1H1zM4 6h1v1H4zM11 6h1v1H11zM1 7h1v1H1zM4 7h1v1H4zM11 7h1v1H11zM4 8h1v1H4zM11 8h1v1H11zM4 9h1v1H4zM11 9h1v1H11zM4 10h1v1H4zM7 10h5v1H7z'/%3E%3Cpath fill='%23707070' d='M8 0h1v1H8zM8 2h1v1H8zM11 3h1v1H11zM11 5h1v1H11zM3 7h1v1H3zM6 10h1v1H6z'/%3E%3Cpath fill='%23f0f0f0' d='M2 1h6v1H2zM2 2h1v1H2zM9 2h1v1H9zM2 3h1v1H2zM2 4h1v1H2zM5 4h6v1H5zM2 5h1v1H2zM5 5h1v1H5zM12 5h1v1H12zM2 6h1v1H2zM5 6h1v1H5zM12 6h1v1H12zM5 7h1v1H5zM12 7h1v1H12zM3 8h1v1H3zM5 8h1v1H5zM12 8h1v1H12zM5 9h1v1H5zM12 9h1v1H12zM12 10h1v1H12zM6 11h7v1H6z'/%3E%3Cpath fill='%23d0d0d0' d='M9 1h1v1H9zM12 4h1v1H12zM2 8h1v1H2zM5 11h1v1H5z'/%3E%3Cpath fill='%23909090' d='M1 8h1v1H1zM4 11h1v1H4z'/%3E%3C/svg%3E");
}
[data-os="riscosnew"] .w-close {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='12' shape-rendering='crispEdges'%3E%3Cpath fill='%23d0d0d0' d='M1 1h1v1H1zM4 1h1v1H4zM12 1h1v1H12zM1 2h1v1H1zM5 2h1v1H5zM11 2h2v1H11zM2 3h1v1H2zM6 3h1v1H6zM10 3h2v1H10zM3 4h1v1H3zM10 4h1v1H10zM4 5h2v1H4zM9 5h1v1H9zM9 6h1v1H9zM6 7h1v1H6zM5 8h3v1H5zM4 9h2v1H4zM8 9h1v1H8zM3 10h2v1H3zM9 10h1v1H9zM2 11h2v1H2zM10 11h2v1H10z'/%3E%3Cpath fill='%23505050' d='M2 1h1v1H2zM10 1h1v1H10zM3 2h1v1H3zM9 2h1v1H9zM4 3h1v1H4zM8 3h1v1H8zM5 4h1v1H5zM5 6h1v1H5zM8 6h1v1H8zM4 7h1v1H4zM9 7h1v1H9zM3 8h1v1H3zM10 8h1v1H10zM2 9h1v1H2zM11 9h1v1H11z'/%3E%3Cpath fill='%23707070' d='M3 1h1v1H3zM4 2h1v1H4zM5 3h1v1H5zM7 4h1v1H7z'/%3E%3Cpath fill='%23909090' d='M11 1h1v1H11zM10 2h1v1H10zM9 3h1v1H9zM6 4h1v1H6zM8 4h1v1H8zM6 5h2v1H6zM6 6h2v1H6zM5 7h1v1H5zM8 7h1v1H8zM4 8h1v1H4zM9 8h1v1H9zM3 9h1v1H3zM10 9h1v1H10zM2 10h1v1H2zM11 10h1v1H11z'/%3E%3Cpath fill='%23f0f0f0' d='M2 2h1v1H2zM3 3h1v1H3zM4 4h1v1H4zM9 4h1v1H9zM8 5h1v1H8zM7 7h1v1H7zM8 8h1v1H8zM9 9h1v1H9zM10 10h1v1H10z'/%3E%3C/svg%3E");
}

/* Body widgets are NOT the caption's slab. Measured off the bump arrows beside
   the writable fields in riscosnewlook.png (x432-505, y313-333): the icon is
   the window's own #d0d0d0, and the whole 3D effect is one #f0f0f0 edge and one
   #707070 edge. No second face colour, no four-tone ramp. */
[data-os="riscosnew"] .track {
  height: 14px;
  background: #d0d0d0;
  box-shadow: inset 1px 1px 0 #707070, inset -1px -1px 0 #f0f0f0,
              inset 2px 2px 0 #909090, inset -2px -2px 0 #f0f0f0;
}
[data-os="riscosnew"] .fill  { background: #00c000; }

[data-os="riscosnew"] .btn {
  background: #d0d0d0; color: #000;
  box-shadow: inset 1px 1px 0 #f0f0f0, inset -1px -1px 0 #707070,
              inset 2px 2px 0 #f0f0f0, inset -2px -2px 0 #909090;
}
[data-os="riscosnew"] .btn:active {
  box-shadow: inset 1px 1px 0 #707070, inset -1px -1px 0 #f0f0f0,
              inset 2px 2px 0 #909090, inset -2px -2px 0 #f0f0f0;
}


/* ====================== SKIN — Windows 2.03 (1987) ======================
   Rebuilt from three 4x captures — the COMMAND window, the End Session box
   and the Screen Colors control panel — all exact integer scales. Four
   colours across the set: #000000, #ffffff, #5555ff and the #55ffff of the
   application workspace.

   Three references, three jobs, because no single 2.03 window has all of it:

     the outer border  from COMMAND — 1px black, a 4px band of 50% black and
                       white checker (2.03's sizing border), then 1px black
     the dialog        from End Session — a 19-row band of solid blue with the
                       title in a black block that runs its full height and is
                       centred on the whole bar, then white
   The Screen Colors panel puts a 1px white and 4px blue band between its
   client and its frame. It was in here for a pass and it was too much against
   the checker, so the client is plain white and the blue stays in the caption.

   Buttons are End Session's, measured cap by cap: 62x24 with a 1px outline
   and the same four-row rounded end 1.01 uses, and the default is 64x26 with
   a 2px outline and a dotted focus rectangle inside it. Both are drawn in one
   64x26 box so nothing shifts when the ring appears.

   2.03 shipped no progress control, so the bar is invented: a 1px black box,
   white, filled with the caption blue.

   FONT IS A STAND-IN. 2.03's system font is not 1.01's. Both have 2px stems,
   but 2.03's caps are 9 rows against 1.01's 10 — visible in End Session's own
   title, where "End Session" runs rows 6 to 14 of a 19-row band. Until it is
   harvested this borrows 1.01's face, which is the right manufacturer and the
   right decade and the wrong height.                                      */

[data-os="win2"] {
  --font: "Win1System", monospace;
  --fsize: 12px; --lh: 12px;
  --dlg-w: 320px;
  --face: #fff; --text: #000;
  --title-h: 21px; --title-fg: #fff;
  --pad: 12px; --gap: 14px;
  --bar-h: 16px; --btn-h: 26px; --btn-w: 64px;
  --notice-fg: #000; --notice-fsize: 12px;
}

[data-os="win2"] .screen { background: #55ffff; }

/* 1px black, then the 4px checker the padding is filled with. The 1px black
   line that closes the frame is carried by the caption and the client, which
   is also how they get their own outline.

   The sizing border is not one continuous band: it is cut into a corner piece
   and an edge piece on each side by a solid black rule, 31 columns in from
   the left and right and 25 rows down from the top and bottom — the drag
   handles, and the reason 2.03's frame reads as jointed rather than woven.
   (31 against 25 because EGA pixels were taller than they were wide, so the
   corners were square on the glass and are not here.) They are drawn as four
   full-length lines and the caption and client, being opaque, hide the middle
   of each — so only the eight corner cuts show. */
[data-os="win2"] .dialog {
  border: 1px solid #000;
  padding: 4px;
  background:
    linear-gradient(#000, #000) 30px 0 / 1px 100% no-repeat,
    linear-gradient(#000, #000) right 30px top 0 / 1px 100% no-repeat,
    linear-gradient(#000, #000) 0 24px / 100% 1px no-repeat,
    linear-gradient(#000, #000) left 0 bottom 24px / 100% 1px no-repeat,
    repeating-conic-gradient(#000 0 25%, #fff 0 50%) 0 0 / 2px 2px;
}

/* 21px = the frame's inner black line + 19 rows of blue + the rule under. */
[data-os="win2"] .titlebar {
  padding: 0;
  border: 1px solid #000;
  background: #5555ff;
}
/* COMMAND's three caption boxes, each 25px of white against the blue with a
   1px black rule between it and the band. Unlike 1.01, 2.03 centres the title
   on the space LEFT BETWEEN the boxes rather than on the whole bar — measured
   at 272.5 against a window centre of 285.5 — which is what the flex default
   does here, so the end cells are deliberately not balanced. */
[data-os="win2"] .tb-l,
[data-os="win2"] .tb-r { align-items: stretch; align-self: stretch; gap: 0; }
[data-os="win2"] .tb-c {
  justify-content: center;
  align-items: stretch;
  align-self: stretch;
}
[data-os="win2"] .w-close,
[data-os="win2"] .w-a,
[data-os="win2"] .w-b {
  display: block; flex: none; width: 26px; align-self: stretch;
  background-color: #fff;
  background-repeat: no-repeat;
  background-size: 25px 19px;
}
[data-os="win2"] .w-close {
  border-right: 1px solid #000;
  background-image: url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='25'%20height='19'%20shape-rendering='crispEdges'><path%20d='M2%207h20v1H2M2%208h1v1H2M21%208h2v1H21M2%209h1v1H2M21%209h2v1H21M2%2010h21v1H2M3%2011h20v1H3'/></svg>");
  background-position: 0 0;
}
[data-os="win2"] .w-a,
[data-os="win2"] .w-b {
  border-left: 1px solid #000;
  background-position: 100% 0;
}
[data-os="win2"] .w-a { background-image: url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='25'%20height='19'%20shape-rendering='crispEdges'><path%20d='M10%202h5v1H10M10%203h1v1H10M14%203h1v1H14M10%204h1v1H10M14%204h2v1H14M10%205h1v1H10M14%205h2v1H14M10%206h1v1H10M14%206h2v1H14M10%207h1v1H10M14%207h2v1H14M10%208h1v1H10M14%208h2v1H14M10%209h1v1H10M14%209h2v1H14M7%2010h4v1H7M14%2010h4v1H14M8%2011h1v1H8M16%2011h3v1H16M9%2012h1v1H9M15%2012h3v1H15M10%2013h1v1H10M14%2013h3v1H14M11%2014h1v1H11M13%2014h3v1H13M12%2015h3v1H12M13%2016h1v1H13'/></svg>"); }
[data-os="win2"] .w-b { background-image: url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='25'%20height='19'%20shape-rendering='crispEdges'><path%20d='M12%202h1v1H12M11%203h1v1H11M13%203h2v1H13M10%204h1v1H10M14%204h2v1H14M9%205h1v1H9M15%205h2v1H15M8%206h1v1H8M16%206h2v1H16M7%207h4v1H7M14%207h5v1H14M10%208h1v1H10M14%208h4v1H14M10%209h1v1H10M14%209h2v1H14M10%2010h1v1H10M14%2010h2v1H14M10%2011h1v1H10M14%2011h2v1H14M10%2012h1v1H10M14%2012h2v1H14M10%2013h1v1H10M14%2013h2v1H14M10%2014h1v1H10M14%2014h2v1H14M10%2015h6v1H10M11%2016h5v1H11'/></svg>"); }
[data-os="win2"] .title {
  background: #000;
  padding: 5px 2px 0;
  line-height: 12px;
}

[data-os="win2"] .content {
  border: 1px solid #000;
  border-top: 0;
  background: #fff;
}

/* 2.03 has no progress control, so this is its slider: the Control Panel's
   own trough is not flat but a 4x2 dither three parts black to one — white at
   (3,0) and (1,1) — and that is what fills the bar, inside a 1px black box on
   white. Measured off the Cursor Blink and Double Click sliders, which agree. */
[data-os="win2"] .track {
  height: 15px; padding: 0;
  border: 1px solid #000; background: #fff;
}
[data-os="win2"] .fill { background: url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='4'%20height='2'%20shape-rendering='crispEdges'><path%20d='M0%200h4v2H0z'/><path%20fill='%23fff'%20d='M3%200h1v1H3zM1%201h1v1H1z'/></svg>") 0 0 / 4px 2px; }

/* 62x24 drawn inside a 64x26 box. */
[data-os="win2"] .btn {
  height: 26px;
  /* Seven rows under the top edge, eight over the bottom — End Session's own
     Cancel. */
  padding: 2px 6px 0;
  border: 0;
  border-radius: 0;
  line-height: 12px;
  background:
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='24'%20shape-rendering='crispEdges'><path%20fill='%23fff'%20d='M4%201h8v1H4M2%202h10v1H2M2%203h10v1H2M1%204h11v1H1M1%205h11v1H1M1%206h11v1H1M1%207h11v1H1M1%208h11v1H1M1%209h11v1H1M1%2010h11v1H1M1%2011h11v1H1M1%2012h11v1H1M1%2013h11v1H1M1%2014h11v1H1M1%2015h11v1H1M1%2016h11v1H1M1%2017h11v1H1M1%2018h11v1H1M1%2019h11v1H1M2%2020h10v1H2M2%2021h10v1H2M4%2022h8v1H4'/><path%20d='M4%200h8v1H4M2%201h2v1H2M1%202h1v1H1M1%203h1v1H1M0%204h1v1H0M0%205h1v1H0M0%206h1v1H0M0%207h1v1H0M0%208h1v1H0M0%209h1v1H0M0%2010h1v1H0M0%2011h1v1H0M0%2012h1v1H0M0%2013h1v1H0M0%2014h1v1H0M0%2015h1v1H0M0%2016h1v1H0M0%2017h1v1H0M0%2018h1v1H0M0%2019h1v1H0M1%2020h1v1H1M1%2021h1v1H1M2%2022h2v1H2M4%2023h8v1H4'/></svg>") 1px 1px / 12px 24px no-repeat,
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='24'%20shape-rendering='crispEdges'><path%20fill='%23fff'%20d='M0%201h8v1H0M0%202h10v1H0M0%203h10v1H0M0%204h11v1H0M0%205h11v1H0M0%206h11v1H0M0%207h11v1H0M0%208h11v1H0M0%209h11v1H0M0%2010h11v1H0M0%2011h11v1H0M0%2012h11v1H0M0%2013h11v1H0M0%2014h11v1H0M0%2015h11v1H0M0%2016h11v1H0M0%2017h11v1H0M0%2018h11v1H0M0%2019h11v1H0M0%2020h10v1H0M0%2021h10v1H0M0%2022h8v1H0'/><path%20d='M0%200h8v1H0M8%201h2v1H8M10%202h1v1H10M10%203h1v1H10M11%204h1v1H11M11%205h1v1H11M11%206h1v1H11M11%207h1v1H11M11%208h1v1H11M11%209h1v1H11M11%2010h1v1H11M11%2011h1v1H11M11%2012h1v1H11M11%2013h1v1H11M11%2014h1v1H11M11%2015h1v1H11M11%2016h1v1H11M11%2017h1v1H11M11%2018h1v1H11M11%2019h1v1H11M10%2020h1v1H10M10%2021h1v1H10M8%2022h2v1H8M0%2023h8v1H0'/></svg>") right 1px top 1px / 12px 24px no-repeat,
    linear-gradient(180deg, #000 0 1px, #fff 1px 23px, #000 23px 24px)
      13px 1px / calc(100% - 26px) 24px no-repeat;
}

/* The default button, filling the whole 64x26, with End Session's own dotted
   rectangle inside it. */
[data-os="win2"] .btn:focus-visible {
  outline: 1px dotted #000;
  outline-offset: -5px;
  background:
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='26'%20shape-rendering='crispEdges'><path%20fill='%23fff'%20d='M5%202h7v1H5M3%203h9v1H3M3%204h9v1H3M2%205h10v1H2M2%206h10v1H2M2%207h10v1H2M2%208h10v1H2M2%209h10v1H2M2%2010h10v1H2M2%2011h10v1H2M2%2012h10v1H2M2%2013h10v1H2M2%2014h10v1H2M2%2015h10v1H2M2%2016h10v1H2M2%2017h10v1H2M2%2018h10v1H2M2%2019h10v1H2M2%2020h10v1H2M3%2021h9v1H3M3%2022h9v1H3M5%2023h7v1H5'/><path%20d='M5%200h7v1H5M3%201h9v1H3M2%202h3v1H2M1%203h2v1H1M1%204h2v1H1M0%205h2v1H0M0%206h2v1H0M0%207h2v1H0M0%208h2v1H0M0%209h2v1H0M0%2010h2v1H0M0%2011h2v1H0M0%2012h2v1H0M0%2013h2v1H0M0%2014h2v1H0M0%2015h2v1H0M0%2016h2v1H0M0%2017h2v1H0M0%2018h2v1H0M0%2019h2v1H0M0%2020h2v1H0M1%2021h2v1H1M1%2022h2v1H1M2%2023h3v1H2M3%2024h9v1H3M5%2025h7v1H5'/></svg>") 0 0 / 12px 26px no-repeat,
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='26'%20shape-rendering='crispEdges'><path%20fill='%23fff'%20d='M0%202h7v1H0M0%203h9v1H0M0%204h9v1H0M0%205h10v1H0M0%206h10v1H0M0%207h10v1H0M0%208h10v1H0M0%209h10v1H0M0%2010h10v1H0M0%2011h10v1H0M0%2012h10v1H0M0%2013h10v1H0M0%2014h10v1H0M0%2015h10v1H0M0%2016h10v1H0M0%2017h10v1H0M0%2018h10v1H0M0%2019h10v1H0M0%2020h10v1H0M0%2021h9v1H0M0%2022h9v1H0M0%2023h7v1H0'/><path%20d='M0%200h7v1H0M0%201h9v1H0M7%202h3v1H7M9%203h2v1H9M9%204h2v1H9M10%205h2v1H10M10%206h2v1H10M10%207h2v1H10M10%208h2v1H10M10%209h2v1H10M10%2010h2v1H10M10%2011h2v1H10M10%2012h2v1H10M10%2013h2v1H10M10%2014h2v1H10M10%2015h2v1H10M10%2016h2v1H10M10%2017h2v1H10M10%2018h2v1H10M10%2019h2v1H10M10%2020h2v1H10M9%2021h2v1H9M9%2022h2v1H9M7%2023h3v1H7M0%2024h9v1H0M0%2025h7v1H0'/></svg>") right top / 12px 26px no-repeat,
    linear-gradient(180deg, #000 0 2px, #fff 2px 24px, #000 24px 26px)
      12px 0 / calc(100% - 24px) 26px no-repeat;
}

[data-os="win2"] .btn:active {
  color: #fff;
  background:
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='24'%20shape-rendering='crispEdges'><path%20d='M4%200h8v1H4M2%201h10v1H2M1%202h11v1H1M1%203h11v1H1M0%204h12v1H0M0%205h12v1H0M0%206h12v1H0M0%207h12v1H0M0%208h12v1H0M0%209h12v1H0M0%2010h12v1H0M0%2011h12v1H0M0%2012h12v1H0M0%2013h12v1H0M0%2014h12v1H0M0%2015h12v1H0M0%2016h12v1H0M0%2017h12v1H0M0%2018h12v1H0M0%2019h12v1H0M1%2020h11v1H1M1%2021h11v1H1M2%2022h10v1H2M4%2023h8v1H4'/></svg>") 1px 1px / 12px 24px no-repeat,
    url("data:image/svg+xml,<svg%20xmlns='http%3A//www.w3.org/2000/svg'%20width='12'%20height='24'%20shape-rendering='crispEdges'><path%20d='M0%200h8v1H0M0%201h10v1H0M0%202h11v1H0M0%203h11v1H0M0%204h12v1H0M0%205h12v1H0M0%206h12v1H0M0%207h12v1H0M0%208h12v1H0M0%209h12v1H0M0%2010h12v1H0M0%2011h12v1H0M0%2012h12v1H0M0%2013h12v1H0M0%2014h12v1H0M0%2015h12v1H0M0%2016h12v1H0M0%2017h12v1H0M0%2018h12v1H0M0%2019h12v1H0M0%2020h11v1H0M0%2021h11v1H0M0%2022h10v1H0M0%2023h8v1H0'/></svg>") right 1px top 1px / 12px 24px no-repeat,
    linear-gradient(180deg, #000 0 24px)
      13px 1px / calc(100% - 26px) 24px no-repeat;
}


/* ======================= SKIN — OS/2 1.1 (1988) =========================
   Measured from os211shutdown.png and os211startup.png, native 640x480. The
   whole capture holds six colours: #ffffff, #a8a8a8, #000000, #0000a8 and two
   accents that never touch the chrome.

   The desktop is a 50%% checker of white and #a8a8a8, inlined below as the real
   2x2 cell. The window frame, measured at x188-191, is 1px black, 2px of that
   same checker as a sizing border, then 1px black — no bevel anywhere, this is
   two years before the Workplace Shell.

   Body is white and the message text is NAVY, not black: 1.1's PM dialogues
   set their text in #0000a8, which is the single most recognisable thing about
   them. Buttons are white with a thin black outline.

   Font is a stand-in — 1.1's system font has not been harvested.           */

[data-os="os211"] {
  --font: "Helv", Helvetica, Arial, sans-serif;
  --fsize: 12px; --lh: 1.35;
  --dlg-w: 320px;
  --face: #fff; --text: #0000a8;
  --title-h: 19px; --title-fg: #000;
  --pad: 14px; --gap: 14px;
  --bar-h: 14px; --btn-h: 22px; --btn-w: 72px;
  --notice-fg: #000;
}
[data-os="os211"] .screen {
  background-color: #a8a8a8;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2'%3E%3Cpath fill='%23a8a8a8' d='M0 0h2v2H0z'/%3E%3Cpath fill='%23ffffff' d='M0 0h1v1H0zM1 1h1v1H1z'/%3E%3C/svg%3E");
  background-size: var(--dither) var(--dither);
}
[data-os="os211"] .dialog {
  border: 1px solid #000;
  padding: 2px;
  background-color: #a8a8a8;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2'%3E%3Cpath fill='%23a8a8a8' d='M0 0h2v2H0z'/%3E%3Cpath fill='%23ffffff' d='M0 0h1v1H0zM1 1h1v1H1z'/%3E%3C/svg%3E");
  background-size: 2px 2px;
  box-shadow: inset 0 0 0 0 transparent;
}
[data-os="os211"] .titlebar {
  padding: 0;
  border: 1px solid #000; border-bottom: 0;
  background: #fff;
}
[data-os="os211"] .tb-c  { justify-content: center; }
[data-os="os211"] .title  { font-weight: bold; }
[data-os="os211"] .content {
  border: 1px solid #000; border-top: 1px solid #000;
  background: #fff;
}
[data-os="os211"] .track  { height: 14px; border: 1px solid #000; background: #fff; }
[data-os="os211"] .fill  { background: #0000a8; }
[data-os="os211"] .btn  { background: #fff; color: #000; border: 1px solid #000; }
[data-os="os211"] .btn:active  { background: #000; color: #fff; }


/* ================= SKIN — OS/2 2.0 Workplace Shell (1992) ===============
   Measured from os220folders.png, native 640x480. Palette is exactly four
   greys plus the desktop: #ffffff, #cccccc, #808080, #000000, teal #008080.

   Frame measured on the "Drive C - Icon View" window at x275-281 and y98-119:
   2px of #cccccc, then 1px #808080, then 1px #ffffff, then the client. The
   caption is 16 rows of #cccccc between two #808080 rules, with the system
   menu box closed off by its own #808080/#ffffff pair.

   The capture's windows are all INACTIVE — their titles are drawn in #808080.
   An active WPS caption puts the title in black, which is what this uses.

   Font is a stand-in for WarpSans.                                        */

[data-os="os220"] {
  --font: "Helv", Helvetica, Arial, sans-serif;
  --fsize: 12px; --lh: 1.35;
  --dlg-w: 330px;
  --face: #cccccc; --text: #000;
  --title-h: 18px; --title-fg: #000;
  --pad: 12px; --gap: 12px;
  --bar-h: 14px; --btn-h: 24px; --btn-w: 80px;
  --notice-fg: #fff;
}
[data-os="os220"] .screen  { background: #008080; }
[data-os="os220"] .dialog {
  padding: 2px;
  background: #cccccc;
  box-shadow: inset -1px -1px 0 #808080, inset 1px 1px 0 #fff;
}
[data-os="os220"] .titlebar {
  padding: 0 4px;
  background: #cccccc;
  box-shadow: inset 0 1px 0 #808080, inset 0 -1px 0 #808080;
}
[data-os="os220"] .tb-c  { justify-content: center; }
[data-os="os220"] .content  { background: #cccccc; }
[data-os="os220"] .track {
  height: 14px; padding: 1px; background: #cccccc;
  box-shadow: inset 1px 1px 0 #808080, inset -1px -1px 0 #fff;
}
[data-os="os220"] .fill  { background: #808080; }
[data-os="os220"] .btn {
  background: #cccccc;
  box-shadow: inset -1px -1px 0 #808080, inset 1px 1px 0 #fff,
              inset -2px -2px 0 #808080, inset 2px 2px 0 #fff;
}
[data-os="os220"] .btn:active {
  box-shadow: inset 1px 1px 0 #808080, inset -1px -1px 0 #fff;
  padding-top: 2px; padding-left: 2px;
}


/* ================== SKIN — OS/2 Warp 3 installer (1994) =================
   Not the Workplace Shell — Warp 3's INSTALLER, measured from the native
   640x480 os23installing.gif, which is the closest thing on toastytech to the
   dialogue this page is pretending to be.

   The caption is the find: 20 rows between two #808080 rules, filled with
   1px horizontal stripes alternating #800080 and #000080. Not a gradient, not
   a solid — alternating single-pixel rows, measured row by row from y43 to
   y62. Body is #c0c0c0, text #000080, backdrop the installer's #008080.

   The progress bar is abstracted. Warp 3 drew the filled portion as black
   carrying a repeating colour illustration; the four colour zones measured
   down it (#ff0000, #ffff00, #00ffff, #00ff00 in that order) are kept as
   rules over black, which reads as the original at a glance without pretending
   to be the artwork.                                                      */

[data-os="warp3"] {
  --font: "Helv", Helvetica, Arial, sans-serif;
  --fsize: 12px; --lh: 1.4;
  --dlg-w: 340px;
  --face: #c0c0c0; --text: #000080;
  --title-h: 22px; --title-fg: #fff;
  --pad: 14px; --gap: 14px;
  --bar-h: 28px; --btn-h: 24px; --btn-w: 80px;
  --notice-fg: #fff;
}
[data-os="warp3"] .screen  { background: #008080; }
[data-os="warp3"] .dialog {
  padding: 2px;
  background: #c0c0c0;
  box-shadow: inset -1px -1px 0 #808080, inset 1px 1px 0 #fff;
}
[data-os="warp3"] .titlebar {
  padding: 0 6px;
  background-image: repeating-linear-gradient(180deg, #800080 0 1px, #000080 1px 2px);
  box-shadow: inset 0 1px 0 #808080, inset 0 -1px 0 #808080;
}
[data-os="warp3"] .title  { font-weight: bold; }
[data-os="warp3"] .content  { background: #c0c0c0; }
[data-os="warp3"] .track {
  height: 28px; padding: 1px; background: #c0c0c0;
  box-shadow: inset 1px 1px 0 #808080, inset -1px -1px 0 #fff;
}
[data-os="warp3"] .fill {
  background-color: #000;
  background-image: linear-gradient(180deg,
    transparent 0 5px, #ff0000 5px 7px, transparent 7px 12px,
    #ffff00 12px 14px, transparent 14px 18px, #00ffff 18px 20px,
    transparent 20px 24px, #00ff00 24px 26px, transparent 26px);
}
[data-os="warp3"] .btn {
  background: #c0c0c0; color: #000;
  box-shadow: inset -1px -1px 0 #808080, inset 1px 1px 0 #fff,
              inset -2px -2px 0 #808080, inset 2px 2px 0 #fff;
}
[data-os="warp3"] .btn:active {
  box-shadow: inset 1px 1px 0 #808080, inset -1px -1px 0 #fff;
  padding-top: 2px; padding-left: 2px;
}


/* =================== SKIN — OS/2 Warp 4 (1996) ==========================
   Palette measured from the native 640x480 os24_winlist.png: #ffffff, the
   pair #0000ad and #000052, face #cecece, #080808, #848484.

   Warp 4 kept the Workplace Shell's geometry and changed its colour, so the
   frame and caption structure here are 2.0's, measured, with Warp 4's palette
   over them. The blue pair is the one thing read from the palette rather than
   from a measured caption band — it is far too much of the image to be
   anything but the desktop and the active caption, and both are given the
   gradient it is famous for.                                              */

[data-os="warp4"] {
  --font: "Helv", Helvetica, Arial, sans-serif;
  --fsize: 12px; --lh: 1.35;
  --dlg-w: 330px;
  --face: #cecece; --text: #080808;
  --title-h: 20px; --title-fg: #fff;
  --pad: 12px; --gap: 12px;
  --bar-h: 14px; --btn-h: 24px; --btn-w: 80px;
  --notice-fg: #fff;
}
[data-os="warp4"] .screen  { background: linear-gradient(180deg, #0000ad 0%, #000052 100%); }
[data-os="warp4"] .dialog {
  padding: 2px;
  background: #cecece;
  box-shadow: inset -1px -1px 0 #848484, inset 1px 1px 0 #fff;
}
[data-os="warp4"] .titlebar {
  padding: 0 6px;
  background-image: linear-gradient(90deg, #000052 0%, #0000ad 100%);
}
[data-os="warp4"] .title  { font-weight: bold; }
[data-os="warp4"] .content  { background: #cecece; }
[data-os="warp4"] .track {
  height: 14px; padding: 1px; background: #cecece;
  box-shadow: inset 1px 1px 0 #848484, inset -1px -1px 0 #fff;
}
[data-os="warp4"] .fill  { background: #0000ad; }
[data-os="warp4"] .btn {
  background: #cecece; color: #080808;
  box-shadow: inset -1px -1px 0 #848484, inset 1px 1px 0 #fff,
              inset -2px -2px 0 #848484, inset 2px 2px 0 #fff;
}
[data-os="warp4"] .btn:active {
  box-shadow: inset 1px 1px 0 #848484, inset -1px -1px 0 #fff;
  padding-top: 2px; padding-left: 2px;
}


/* ====================== SKIN — RISC OS 4 (1999) =========================
   Rebuilt from Hami's captures of the Display manager, the shutdown box and
   the Task Manager. All three resample to an exact integer scale once the
   phase is found — 8x for the first, 4x for the other two — so the numbers
   below are real pixels.

   TEXTURE is the thing that makes a RISC OS 4 screenshot recognisable, and a
   background-color cannot get near it: the desktop, the window face and the
   title bar are all FILLED with a speckled, faintly cloudy pattern rather
   than painted flat. The window face runs 59% #dedede with the rest scattered
   a step or two down; per-pixel sd 7.2, but 8x8 block sd 2.7 where white
   noise alone would give 0.9, so the speckle clumps. The capture's own
   texture does not repeat, so a lifted patch would carry a seam;
   build/riscos-tile.py generates seamless ones instead, on a torus, matched
   to the measured histogram and to that block sd. Three of them: face, title
   bar, desktop.

   FRAME    1px black, then a 2px bevel — #ffffff up on the top and left,
            #9c9c9c down on the bottom and right.
   CAPTION  19 rows: 1px #ffffff, 15 rows of the title texture, #9c9c9c,
            #5a5a5a, and a 1px black rule. RISC OS sizes the bar to the
            configured desktop font, which is why the smaller Display-manager
            capture has 11 texture rows and the About window 15; this follows
            the About window, since that is where the type came from. The
            icons at its left are cells of the same height, each one white
            then content then #9c9c9c and #5a5a5a — the bar's own section
            turned on its side.
   BUTTON   a 2px bevel on a FLAT #dedede — the speckle stops at the button,
            as the About window's More shows.  #ffffff up against #737373 down.
            The DEFAULT button wears two more rings — 2px of #efefbd, then a
            2px sunken one — which is Restart in the shutdown capture and
            neither Cancel nor Change in the Display manager, so it is the
            focus ring here.
   WELL     the writable fields are the same 2px bevel inverted, #737373 up
            against #ffffff down.
   BAR      not invented this time: the Task Manager draws its memory bars as
            a 1px black outline round 8 rows of #de0000, straight on the
            window face with no trough behind them, and that is what this is.

   FONT     Homerton, which is Acorn's Helvetica, so Nimbus Sans is the same
            design. Regular at 14px — see the note in style.css for why this
            went round the houses first. RISC OS drew outline fonts
            antialiased, so unlike the 1-bit skins here this one is meant to
            be smooth.                                                    */

[data-os="riscos4"] {
  --font: "RO4Desk", "Nimbus Sans", Helvetica, Arial, sans-serif;
  --fsize: 14px; --lh: 20px;
  --dlg-w: 320px;
  --face: #dedede; --text: #000;
  --title-h: 19px; --title-fg: #000;
  /* RISC OS packs a window tight. In the About box the first gadget starts 2
     rows below the content's white lip, the last ends 3 above its shadow, and
     the right-hand one stops 3 short of it; the gaps between the Name, Author
     and Version fields are 4 and 3. That measures 5 of padding, of which the
     2px lip eats two — but the About box is three stacked fields with nothing
     loose in it, and this dialog is a line of prose, a bar and one button, so
     it is Hami's call that it wants twice the room. 10, then, and 4 between
     children as measured. */
  --pad: 10px; --gap: 4px;
  --bar-h: 12px; --btn-h: 26px; --btn-w: 90px;
  --notice-fg: #000;
}
/* Flat #777777. RISC OS 4's own desktop is a tiled noise texture, and
   build/riscos-tile.py still generates the window and title-bar tiles from
   the same capture — but at this size a 128px tile of speckle behind a 320px
   dialog reads as compression artefacts rather than as a texture, and it
   fights the address sitting on top of it. Hami's call. */
[data-os="riscos4"] .screen { background: #777; }
[data-os="riscos4"] .notice { line-height: 20px; }
[data-os="riscos4"] .dialog {
  border: 1px solid #000;
  background: url("../img/ro-face.png") 0 0 / 64px 64px repeat;
}

/* The bar's own section, top to bottom, is drawn as background layers so each
   row lands exactly where the capture has it; the texture is the last layer
   and shows through the eleven rows between. The offsets look one short
   because a percentage in background-position resolves against the box height
   MINUS the layer's own, so on a 15px bar 100% is 14, not 15. */
[data-os="riscos4"] .titlebar {
  padding: 0;
  border-right: 1px solid #9c9c9c;
  color: #000;
  background:
    linear-gradient(#fff, #fff)         left top / 100% 1px no-repeat,
    linear-gradient(#9c9c9c, #9c9c9c)   left calc(100% - 2px) / 100% 1px no-repeat,
    linear-gradient(#5a5a5a, #5a5a5a)   left calc(100% - 1px) / 100% 1px no-repeat,
    linear-gradient(#000, #000)         left bottom / 100% 1px no-repeat,
    url("../img/ro-title.png") 0 0 / 32px 32px repeat;
}
[data-os="riscos4"] .tb-l  { align-self: stretch; gap: 0; }
[data-os="riscos4"] .tb-c  { justify-content: center; }
/* The caption gets its own leading so its box cannot overflow the bar. */
[data-os="riscos4"] .title { line-height: 19px; }
/* 5, not the shared 4: it makes the stage 190 rows rather than 189, and an odd
   stage is centred on a half pixel, which softens every 1px rule in the frame. */
[data-os="riscos4"] .osname { margin-top: 5px; }

/* Both title-bar icons, lifted whole from Hami's 4x close-up rather than
   redrawn. They are 3D objects — the back icon is two overlapping window
   outlines with their own highlights and shadows, the close cross is a raised
   X, and each sits in a cell of white, its content, #9c9c9c and #5a5a5a.
   Enough shading that a hand-drawn SVG would only approximate it, and small
   enough that lifting costs 320 bytes.

   The 39px is the pair plus the black divider between them and the black-then-
   white edge where the title cell starts, so it carries the caption's left end
   entire; .titlebar therefore has no left border of its own. The lift is 15x15
   and the cells are 19x19, which is what makes them square against the taller
   bar: the eight columns and four rows between are copies of each cell's own
   plain ground, two on every side of every glyph, so the frames and the glyphs
   are still the capture's and each icon keeps its 3-pixel margin all round. */
[data-os="riscos4"] .w-close {
  display: block; flex: none;
  width: 39px; height: 19px; align-self: flex-start;
  background: url("../img/ro-title-icons.png") 0 0 no-repeat;
}

/* The work area's lip is 2px of white over 2px of #737373 — the About box has
   #ffffff down its rows 20-21 and columns 1-2, and #777777 (that machine's
   name for this grey) up rows 138-139 and columns 349-350. */
[data-os="riscos4"] .content {
  background: url("../img/ro-face.png") 0 0 / 64px 64px repeat;
  box-shadow: inset 2px 2px #fff, inset -2px -2px #737373;
}

/* A sunken well, cut the same way as the About box's Name/Author/Version
   fields: 2px of #737373 on the top and left, 2px of white on the bottom and
   right, and a face that is FLAT — the speckle stops at a well's edge, which
   is the one place in the window the fill does not reach. Eight rows of
   #de0000 inside it, the height the Task Manager's own bar runs to. */
[data-os="riscos4"] .track {
  height: 12px; padding: 2px;
  border: 0;
  background: #dedede;
  box-shadow: inset 2px 2px #737373, inset -2px -2px #fff;
}
[data-os="riscos4"] .fill  { background: #de0000; }

/* Flat, not textured. The window face is filled with the speckle and the
   button face is NOT — the More button in the About window is a clean #dedede
   with nothing in it but its label, which is the one place the fill stops. */
/* The label is not centred in the face. Both of Hami's 8x button captures put
   a 12-row ink box in a 22-row interior with 4 rows above it and 6 below, so
   the baseline sits 6 up from the bottom lip rather than the 5 that centring
   would give. 4px of top padding and none at the bottom moves the line box the
   two rows that buys — a button centres its text in its CONTENT box, so the
   shift is half the difference, not all of it. */
[data-os="riscos4"] .btn {
  padding-top: 4px; padding-bottom: 0;
  color: #000;
  background: #dedede;
  box-shadow: inset 2px 2px #fff, inset -2px -2px #737373;
}
[data-os="riscos4"] .btn:active {
  box-shadow: inset 2px 2px #737373, inset -2px -2px #fff;
}
/* The default action's rings, 2px of #efefbd inside a 2px sunken one. */
[data-os="riscos4"] .btn:focus-visible {
  outline: 0;
  box-shadow:
    inset 2px 2px #fff, inset -2px -2px #737373,
    0 0 0 2px #efefbd,
    -1px -1px 0 3px #737373,
     1px 1px 0 3px #fff;
}


/* =============== SKIN — Solaris 8 / CDE (2000) ==========================
   Rebuilt from Hami's 8x captures — the Encryption dialog, the Style Manager
   window, and a sheet of purple buttons in both states. All three resample to
   an exact 8x once the phase is found, so every number below is a real pixel.

   PALETTE (the captures hold these and almost nothing else)
     desktop #524a8c   frame face #b54a7b   frame highlight #deadc6
     window  #adb5c6   frame shadow #522139
     wells   #fff7ef   bevel up #dedee7     bevel down #5a636b

   FRAME  five pixels, three colours a side, and MITRED — each side owns a
          45-degree wedge, so the bands turn the corner on a diagonal rather
          than butting square. Outside in: 2px raised bevel, 2px of frame face,
          1px sunken lip. Four box-shadows would give square corners, so this
          is a border-image whose corner tiles carry the mitre; the source is
          generated by build/cde-frame.py, whose model reproduces both of the
          capture's corners with zero differing pixels.

   CAPTION 19 rows — a 1px raised bevel around 17 rows of #b54a7b. In a window
          the bar is a ROW of such cells, minimise then title then maximise,
          each 19px and abutting; a modal dialog is one cell across, which is
          what this is. Title white and centred, and not bold.

   CLIENT 1px #dedee7 up on the top and left, 2px #5a636b down on the bottom
          and right. The asymmetry is measured, not a slip — the Style
          Manager's client carries 1px there and this dialog's form carries 2.

   BUTTONS Motif's two-tone, 1px: #dedee7 on the top and left, #5a636b on the
          bottom and right, and pressing FLIPS the pair. That is what the
          purple sheet shows — its four samples are one pressed and three
          identical at rest, so there is exactly one state change to carry
          over. The DEFAULT button additionally wears a 1px sunken ring two
          pixels outside itself, which OK has in the capture and Cancel does
          not; here that is the focus ring.

   ETCHED  the button row is separated from the body by a 1px #5a636b over a
          1px #dedee7 — Motif's etched-in line — running the full width of the
          client, which is why .actions is pulled out to the padding edges.

   Font is a stand-in for the DtStandard bitmap face.                      */

[data-os="solaris8"] {
  --font: "DtSans", "DejaVu Sans", Verdana, sans-serif;
  /* 15px is the strike's own cell, so it sits 1:1 and stays one bit deep.
     Line height in px, not a ratio, so .stage cannot end up a fraction of a
     pixel tall and put the centred dialog on a half pixel. */
  --fsize: 15px; --lh: 17px;
  --dlg-w: 340px;
  --face: #adb5c6; --text: #000;
  --title-h: 19px; --title-fg: #fff;
  --pad: 14px; --gap: 14px;
  /* The label is 48px of ink inside 12px padding, so the button has to be even
     for text-align centring to have no half pixel to split — a stem on one is
     two grey columns on a face drawn one bit deep. Both this and the title's
     padding above follow the label widths, so they move when the font does. */
  --bar-h: 15px; --btn-h: 25px; --btn-w: 84px;
  --notice-fg: #fff7ef;
}
[data-os="solaris8"] .screen  { background: #524a8c; }
/* Centred text lands on a half pixel whenever the box it centres in differs
   from it by an odd number, and a stem on a half pixel is two grey columns on
   a face drawn one bit deep. Both 1px paddings exist only to fix that parity:
   the first makes the block an even width so the stage centres it whole, the
   second does the same for the OS name inside it. They follow the string
   widths, so they move if the strings or the font do. */
[data-os="solaris8"] .notice  { line-height: 17px; padding-right: 1px; }
/* 5, not the shared 4: it makes the stage 210 rows rather than 209, and an odd
   stage is centred on a half pixel, which the 2x zoom then smears every 1px
   bevel across. Nothing to do with the OS name itself. */
[data-os="solaris8"] .osname  { padding-right: 1px; margin-top: 5px; }

[data-os="solaris8"] .dialog {
  padding: 0;
  border: 5px solid transparent;
  border-image: url("../img/cde-frame.png") 5 fill / 5px stretch;
  background: none;
}
[data-os="solaris8"] .titlebar {
  height: 19px; padding: 0;
  background: #b54a7b;
  box-shadow: inset 1px 1px #deadc6, inset -1px -1px #522139;
}

/* The caption is a ROW of raised cells rather than one bar with widgets laid
   on it: the window-menu box, then the title, each 1px bevelled and abutting,
   so the boundary between them reads as a shadow beside a highlight. The cells
   are 19px — the caption's full height — and the box is hard against the
   frame, which is why the bar carries no padding of its own.

   The box's own bevel supplies the caption's top and left edge where it sits;
   .tb-c then only needs the one highlight column where the title cell starts.
   Both are drawn highlight-first so the highlight owns the bottom-left corner,
   which is what the capture has at row 29 of the caption. */
[data-os="solaris8"] .tb-l  { align-self: stretch; gap: 0; }
[data-os="solaris8"] .tb-c  {
  align-self: stretch; justify-content: center;
  /* Keeps the title off the highlight column, and makes the space it centres
     in an even number of pixels wider than the title, so text-align has no
     half pixel to split — a stem on one is two grey columns. */
  padding-left: 2px;
  box-shadow: inset 1px 0 #deadc6;
}
[data-os="solaris8"] .title { font-weight: normal; }

/* The window-menu box. Its slab is an 11x4 raised rectangle at (4, 7) inside
   the 19px cell — highlight along the top and down the left, shadow along the
   bottom and up the right, caption rose between. Read off Hami's 8x close-up,
   which agrees with the Style Manager capture pixel for pixel. */
[data-os="solaris8"] .w-close {
  display: block; flex: none;
  width: 19px; align-self: stretch;
  background: #b54a7b url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='19' shape-rendering='crispEdges'%3E%3Cpath fill='%23deadc6' d='M4 7h11v1H4zM4 8h1v3H4z'/%3E%3Cpath fill='%23522139' d='M14 8h1v2h-1zM5 10h10v1H5z'/%3E%3C/svg%3E") no-repeat 0 0;
  box-shadow: inset 1px 1px #deadc6, inset -1px -1px #522139;
}
[data-os="solaris8"] .content {
  background: #adb5c6;
  box-shadow: inset 1px 1px #dedee7, inset -2px -2px #5a636b;
}
/* Label text sits straight on the window face — CDE puts a well round an
   editable field, never round a message. */
[data-os="solaris8"] .message { background: none; padding: 0; box-shadow: none; }

/* The XmScale trough, off the Screen Lock capture: a 1px sunken bevel round a
   trough of #9494a5, which is a good deal darker than the window face and is
   the thing that reads as CDE at a glance. The fill takes the caption rose,
   not the desktop purple. */
[data-os="solaris8"] .track {
  height: 15px; padding: 1px; background: #9494a5;
  box-shadow: inset 1px 1px #5a636b, inset -1px -1px #dedee7;
}
/* The fill is a RAISED box standing in the trough, not a flat band: the slider
   close-up draws its thumb with a 1px highlight along the top and left and a
   1px shadow along the bottom and right, filling the trough's full 13 rows.
   The thumb also carries a divider down its middle, which a progress fill has
   no business with and is left off. Rose face, so the bevel takes the rose
   pair the caption uses rather than the grey one. */
[data-os="solaris8"] .fill  {
  background: #b54a7b;
  box-shadow: inset 1px 1px #deadc6, inset -1px -1px #522139;
}

/* Motif's etched-in line, pulled out to the client's edges. */
[data-os="solaris8"] .actions {
  margin: 0 -14px; padding: 14px 14px 0;
  border-top: 1px solid #5a636b;
  box-shadow: inset 0 1px #dedee7;
}
[data-os="solaris8"] .btn {
  background: #adb5c6; color: #000;
  box-shadow: inset 1px 1px #dedee7, inset -1px -1px #5a636b;
}
[data-os="solaris8"] .btn:active {
  box-shadow: inset 1px 1px #5a636b, inset -1px -1px #dedee7;
}
/* The location cursor: a 1px sunken ring two pixels clear of the button. The
   #adb5c6 layer is listed first so it paints over the two ring layers inside
   that gap, leaving each of them showing on one pair of sides only. */
[data-os="solaris8"] .btn:focus-visible {
  outline: 0;
  box-shadow:
    inset 1px 1px #dedee7, inset -1px -1px #5a636b,
    0 0 0 2px #adb5c6,
    -1px -1px 0 2px #5a636b,
     1px 1px 0 2px #dedee7;
}

/* ================== SKIN — QNX 4.0 Photon (1990) =======================
   Rebuilt 2026-09-06 from Hami's 8x of the Extension De Installer window and
   his 8x of a Font field. Both resample with purity 1.000 at 8x, and the big
   one holds SIX colours over 96,390 pixels and nothing else:

     face    #c6c6c6  78.9%      caption #007b6b   5.8%
     shadow  #8c8c8c   5.4%      deep    #5a5a5a   4.2%
     ink     #000000   3.3%      lit     #ffffff   2.5%

   The old block had this skin in the face grey with the title centred on it and
   1px bevels throughout. Photon is nothing like that: the caption is a slab of
   teal with three shaded round buttons on it, the frame is a 4px bar, and every
   bevel in the work area is TWO pixels.

   FRAME    a 4px #8c8c8c bar, lit by a 1px face highlight on its outer top and
            left and shadowed by a 1px #5a5a5a on the far side of the bar —
            which lands INSIDE the bar at the top and left and OUTSIDE it at
            the bottom and right, so one rule covers all four sides.

   CAPTION  20 rows of #007b6b with a 1px #5a5a5a rule under it, inset a pixel
            from the work area, black bold title centred. The three buttons are
            18x18 and 1px down from the top of the slab, the menu button 2px in
            from the left and the pair 1px in from the right with 2px between.

   BUTTONS  2px of white on the top and left, 2px of #5a5a5a on the bottom and
            right, no outer ring at all. Cancel is 65x30 and its label is dead
            centre — 6 rows of face above the ink and 6 below.

   WELLS    the list box is a GROOVE: 2px #5a5a5a then 2px #ffffff going in on
            the top and left, and the same two reversed on the bottom and right.
            The Font field is the simple half of that, one 2px sunken bevel, and
            Hami's call is that the progress bar is the field rather than the
            list, so that is what .track is.

   Two more 8x captures, of the caption's two ends, then settled three things
   the first pair could not. They are 16-bit rather than 8-bit — 20 colours,
   with the greys carrying a slight green deficit (#949294 where it means
   #949494, #5a5d5a for #5a5a5a); red and blue agree on the value in every one
   of them, so neutralising is arithmetic rather than taste.

     * the DESKTOP is in shot at last, and it is #5a5a5a. That had been a
       guess off the palette; it is now measured.
     * the frame bar is #949494, not the #8c8c8c the 8-bit capture reads. Both
       are real Photon, Hami's call is the newer pair.
     * the right of the caption carries a 1px #5a5a5a edge as well as the
       bottom, and the two buttons on it — minimise and close — sit 5px apart,
       not the 2px everything else in the caption uses. (The capture has a help
       button before them at 2px; Hami's call is to drop it.)

   Only the #10b584 of the fill is still off the older 640x480
   qnxdemocontrols.png; none of the four captures has a progress bar in it. */

[data-os="qnx4"] {
  --font: "PhotonHelv", "Helv", Helvetica, Arial, sans-serif;
  --font-bold: "PhotonHelvBold", "PhotonHelv", Helvetica, Arial, sans-serif;
  --font-btn: "PhotonHelvBtn", "PhotonHelvBold", Helvetica, Arial, sans-serif;
  --fsize: 13px; --lh: 17px;
  --dlg-w: 358px;
  --face: #c6c6c6; --text: #000;
  --title-h: 21px; --title-fg: #000; --title-fsize: 14px;
  --pad: 8px; --gap: 6px;
  --bar-h: 19px; --btn-h: 23px; --btn-w: 93px;
  --notice-fg: #fff;
}
[data-os="qnx4"] .screen  { background: #5a5a5a; }

/* Hami's three slices read, outside in: #c6c6c6 highlight, four of #949494,
   one of #5a5a5a, one of #c6c6c6, then the caption — and coming back out on
   the right, #5a5a5a, #c6c6c6, four of #949494, #5a5a5a.

   So the padding is TWO on the top and left, not one: the inset shadow paints
   the first of them and the row of face is the second. With one, the shadow
   covered the face and the caption sat straight on the dark line — which is
   what the vertical slice caught. There is no padding on the other two sides;
   the work area runs up to the bar there, which is where the shadow is not. */
[data-os="qnx4"] .dialog {
  border: 4px solid #949494;
  padding: 2px 0 0 2px;
  background: #c6c6c6;
  box-shadow: inset 1px 1px 0 #5a5a5a,
              1px 1px 0 #5a5a5a,
              -1px -1px 0 #c6c6c6;
}

/* The resize grip. Three grooves cut into the bottom border and three into the
   right, each one a column of #5a5a5a with a column of #c6c6c6 beside it, at a
   pitch of 3 — and they run the whole depth of the border, a pixel up into the
   work area at one end and through the offset shadow at the other. Both sets
   are anchored to the corner: the last groove's dark line sits 14px in from the
   outer edge and they step away from it in threes.

   The third column of each groove is left TRANSPARENT rather than painted,
   which is what makes one gradient do the whole depth: behind it is the work
   area's face for that first row, the #949494 bar for the four after it, and
   the shadow for the last — exactly what the capture has in that column.

   Measured off the Extension De Installer window, whose grooves land at columns
   335/338/341 against a border box ending at 355, and confirmed by Hami's 8x of
   the corner: 15 from the outer edge in both. */
[data-os="qnx4"] .dialog { position: relative; }
[data-os="qnx4"] .dialog::before,
[data-os="qnx4"] .dialog::after {
  content: ""; position: absolute;
}
[data-os="qnx4"] .dialog::before {          /* the bottom border's three */
  right: 9px; bottom: -5px; width: 8px; height: 6px;
  background: repeating-linear-gradient(to right,
    #5a5a5a 0 1px, #c6c6c6 1px 2px, transparent 2px 3px);
}
[data-os="qnx4"] .dialog::after {           /* and the right border's */
  right: -5px; bottom: 9px; width: 6px; height: 8px;
  background: repeating-linear-gradient(to bottom,
    #5a5a5a 0 1px, #c6c6c6 1px 2px, transparent 2px 3px);
}

[data-os="qnx4"] .titlebar {
  margin: 0 1px 0 0;
  padding: 0 1px 0 2px;
  border-right: 1px solid #5a5a5a;
  border-bottom: 1px solid #5a5a5a;
  background: #007b6b;
  font-family: var(--font-bold);
}
[data-os="qnx4"] .tb-l { gap: 2px; align-self: flex-start; }
/* Minimise and close are 5px apart in the capture, the one gap in the caption
   that is not the default 2. */
[data-os="qnx4"] .tb-r { gap: 5px; align-self: flex-start; }
/* The caption centres in the space the two button groups leave, so whenever
   its width and that space disagree in parity it lands on a half pixel — two
   grey columns per stem in a face that has no grey. This is checked after any
   change to the bold face, because it moves with the type: giving 'm' the
   sidebearings the harvested letters use took a column off the title and
   needed a pixel of padding here; deriving 'v' from 'y' put the column back
   and the padding had to go again. At 136px in 284px it is even, so no nudge. */
[data-os="qnx4"] .tb-c { justify-content: center; }
[data-os="qnx4"] .title { line-height: 20px; }

/* The three caption buttons, lifted whole from the close-ups: shaded spheres
   in eighteen greys, hard-edged, with the teal knocked out so they sit on the
   slab. Drawing these by hand would only ever approximate them. One 54x18
   strip, one 18px cell each — menu, minimise, close. */
[data-os="qnx4"] .w-close, [data-os="qnx4"] .w-a, [data-os="qnx4"] .w-b {
  display: block; flex: none;
  width: 18px; height: 18px; margin-top: 1px;
  background: url("../img/qnx4-caption.png") 0 0 no-repeat;
}
[data-os="qnx4"] .w-a { background-position: -18px 0; }
[data-os="qnx4"] .w-b { background-position: -36px 0; }

/* Hami's crop of a button's bottom right corner measured 4 rows of face below
   its bevel and 5 columns right of it, and his call is half as much again: 6
   and 8. The gap between children is that same 6, so the work area is evenly
   spaced top to bottom — 6 above the message, 6 under it, 6 under the bar, 6
   under the button.
   The one number nothing measures is the progress bar's height, so it carries
   the parity: 19 rather than 18 makes the dialog an EVEN 118 rows, and an odd
   one centres on a half pixel and softens every 1px rule in the frame. */
[data-os="qnx4"] .content { padding: 6px 8px; background: #c6c6c6; }
/* The message line is the small bold — the one Netscape's group-box labels and
   tab captions are set in, cap 8, the same face the buttons use and the same
   size as the body text beside it. 12px is the strike's own cell, so it sits
   1:1 and stays hard-edged under the page's integer zoom. */
[data-os="qnx4"] .message { font-family: var(--font-btn); font-size: 12px; line-height: 17px; }
/* 16 is the blurb's own line pitch — its three lines start on rows 4, 20 and
   36 — and whole-pixel leading matters besides: 1.4 of 13px is 18.2, and a
   fractional notice makes a fractional stage, which centres the dialog on a
   half pixel and softens every 1px rule in the frame. */
[data-os="qnx4"] .notice { line-height: 16px; }

/* The Font field's bevel: 2px of #5a5a5a on the top and left, 2px of white on
   the bottom and right, and the face showing through where the fill has not
   reached. */
[data-os="qnx4"] .track {
  height: 19px; padding: 2px;
  border: 0;
  background: #c6c6c6;
  box-shadow: inset 2px 2px 0 #5a5a5a, inset -2px -2px 0 #fff;
}
[data-os="qnx4"] .fill { background: #10b584; }

/* 93x23 with the label dead centre — 5 rows of face above the ink and 5 below
   — measured off Hami's Exit button. The bevel MITRES rather than butting
   square: the white top row runs the full width and the row under it stops a
   pixel short, so the highlight owns a 45-degree wedge at the top right and
   bottom left. Four box-shadows cannot do that, so it is a border-image, from
   build/qnx4-bevel.py. */
[data-os="qnx4"] .btn {
  padding: 0 10px;
  border: 2px solid transparent;
  border-image: url("../img/qnx4-btn.png") 2 repeat;
  border-radius: 0;
  background: #c6c6c6; color: #000;
  font-family: var(--font-btn);
  font-size: 12px;
}
[data-os="qnx4"] .btn:active { border-image: url("../img/qnx4-btn-down.png") 2 repeat; }

/* Photon underlines the accelerator letter, and draws the mark ENGRAVED — a
   white row over a #5a5a5a one, a pixel wider than the letter's ink and two
   rows below it. Hami's 32x of a Cancel button has it under the C: the C's ink
   is 7 columns and the mark is 8, and there is one clear row between the two. */
[data-os="qnx4"] .btn .mn {
  position: relative;
}
[data-os="qnx4"] .btn .mn::after {
  content: ""; position: absolute;
  left: 0; right: 1px; top: 11px; height: 2px;
  background: linear-gradient(#fff 0 1px, #5a5a5a 1px 2px);
}
[data-os="qnx4"] .btn:focus-visible {
  outline: 1px dotted #000; outline-offset: -5px;
}


/* ============== SKIN — Xerox GlobalView 2 (1996) ========================
   Rebuilt 2026-09-06 from Hami's Logoff Option Sheet capture, a clean 4x of a
   450x250 window — 100% of sampled 4x4 blocks flat, and one bit deep: white,
   black, and #808080 for the desktop, nothing else. A second capture (Icon
   Properties) is a lossy resample, so it was read for structure and
   letterforms only. Everything measured below is off the first.

   The old block had a flat #bfbfbf header, a navy progress bar and rounded
   grey buttons, none of which GlobalView has anywhere.

   FRAME     1px black, with the bottom and right a pixel or two heavier —
             rows 247-249 and columns 448-449 of a 250x450 window. A 1px border
             and a 1px/2px hard shadow puts that back.
   HEADER    25 rows: a 1px rule, 23 rows of 50% checkerboard, a 1px rule. The
             checker is the whole character of a Star-lineage window and is
             what the old #bfbfbf flat got most wrong.
   TITLE     not loose on the band — in a white box with a 1px black border and
             its four corner pixels cut, 19 rows tall, 16px in from the frame.
   COMMANDS  GlobalView hangs a window's commands off the RIGHT of the header,
             not the bottom of the body, so Cancel is lifted out of .actions
             and parked there. A rounded box over a hard two-pixel shadow,
             generated by build/gv-widget.py rather than lifted, so Cancel and
             the three chrome buttons that follow it are one shape at one size
             with mirrored corners. The capture's own corners are not
             symmetric — two rows of round on the left against one on the
             right, plus a stray pixel over the shadow's top right — and
             regularising them was Hami's call.
   SCROLLBARS every GlobalView window has them, down the right and along the
             bottom, and they are most of what the silhouette is. The four ends
             are lifted (img/gv-vs-top/bot, gv-hs-left/right) with their rules,
             arrows, plus and minus marks and dithered corner blocks; the
             stretch between them is plain white.
   FONT      Xerox's own Modern, which no free recreation of exists. DejaVu
             Sans at 11ppem is the closest of the faces to hand and a good one:
             cap height 8 against the capture's 8, "Logoff Option Sheet" 112px
             against 111 and "RETURN TO LOGON" 107 against 107. Shipped as its
             own hinted 1-bit strike (build/ttf-strike.py, then prop-font.py at
             12 rows / 9), because GlobalView drew type one bit deep and a
             smoothed outline is the wrong texture whatever the shapes.       */

[data-os="gv2"] {
  --font: "GVSans", "DejaVu Sans", Verdana, sans-serif;
  --fsize: 12px; --lh: 17px;
  --dlg-w: 340px;
  --face: #fff; --text: #000;
  --title-h: 24px; --title-fg: #000;
  --pad: 16px; --gap: 16px;
  /* 48 is the capture's own command: a 46px face and its 2px shadow. It also
     leaves the content box exactly as wide as "Cancel", so text-align centring
     has nothing to halve — a stem on a half pixel is two grey columns on a skin
     drawn one bit deep. */
  --bar-h: 19px; --btn-h: 19px; --btn-w: 48px;
  --notice-fg: #fff;
}
[data-os="gv2"] .screen  { background: #808080; }
/* .notice's 1.4 line-height is 16.8px at 12, which makes the stage a fraction
   of a pixel tall, which puts the centred window on a half pixel and softens
   every hard edge on it. A whole number puts it back on the grid. */
[data-os="gv2"] .notice  { line-height: 17px; }
[data-os="gv2"] .dialog {
  position: relative;
  border: 1px solid #000;
  background: #fff;
  box-shadow: 1px 2px 0 #000;
}
/* The two scrollbars. The horizontal one runs the full width so its lifted
   ends carry the dithered corner blocks, and the vertical one stops short of
   it, which is the order the capture has. */
[data-os="gv2"] .dialog::before {
  content: ""; position: absolute; z-index: 1;
  left: -1px; right: -1px; bottom: -1px; height: 10px;
  border-top: 1px solid #000;
  background:
    url("../img/gv-hs-left.png")  left bottom  no-repeat,
    url("../img/gv-hs-right.png") right bottom no-repeat,
    #fff;
}
[data-os="gv2"] .dialog::after {
  content: ""; position: absolute; z-index: 1;
  right: -1px; top: 24px; bottom: 9px; width: 11px;
  border-left: 1px solid #000;
  background:
    url("../img/gv-vs-top.png") right top    no-repeat,
    url("../img/gv-vs-bot.png") right bottom no-repeat,
    #fff;
}
[data-os="gv2"] .titlebar {
  position: relative;
  padding: 0;
  border-bottom: 1px solid #000;
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2'%3E%3Cpath d='M1 0h1v1H1zM0 1h1v1H0z'/%3E%3C/svg%3E");
  background-size: 2px 2px;
  overflow: visible;
}
/* The corner squares, tucked into the two top corners of the band: ten pixels
   of the same dither, ruled off on the inner side and bottom, the window frame
   closing the other two. What looked like a phase break in the checker on the
   first pass is these. */
[data-os="gv2"] .tb-l {
  align-self: flex-start;
  width: 10px; height: 10px;
  margin-right: 6px;
  border-right: 1px solid #000;
  border-bottom: 1px solid #000;
}
[data-os="gv2"] .titlebar::after {
  content: ""; position: absolute; right: 0; top: 0;
  width: 10px; height: 10px;
  border-left: 1px solid #000;
  border-bottom: 1px solid #000;
}
[data-os="gv2"] .tb-c  { justify-content: flex-start; }
/* The window's own three chrome buttons. Not lifted whole: the capture draws
   them a pixel apart in width and pitch, and keying the dither out of a lift
   claimed a ring of it around every edge. These are the SAME widget the Cancel
   button is built from — same 17-row face, same two-pixel shadow, same corners
   — with only the capture's ink copied onto each, so the three agree with the
   text button and with each other. 18px faces on a 22px pitch: three elements
   and two 2px gaps is 64. Nothing but the widget is in the file, so the band's
   dither runs through it wherever it lands. */
[data-os="gv2"] .tb-r {
  align-self: flex-start;
  width: 64px; height: 19px; margin: 2px 16px 0 6px;
  background: url("../img/gv-icons.png") no-repeat;
}
[data-os="gv2"] .w  { display: none; }

/* A Star-lineage box. The corner is a 2px round: the rule stops a pixel short,
   one pixel bridges the diagonal, and the side rule starts two rows down.
   border-radius would antialias that into grey on a skin that has no grey, so
   these are border-image sources instead — every edge a solid stretched
   rectangle, so every edge stays hard.

   The title's box is outlined and 19 rows tall (7x7, sliced 3). A command
   button is not outlined, is 17 rows tall, and carries a hard black shadow two
   pixels down and right — 11x11, sliced 5, the box drawn twice. */
[data-os="gv2"] .title {
  height: 19px; line-height: 14px;
  border: 3px solid transparent;
  padding: 0 2px;
  color: #000;
  background: none;
  text-align: center;
  border-image: url("../img/gv-box.png") 3 fill / 3px stretch;
}
/* GlobalView hangs a window's commands off the RIGHT of the header rather than
   the bottom of the body, so Cancel is lifted out of .actions and parked there,
   ahead of the chrome buttons. */
[data-os="gv2"] .actions {
  position: absolute; top: 2px; right: 82px; margin: 0;   /* 16 + 64 + a 2px gap */
}
/* border-image-width is pinned at the slice, so the frame draws 1:1 whatever
   the border-widths are; the widths are therefore free to place the content box
   instead. 3 top and 4 bottom makes it 12 tall, the same as the line box, so
   there is no half-leading, and sets where the label sits in the face. 3 and 5
   across, with 1px padding, leaves 38 — the exact
   advance of "Cancel" — so nothing lands on a half pixel in either axis. */
[data-os="gv2"] .btn {
  height: 19px; line-height: 12px;
  border: 3px solid transparent;
  border-width: 3px 5px 4px 3px;
  padding: 0 1px;
  color: #000;
  background: none;
  text-align: center;
  border-image: url("../img/gv-cmd.png") 5 fill / 5px stretch;
}
/* Pressed. Neither capture contains one: the filled "Start" in the Logoff
   Option Sheet is that sheet's DEFAULT command, drawn reversed the way
   ViewPoint reverses a chosen item, and it sits on the same rows as the
   unpressed Cancel beside it. So this is reasoned rather than measured, and
   the reasoning is the shadow: a hard offset shadow exists to say the face is
   standing proud, so pressing it puts it down. The face moves the two pixels
   into the shadow's place and nothing is left behind it — which is the same
   rectangle translated, so the source is the rest state's box drawn at the
   shadow's offset. Swapping the border widths carries the label with it. */
[data-os="gv2"] .btn:active,
[data-os="gv2"] .btn:focus-visible {
  outline: 0;
  border-width: 5px 3px 2px 5px;      /* the rest state, moved 2 down and right */
  border-image: url("../img/gv-cmd-down.png") 5 fill / 5px stretch;
}
[data-os="gv2"] .content {
  background: #fff;
  padding: 18px 27px 22px 18px;
}
/* GlobalView has no progress bar. This is its value box — a 1px black frame
   with the fill inset a pixel, which is how the capture draws a chosen cell in
   a choice strip. */
[data-os="gv2"] .track {
  height: 19px; border: 1px solid #000; padding: 1px; background: #fff;
}
[data-os="gv2"] .fill  { background: #000; }


/* ================== SKIN — Microsoft Bob (1995) =========================
   Bob has no dialogues. It has Rover, and Rover has a speech balloon, so that
   is what this is — the one skin in the set that is a shape rather than a
   window, at Hami's suggestion.

   Rebuilt from Hami's two captures, both clean 4x nearest of a 256-colour
   screen — every run length a multiple of four, 100% of sampled 4x4 blocks
   flat — so the 1:1 underneath them is exact, and the palette is web-safe.

   Paper:    NOT white. #ffffcc woven with #ffffff on a 4x4 tile:

                 . # . #        # = #ffffff
                 # # # .        . = #ffffcc
                 . # . #
                 # . # #

             img/bob-hatch.png is that tile. The balloon and the widgets all
             sit on it. Outline 2px #000, radius 15px, no drop shadow.
   Font:     Times New Roman, which is the joke — Vincent Connare saw Rover
             speaking in it and drew Comic Sans, which missed the ship date.
             Measured off the captures: the headline is bold at 13px, the body
             regular at 11px, and the option rows and Cancel regular at 13px.
             Liberation Serif is metric-compatible with Times and was the check
             — at 11ppem "To see the programs in this" comes out 127px against
             the capture's 126, "room, hold down the F1 key." 133 against 133,
             and bold at 13ppem "just click on it." 82 against 82. The three
             faces here are its own hinted 1-bit strikes at those two sizes,
             via build/ttf-strike.py and build/prop-font.py, so the page gets
             the whole character set rather than the letters Rover happened to
             use, and gets it as bitmaps rather than smoothed outlines.
   Widgets:  one construction for all of them — reading outward from the face,
             a gold #ffcc33 rim lit #ffffff at the top left and shaded #ff9999
             at the bottom right, then #000, #ccccff, #000. Cancel is that as a
             stadium, the option bullet as a circle, and the reference carries
             a magenta X on the button, lifted here as img/bob-x.png.
   Room:     the backdrop is the dominant #ce6331 of the native 640x480
             bobhome1p.png; reproducing the illustration is not on.          */

[data-os="bob"] {
  --font: "BobSerif", "Times New Roman", serif;
  --fsize: 11px; --lh: 14px;
  --dlg-w: 300px;
  --face: #ffffcc; --text: #000;
  --title-h: 0px; --title-fsize: 13px;
  --pad: 16px; --gap: 14px;
  --bar-h: 14px; --btn-h: 22px; --btn-w: 102px;
  --notice-fg: #ffffcc;
}
[data-os="bob"] .screen  { background: #ce6331; }
[data-os="bob"] .dialog {
  position: relative;
  background: url("../img/bob-hatch.png") repeat;
  background-size: 4px 4px;
  border: 2px solid #000;
  border-radius: 15px;
  box-shadow: none;
}
/* The tail is a long thin spike down and to the right, not the rotated square
   this used to draw. Measured off the 8x capture, in pixels from the balloon's
   bottom left corner: the mouth breaks the bottom border between 26 and 43,
   the left edge falls at 4 across for every 3 down and the right edge at 4 for
   every 9, and they meet at a tip 51 along and 19 below.

   Neither line stops at the border. Both carry two pixels past it into the
   paper — the capture has a stub at 21 and another at 41, four rows above the
   balloon's bottom edge — so the tail reads as drawn through the balloon
   rather than hung off it, and the black outline starts four rows up to get
   them. Two clipped boxes: that outline, and the paper inside it, which starts
   higher still so it covers everything between the two stubs.

   Both are laid out against the padding box, which is 2px inside the border,
   so every offset below has that taken back out of it. The left offset stays a
   multiple of four so the paper's weave keeps step with the balloon's. */
[data-os="bob"] .dialog::before,
[data-os="bob"] .dialog::after {
  content: ""; position: absolute; left: 16px; bottom: -22px; width: 35px;
}
[data-os="bob"] .dialog::before {
  height: 24px;
  background: #000;
  clip-path: polygon(2px 0, 24px 0, 25px 4px, 34px 24px);
}
[data-os="bob"] .dialog::after {
  height: 26px;
  background: url("../img/bob-hatch.png") repeat;
  background-size: 4px 4px;
  clip-path: polygon(2px 0, 21px 0, 28px 19px);
}
[data-os="bob"] .titlebar {
  height: auto; padding: 14px 16px 0; background: none; color: #000;
  font-family: "BobSerifL", "Times New Roman", serif;
  font-weight: bold; line-height: 16px; overflow: visible;
}
[data-os="bob"] .tb-c  { justify-content: flex-start; }
[data-os="bob"] .content  { padding: 8px 16px 16px; background: none; }
/* Bob never showed a progress bar. This is the widget construction above, run
   out into a tube, which is the only honest way to invent one for it. */
[data-os="bob"] .track {
  height: 14px; border: 0; border-radius: 7px; margin: 3px 3px 0;
  background: url("../img/bob-hatch.png") repeat;
  background-size: 4px 4px;
  box-shadow: 0 0 0 1px #000, 0 0 0 2px #ccccff, 0 0 0 3px #000;
}
[data-os="bob"] .fill {
  border-radius: 7px;
  background: linear-gradient(180deg,
    #ffcc00 0 3px, #ffff99 3px 6px, #ffcc00 6px 12px, #ff9999 12px 14px);
}
[data-os="bob"] .actions  { justify-content: flex-end; }
/* .notice's 1.4 line-height is 15.4px at 11, which makes the stage a fraction
   of a pixel tall, which makes the centred balloon land on a half pixel, which
   antialiases the caps of every pill on it. A whole number puts it back on the
   grid. */
[data-os="bob"] .notice  { line-height: 15px; }
[data-os="bob"] .btn {
  /* The 8x capture settles this one to the pixel. The whole widget is 102x22
     and the two caps are true half-circles, so they are lifted rather than
     drawn: img/bob-btn-l.png and -r.png are the real 11x22 ends, and the 22px
     column between them — black, #ccccff, black, #ffcc33, #ffffff, thirteen of
     #ffff99, #ffcc33, black, #ccccff, black — is a gradient inset by a cap at
     each side. CSS can round a rectangle but it antialiases the curve, and at
     3x that reads as grey fuzz on a face with no grey in it.

     The X sits on the label's baseline rather than the widget's centre line:
     nine rows deep with its foot on the baseline, so it is pinned seven rows
     down, and the label gets to the same row with leading off, its line box at
     the top and six pixels of padding above it. Across: the label runs from
     column 26 to 61 and the X from 80 to 92, which is what the lopsided
     padding and the 9px right offset put them at. */
  display: flex; align-items: flex-start; justify-content: center;
  height: 22px; border: 0; border-radius: 0;
  padding: 6px 33px 0 19px;
  font-family: "BobSerifL", "Times New Roman", serif;
  font-size: 13px; line-height: 13px;
  color: #000;
  background:
    url("../img/bob-btn-l.png") left top no-repeat,
    url("../img/bob-btn-r.png") right top no-repeat,
    url("../img/bob-x.png") no-repeat right 9px top 7px,
    linear-gradient(180deg,
      #000000 0 1px, #ccccff 1px 2px, #000000 2px 3px,
      #ffcc33 3px 4px, #ffffff 4px 5px, #ffff99 5px 18px,
      #ffcc33 18px 19px, #000000 19px 20px, #ccccff 20px 21px, #000000 21px 22px)
      11px 0 / calc(100% - 22px) 100% no-repeat;
  box-shadow: none;
}
/* Pressed: the rim's light flips end for end, which is the one part of this
   the capture cannot show — Bob's buttons are only ever caught at rest. */
[data-os="bob"] .btn:active,
[data-os="bob"] .btn:focus-visible {
  outline: 0;
  background:
    url("../img/bob-btn-l.png") left top no-repeat,
    url("../img/bob-btn-r.png") right top no-repeat,
    url("../img/bob-x.png") no-repeat right 9px top 7px,
    linear-gradient(180deg,
      #000000 0 1px, #ccccff 1px 2px, #000000 2px 3px,
      #ffcc33 3px 4px, #ff9999 4px 5px, #ffcc33 5px 18px,
      #ffffff 18px 19px, #000000 19px 20px, #ccccff 20px 21px, #000000 21px 22px)
      11px 0 / calc(100% - 22px) 100% no-repeat;
}


/* ============= SKIN — GEOS 2.1, Apple II (1988) =========================
   Measured from about.gif and the other a2geos captures: one bit deep, white
   and black, nothing else. The desktop is a 50%% dither, which at this scale
   reads as the grey it was meant to.

   GEOS dialogues carry no caption, so this uses the window chrome: a 2px black
   border, a striped caption with the title in a punched-out gap, and a hard
   offset drop shadow, which GEOS drew on everything.

   Font is a stand-in. GEOS's BSW face has not been harvested, and it is the
   one substitution in this set that shows — BSW is chunkier than Geneva.  */

[data-os="geosa2"] {
  --font: "Geneva", Verdana, sans-serif;
  --fsize: 12px; --lh: 1.3;
  --dlg-w: 300px;
  --face: #fff; --text: #000;
  --title-h: 16px; --title-fg: #000;
  --pad: 14px; --gap: 14px;
  --bar-h: 12px; --btn-h: 22px; --btn-w: 74px;
  --notice-fg: #000;
}
[data-os="geosa2"] .screen {
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2'%3E%3Cpath d='M0 0h1v1H0zM1 1h1v1H1z'/%3E%3C/svg%3E");
  background-size: var(--dither) var(--dither);
}
[data-os="geosa2"] .dialog {
  border: 2px solid #000; background: #fff;
  box-shadow: 4px 4px 0 #000;
}
[data-os="geosa2"] .titlebar {
  padding: 0;
  border-bottom: 2px solid #000;
  background-color: #fff;
  background-image: repeating-linear-gradient(180deg, #000 0 1px, #fff 1px 3px);
  background-size: 100% 12px; background-position: 0 2px;
  background-repeat: no-repeat;
  overflow: visible;
}
[data-os="geosa2"] .tb-c  { justify-content: center; overflow: visible; }
[data-os="geosa2"] .title  { background: #fff; padding: 0 6px; font-weight: bold; }
[data-os="geosa2"] .content  { background: #fff; }
[data-os="geosa2"] .track  { height: 12px; border: 2px solid #000; background: #fff; }
[data-os="geosa2"] .fill  { background: #000; }
[data-os="geosa2"] .btn  { background: #fff; border: 2px solid #000; border-radius: 8px; }
[data-os="geosa2"] .btn:active  { background: #000; color: #fff; }


/* ============= SKIN — GEOS 1.0, Commodore 64 (1985) =====================
   The same GUI, in colour. Measured from c64gabout.gif, which is a clean 2x of
   the native 320x200 — every column pair and every row pair identical, 3422 of
   3422 sampled — so the three colours below are exact: #c0c0c0 for the paper,
   #545454 for the ink and frame, #4040e0 for the C64's blue.

   Same chrome as the Apple II skin above, which is the point: GEOS looked the
   same on both machines, and only the palette gives away which one you were
   sitting at. Font is the same stand-in and the same caveat.              */

[data-os="geosc64"] {
  --font: "Geneva", Verdana, sans-serif;
  --fsize: 12px; --lh: 1.3;
  --dlg-w: 300px;
  --face: #c0c0c0; --text: #545454;
  --title-h: 16px; --title-fg: #545454;
  --pad: 14px; --gap: 14px;
  --bar-h: 12px; --btn-h: 22px; --btn-w: 74px;
  --notice-fg: #c0c0c0;
}
[data-os="geosc64"] .screen  { background: #4040e0; }
[data-os="geosc64"] .dialog {
  border: 2px solid #545454; background: #c0c0c0;
  box-shadow: 4px 4px 0 #545454;
}
[data-os="geosc64"] .titlebar {
  padding: 0;
  border-bottom: 2px solid #545454;
  background-color: #c0c0c0;
  background-image: repeating-linear-gradient(180deg, #545454 0 1px, #c0c0c0 1px 3px);
  background-size: 100% 12px; background-position: 0 2px;
  background-repeat: no-repeat;
  overflow: visible;
}
[data-os="geosc64"] .tb-c  { justify-content: center; overflow: visible; }
[data-os="geosc64"] .title  { background: #c0c0c0; padding: 0 6px; font-weight: bold; }
[data-os="geosc64"] .content  { background: #c0c0c0; }
[data-os="geosc64"] .track  { height: 12px; border: 2px solid #545454; background: #c0c0c0; }
[data-os="geosc64"] .fill  { background: #545454; }
[data-os="geosc64"] .btn  { background: #c0c0c0; border: 2px solid #545454; border-radius: 8px; }
[data-os="geosc64"] .btn:active  { background: #545454; color: #c0c0c0; }


/* ============== SKIN — Apple II Desktop (1986) ==========================
   Measured from three captures of the real thing, each recovered at native
   560x192 and purity 1.000: the DeskTop with two windows open, the Copy
   progress dialog, and the Selector. One bit deep — black and white and
   nothing else anywhere in any of them.

   THE PIXELS ARE NOT SQUARE, and it is the whole reason this block looks the
   way it does. Double hi-res is 560x192 in a 4:3 frame, so one pixel is a
   little over twice as tall as it is wide, and Apple drew the interface to
   suit: every vertical rule in a window frame is TWO pixels wide where every
   horizontal one is a single pixel, and on a real screen the two read as the
   same weight. The captures came back 4x across and 8x down — that aspect
   already applied — which is what makes 4x8 the recovery that works.

   So this skin is authored at 560 across and 384 down: horizontal
   measurements are the capture's, vertical ones are doubled. Every rule below
   is 2px because one scanline is 2px here, and the frame's 1px sides are
   genuinely thinner than its 2px top and bottom, exactly as measured.

   Frame, outside in:  1px rule (2px top and bottom), 4px of white, then a
                       2px rule (2px top and bottom). Identical on the Copy
                       and Selector dialogs, measured to the pixel on both.
   Title bar:          13 scanlines — a rule, five striped lines every other
                       scanline, a rule. The title sits in a punched-out gap
                       in the stripes and the close box in another.
   Close box:          15 x 9 scanlines, outline only, 11px in from the frame
                       with a 2px white gutter each side of it.
   Buttons:            12 scanlines tall with 2px walls, and the top and
                       bottom rules stop 2px short of them — the corners are
                       cut rather than rounded. The label starts 9px in.
   Desktop:            a 50%% dither, one pixel on and one off, which is 1x2
                       here for the same reason as everything else.          */

[data-os="a2desk"] {
  /* The face is lifted whole off the three captures — 45 characters at zero
     spacing residual over 160 equations; see build/a2-harvest.py. Its rows
     are doubled in the font itself, so it sits 1:1 at 16px like every other
     bitmap face here rather than needing a transform. */
  --font: "A2Sys", "Geneva", Verdana, sans-serif;
  --fsize: 16px; --lh: 16px;
  --dlg-w: 340px;
  --face: #fff; --text: #000;
  --title-h: 26px; --title-fg: #000;
  --pad: 16px; --gap: 16px;
  --bar-h: 16px; --btn-h: 24px; --btn-w: 102px;
  --notice-fg: #000;
}
/* One pixel on, one off — 1 wide and 2 tall, which is square on the screen
   this came off. */
[data-os="a2desk"] .screen {
  background-color: #fff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='4'%3E%3Cpath d='M0 0h1v2H0zM1 2h1v2H1z'/%3E%3C/svg%3E");
  background-size: 2px 4px;
}
/* The inner rule is the border; the white gap and the outer rule are drawn
   outside it. ::before rather than an outline because the outer rule is 1px
   at the sides and 2px top and bottom, and an outline is one width all
   round. -6px/-5px puts each edge exactly 4px clear of the border box. */
[data-os="a2desk"] .dialog {
  position: relative;
  /* the outer rule is drawn OUTSIDE this box, so the margin is what keeps it
     inside .stage — without it the stage's bounds clip the frame away */
  margin: 6px 5px;
  border: 2px solid #000;
  background: #fff;
  box-shadow: 0 0 0 4px #fff;
}
[data-os="a2desk"] .dialog::before {
  content: ""; position: absolute; inset: -6px -5px; pointer-events: none;
  border: 2px solid #000;
  border-left-width: 1px; border-right-width: 1px;
}
/* 2px rule, 22px of stripes, 2px rule. The stripes start on the first
   scanline after the top rule and land on every other one after that. */
[data-os="a2desk"] .titlebar {
  padding: 0;
  border-top: 2px solid #000;
  border-bottom: 2px solid #000;
  background-color: #fff;
  background-image: repeating-linear-gradient(180deg, #000 0 2px, #fff 2px 4px);
  background-position: 0 2px;
  background-size: 100% 20px;
  background-repeat: no-repeat;
  overflow: visible;
}
[data-os="a2desk"] .tb-l { align-self: center; padding-left: 11px; }
[data-os="a2desk"] .tb-c { justify-content: center; overflow: visible; }
/* The gap the title is punched into is the white behind it, not a margin —
   the stripes run underneath and the label paints over them. */
[data-os="a2desk"] .title { background: #fff; padding: 0 14px; }
[data-os="a2desk"] .w-close {
  display: block; width: 15px; height: 18px;
  border: 2px solid #000; border-left-width: 1px; border-right-width: 1px;
  background: #fff; box-shadow: 0 0 0 2px #fff;
  margin-right: 2px;
}
[data-os="a2desk"] .content { background: #fff; }
/* The progress well is the same two weights as everything else. No capture
   shows this control — the Copy dialog counts files instead of drawing a bar
   — so the box is the frame's own idiom and the fill is the desktop dither. */
[data-os="a2desk"] .track {
  height: 16px; background: #fff;
  border: 2px solid #000; border-left-width: 1px; border-right-width: 1px;
}
[data-os="a2desk"] .fill {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='4'%3E%3Cpath d='M0 0h1v2H0zM1 2h1v2H1z'/%3E%3C/svg%3E");
  background-size: 2px 4px;
}
/* A rule across the dialog, then the buttons 6px under it and 4px clear of
   the frame — the Selector's spacing, measured. */
[data-os="a2desk"] .actions {
  border-top: 2px solid #000;
  padding: 6px 0 4px;
  margin-top: 16px;
}
/* 2px walls, and the top and bottom rules inset 2px so the corner pixel is
   left out. border-image rather than border-radius: the corner is CUT, and
   asking the browser to round it would put a grey curve on a face that has
   no grey in it. */
[data-os="a2desk"] .btn {
  height: 24px; min-width: 0;
  padding: 0 9px;
  color: #000; background: #fff;
  /* a border-image needs a border-style to paint against; border:0 leaves the
     style at none and the whole thing silently does not draw */
  border: 2px solid transparent;
  border-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='9' shape-rendering='crispEdges'%3E%3Cpath fill='%23000' d='M2 0h5v2H2zM0 2h2v5H0zM7 2h2v5H7zM2 7h5v2H2z'/%3E%3C/svg%3E") 2 fill stretch;
}
[data-os="a2desk"] .btn:active { background: #000; color: #fff; }
[data-os="a2desk"] .notice { color: #000; }
/* Two plates, not one. Black type on a 50% dither is unreadable, so the
   address gets a white box punched behind it — but the OS name underneath is
   hidden until the dialog is double-clicked, and a single box around both
   left an empty white strip sitting under the address whenever it was. The
   link takes its own plate (it is inline, so the box hugs the words) and the
   name takes another, which appears and goes with it because opacity takes
   the background too. */
[data-os="a2desk"] .notice a,
[data-os="a2desk"] .osname {
  background: #fff;
  padding: 2px 8px;
}
[data-os="a2desk"] .osname { width: fit-content; margin-inline: auto; }
/* The plate has to stay WHITE when the name is showing. The reveal fades the
   whole element, background included, which turned the box into a grey panel
   sitting on the dither — so here the element goes fully opaque and the type
   carries the fade itself. Same grey as before on screen, an opaque box under
   it. */
[data-os="a2desk"][data-osname-shown] .osname { opacity: 1; }
[data-os="a2desk"] .osname { color: rgba(0, 0, 0, .5); }

