/* Windows 95 control chrome.
 *
 * This replaces the vendored 98.css. The two are close but not the same, and
 * the difference is visible: Windows 98 draws its inner light ring in #dfdfdf
 * and its dark shadow in #0a0a0a, where Windows 95 uses #c0c0c0 (invisible
 * against the face) and pure #000000.
 *
 * Every colour here was sampled off brain_dump/visuals/screenshots/1.2/
 * win95-st-startup.jpg -- a native Win16 task on Windows 95 OSR2, 1024x768 --
 * and they land exactly on the Windows 95 default scheme. A "Who?" button's
 * left edge reads #ffffff, face, face; its right edge reads face, #808080,
 * #000000. So the light bevel is one pixel and the dark bevel is two, which is
 * why the shadows below are asymmetric.
 */

@font-face {
  font-family: "Pixelated MS Sans Serif";
  font-weight: 400;
  src: url(ms_sans_serif.woff2) format("woff2"), url(ms_sans_serif.woff) format("woff");
}

@font-face {
  font-family: "Pixelated MS Sans Serif";
  font-weight: 700;
  src: url(ms_sans_serif_bold.woff2) format("woff2"), url(ms_sans_serif_bold.woff) format("woff");
}

/* MS Sans Serif was a bitmap font: Windows 95 had no antialiasing to give it,
   and the webfont above is a pixel-for-pixel copy of it. macOS smooths it
   anyway, which puts a grey fringe on 63% of the ink -- measured, on a plain
   string at 11px -- and is the single thing that most gives the rebuild away
   next to a capture of the original. With smoothing off the same string renders
   in 192 solid black pixels and no grey at all, which is what the bitmap was.

   It is not a scaling artefact: the fringe is there at 1x and 2x alike, and
   goes at both.

   Blink and WebKit only. Firefox has no equivalent property and will still
   antialias; there is no standard one to use instead. */
html {
  -webkit-font-smoothing: none;
}

:root {
  --face: #c0c0c0;
  --highlight: #fff;
  /* COLOR_3DLIGHT. Windows 95 defaults it to the face colour, so the inner
     light ring is there structurally but never visible. Kept named rather than
     folded away, because that is the whole difference from the Windows 98 look. */
  --light: #c0c0c0;
  --shadow: #808080;
  --dark: #000;
  --title: #000080;
  --title-inactive: #808080;
  --title-text: #fff;
  --desktop: #008080;
  --disabled: #808080;
  /* The rest of the scheme: what Display Properties' Appearance tab lets you
     change (js/components/schemes.js). Each is a GetSysColor index by another
     name; Windows Standard's values, the same ones the chrome above hardcoded
     before the schemes existed. */
  --title-text-inactive: #c0c0c0;
  --window: #fff;
  --window-text: #000;
  --hilight: #000080;
  --hilight-text: #fff;
  --menu: #c0c0c0;
  --menu-text: #000;
  --button-text: #000;
  --app-workspace: #808080;
  --scrollbar: #c0c0c0;
  --info: #ffffe1;
  --info-text: #000;
  /* VB3's &HFF&. The captures put its brightest pixel near (235, 80, 78), but
     both are JPEGs of a 256-colour guest and neither has a true stroke
     interior at this size; the Windows 95 palette has no such dark red. */
  --vb-red: #f00;
  --font: 11px "Pixelated MS Sans Serif", "MS Sans Serif", sans-serif;
}

/* --- bevels ---------------------------------------------------------------
 * Listed outermost first: box-shadow paints earlier shadows on top, so the 1px
 * rings must precede the 2px ones or they are overpainted.
 */

.w95-raised {
  box-shadow:
    inset -1px -1px 0 var(--dark),
    inset 1px 1px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow),
    inset 2px 2px 0 var(--light);
}

.w95-pressed {
  box-shadow:
    inset 1px 1px 0 var(--dark),
    inset -1px -1px 0 var(--highlight),
    inset 2px 2px 0 var(--shadow),
    inset -2px -2px 0 var(--light);
}

/* EDGE_SUNKEN: what text boxes and list boxes sit in. */
.w95-sunken {
  box-shadow:
    inset 1px 1px 0 var(--shadow),
    inset -1px -1px 0 var(--highlight),
    inset 2px 2px 0 var(--dark),
    inset -2px -2px 0 var(--face);
}

/* EDGE_ETCHED: group boxes. Reading down or right, every edge is #808080 then
   #ffffff -- which is what the capture shows on all four sides. */
.w95-etched {
  box-shadow:
    inset 1px 1px 0 var(--shadow),
    inset -1px -1px 0 var(--highlight),
    inset 2px 2px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow);
}

/* --- controls ------------------------------------------------------------- */

button,
.w95-button {
  box-sizing: border-box;
  /* The pressed shift is a border; see THE PRESSED SHIFT below. Declared here
     as transparent and zero-width so that rule only has to set its widths. */
  border: 0 solid transparent;
  border-radius: 0;
  padding: 0;
  background: var(--face);
  color: var(--button-text);
  font: 700 var(--font);
  text-align: center;
  cursor: default;
  user-select: none;
  box-shadow:
    inset -1px -1px 0 var(--dark),
    inset 1px 1px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow),
    inset 2px 2px 0 var(--light);
}

button:disabled,
.w95-button:disabled {
  color: var(--disabled);
  text-shadow: 1px 1px 0 var(--highlight);
}

/* THE PRESSED SHIFT. The label moves down and right with the face, as it does
   on the real thing -- shifted, not squeezed.

   It is a transparent border and not padding, and that is the whole point. Idle,
   every button carries that border on its bottom and right; pressed, the same
   one pixel moves to its top and left. The content box is the same size either
   way, so the box is too, whether the button is sized explicitly or by what is
   written on it -- and, the part that matters, the button's own padding is never
   touched.

   Padding is what this used to use, and because the four longhands are set
   outright it wiped whatever padding a control had declared for itself. A
   button whose width came from its content lost that padding mid-press and
   shrank out from under the pointer. The workaround was for every such control
   to restate its padding in an `:active` rule of its own -- .start-button and
   .task-button both carried one, Define Custom Voices' controls did not, and
   any control added later would have had to know to. Nothing has to know now.

   The rule for new controls: set padding freely, and do not write an `:active`
   padding rule. If a control must not shift at all, name it in the exclusion
   list below -- and it has to be here, not in a rule of the control's own,
   because this selector carries three pseudo-classes and outranks anything
   written as `.thing:active`.

   What is excluded and why:
     .dropdown-item    menu entries do not emboss; Windows 95 highlights them
                       and leaves them where they are
     .desktop-icon
     .folder-icon      an icon is a picture, not a button face; nothing about
                       it moves when it is clicked, only its label highlights
     .tab-button       picking a tab redraws the whole strip
     .display-swatch   a colour swatch is chosen, not pressed
     .dragging-window  while a window is being dragged, nothing may look
                       pressed: the control under the thumb is still held, so
                       it would stay sunk for the whole drag -- and a sunk
                       button is the app promising a sound on release that the
                       drag has already cancelled. Letting it up is how you
                       know it is safe to let go. Excluded here rather than
                       overridden from app.css, because this selector outranks
                       any override that does not repeat the whole list. */
button:active:not(:disabled):not(.dropdown-item):not(.desktop-icon):not(.folder-icon):not(.tab-button):not(.display-swatch):not(.dragging-window *),
.w95-button:active:not(:disabled):not(.dropdown-item):not(.desktop-icon):not(.folder-icon):not(.tab-button):not(.display-swatch):not(.dragging-window *) {
  border-width: 1px 0 0 1px;
  box-shadow:
    inset 1px 1px 0 var(--dark),
    inset -1px -1px 0 var(--highlight),
    inset 2px 2px 0 var(--shadow),
    inset -2px -2px 0 var(--light);
}

/* The default button carries a black ring outside its bevel and stands taller
   than an ordinary button. The ring is what marks it as the default and is
   always there; the dotted focus rectangle is a different thing entirely and
   belongs to whichever control currently has focus. */
.default-button {
  position: relative;
  height: 23px;
  min-width: 75px;
  padding: 0 12px;
  /* The default button draws its own black ring and dotted focus rectangle,
     so it opts out of the browser's native focus outline the way the ordinary
     buttons do -- without this, Chrome paints a rounded blue glow on top of
     the square Windows 95 button when it takes focus. */
  outline: none;
  box-shadow:
    inset -1px -1px 0 var(--dark),
    inset 1px 1px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow),
    inset 2px 2px 0 var(--light),
    0 0 0 1px var(--dark);
}

/* Only while focused. This used to be unconditional, which left the dotted
   rectangle sitting on every default button in the app -- the logon OK, the
   message boxes, all three of Display Properties' -- no matter where the
   keyboard actually was. */
.default-button:focus::after {
  position: absolute;
  border: 1px dotted var(--dark);
  content: "";
  inset: 3px;
}

.default-button:focus:active::after {
  inset: 4px 2px 2px 4px;
}

/* :focus, not :focus-visible. Windows 95 gives a button the focus rectangle
   when you click it, and leaves it there: the button keeps the keyboard, so
   Space or Enter presses it again without touching the mouse. :focus-visible
   deliberately hides itself from the pointer, which is the modern convention
   and the wrong one here.

   The default button draws its own, one pixel further in, so it is excluded
   here rather than wearing both. */
button:focus:not(.default-button),
.w95-button:focus:not(.default-button) {
  outline: 1px dotted #000;
  outline-offset: -4px;
}

/* The sunken frame is two inset shadows, drawn *inside* the padding box, so
   the padding has to carry the frame as well as the margin: at 1px 2px the
   text sat flush against the dark line. Measured off the DOC.EXE capture
   (experiments/win95_icons/ref-voices.png): the multi-line edit leaves 2px of
   white between the frame and the text, the single-line edits and combos 4px,
   which is 4px and 6px from the control's edge. */
input[type="text"],
input[type="password"],
input[type="number"],
textarea,
select {
  box-sizing: border-box;
  border: 0;
  border-radius: 0;
  padding: 3px 4px;
  background: var(--window);
  color: var(--window-text);
  font: var(--font);
  box-shadow:
    inset 1px 1px 0 var(--shadow),
    inset -1px -1px 0 var(--highlight),
    inset 2px 2px 0 var(--dark),
    inset -2px -2px 0 var(--face);
}

input[type="text"],
input[type="password"],
input[type="number"],
select {
  padding-left: 6px;
}

input:focus,
textarea:focus,
select:focus {
  outline: none;
}

/* Group boxes outside the main window (the dialogs still use real fieldsets).
   EDGE_ETCHED again, drawn on the border rather than with shadows so the legend
   can break the line the way Windows does. */
fieldset {
  margin: 0;
  padding: 8px;
  border: 1px solid var(--highlight);
  border-top-color: var(--shadow);
  border-left-color: var(--shadow);
  box-shadow:
    inset 1px 1px 0 var(--highlight),
    inset -1px -1px 0 var(--shadow);
}

legend {
  padding: 0 3px;
  background: var(--face);
  font: 700 var(--font);
}

/* --- combo box ------------------------------------------------------------
 * A sunken field with a raised drop-down button. The list is ours too, because
 * a native <select> draws its popup with the OS.
 */

.combo {
  position: relative;
  display: flex;
  height: 21px;
  align-items: stretch;
  background: var(--window);
  color: var(--window-text);
  cursor: default;
  font: var(--font);
  user-select: none;
  box-shadow:
    inset 1px 1px 0 var(--shadow),
    inset -1px -1px 0 var(--highlight),
    inset 2px 2px 0 var(--dark),
    inset -2px -2px 0 var(--face);
}

.combo:focus {
  outline: none;
}

.combo-field {
  overflow: hidden;
  flex: 1;
  /* 6px on the left: 4px of white inside the 2px frame, as the DOC.EXE
     capture draws its combos (see the edit controls above). */
  padding: 3px 2px 0 6px;
  white-space: nowrap;
}

.combo:focus .combo-field {
  background: var(--hilight);
  color: var(--hilight-text);
}

.combo-button {
  position: relative;
  width: 16px;
  margin: 2px 2px 2px 0;
  background: var(--face);
  box-shadow:
    inset -1px -1px 0 var(--dark),
    inset 1px 1px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow),
    inset 2px 2px 0 var(--light);
}

.combo-button::before {
  position: absolute;
  top: 50%;
  left: 50%;
  border: 4px solid transparent;
  border-top-color: #000;
  content: "";
  transform: translate(-50%, -25%);
}

.combo.open .combo-button {
  box-shadow:
    inset 1px 1px 0 var(--dark),
    inset -1px -1px 0 var(--highlight),
    inset 2px 2px 0 var(--shadow),
    inset -2px -2px 0 var(--light);
}

.combo-list {
  position: absolute;
  top: 100%;
  right: 0;
  left: 0;
  z-index: 200;
  max-height: 160px;
  overflow-y: auto;
  background: var(--window);
  color: var(--window-text);
  box-shadow: inset 0 0 0 1px var(--dark);
}

.combo-option {
  padding: 1px 3px;
  white-space: nowrap;
}

.combo-option.selected,
.combo-option:hover {
  background: var(--hilight);
  color: var(--hilight-text);
}

/* --- slider ---------------------------------------------------------------
 * A sunken groove with the pointed Windows 95 thumb riding along it. Stood on
 * end (.vertical) for the tray's Volume control, where the thumb points left.
 */

.slider.vertical {
  width: 21px;
  height: auto;
}

.slider.vertical .slider-track {
  top: 1px;
  right: auto;
  bottom: 1px;
  left: 9px;
  width: 4px;
  height: auto;
}

.slider.vertical .slider-thumb {
  top: auto;
  left: 1px;
  width: 19px;
  height: 11px;
  margin-top: -5px;
  margin-left: 0;
  clip-path: polygon(38% 0, 100% 0, 100% 100%, 38% 100%, 0 50%);
}

.slider {
  position: relative;
  height: 21px;
  cursor: default;
}

.slider:focus {
  outline: 1px dotted #000;
}

/* A bigger target than it looks. The track is 21px tall, which is a fine mouse
   target and a poor thumb one; this reaches past it without moving anything.
   The handler measures the box, not this, so the position maths is unchanged. */
.slider::after {
  position: absolute;
  content: "";
  inset: -6px -2px;
}

.slider-track {
  position: absolute;
  top: 9px;
  right: 1px;
  left: 1px;
  height: 4px;
  box-shadow:
    inset 1px 1px 0 var(--shadow),
    inset -1px -1px 0 var(--highlight),
    inset 2px 2px 0 var(--dark),
    inset -2px -2px 0 var(--face);
}

.slider-thumb {
  position: absolute;
  top: 1px;
  width: 11px;
  height: 19px;
  margin-left: -5px;
  background: var(--face);
  /* The Windows 95 thumb is a flag: square on top, pointed at the bottom. */
  clip-path: polygon(0 0, 100% 0, 100% 62%, 50% 100%, 0 62%);
  box-shadow:
    inset -1px -1px 0 var(--shadow),
    inset 1px 1px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow);
}

/* Windows 95 spin buttons: a 16px column of two half-height arrows. */
.spinner {
  display: flex;
  width: 16px;
  flex-direction: column;
  flex-shrink: 0;
}

.spinner button {
  position: relative;
  height: 9px;
  padding: 0;
}

.spinner button::before {
  position: absolute;
  top: 50%;
  left: 50%;
  border: 3px solid transparent;
  content: "";
  transform: translate(-50%, -50%);
}

.spinner button.up::before {
  margin-top: -1px;
  border-bottom-color: #000;
}

.spinner button.down::before {
  margin-top: 1px;
  border-top-color: #000;
}

/* --- window chrome -------------------------------------------------------- */

.window {
  box-sizing: border-box;
  padding: 3px;
  background: var(--face);
  box-shadow:
    inset -1px -1px 0 var(--dark),
    inset 1px 1px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow),
    inset 2px 2px 0 var(--light);
}

.title-bar {
  display: flex;
  height: 18px;
  align-items: center;
  padding: 0 2px 0 1px;
  background: var(--title);
  color: var(--title-text);
  font: 700 var(--font);
  user-select: none;
}

.title-bar.inactive {
  background: var(--title-inactive);
  color: var(--title-text-inactive);
}

.title-bar-text {
  flex: 1;
  overflow: hidden;
  padding-left: 3px;
  white-space: nowrap;
}

.title-bar-controls {
  display: flex;
  gap: 2px;
}

.title-bar-controls button {
  position: relative;
  width: 16px;
  height: 14px;
  padding: 0;
}

/* A disabled control-box button greys its glyph and offsets a white copy behind
   it, the same way Windows 95 greys disabled text. The About box's close button
   is drawn this way in the capture. */
.title-bar-controls button:disabled::before {
  background: var(--shadow);
  filter: drop-shadow(1px 1px 0 var(--highlight));
}

/* The three glyphs, drawn rather than fetched -- they are a few pixels each. */
.title-bar-controls button::before {
  position: absolute;
  background: #000;
  content: "";
}

.title-bar-controls button[data-glyph="minimize"]::before {
  bottom: 3px;
  left: 3px;
  width: 6px;
  height: 2px;
}

.title-bar-controls button[data-glyph="maximize"]::before {
  top: 3px;
  left: 3px;
  width: 8px;
  height: 7px;
  border: 1px solid #000;
  border-top-width: 2px;
  background: none;
}

/* Restore: the glyph a maximised window's middle button wears once it is
   already filling the screen. Windows 95 drew two overlapping title-barred
   frames, so this is two boxes -- the back one up and right, the front one down
   and left, painted over it. */
.title-bar-controls button[data-glyph="restore"]::before {
  top: 2px;
  left: 5px;
  width: 4px;
  height: 3px;
  border: 1px solid #000;
  border-top-width: 2px;
  background: none;
}

.title-bar-controls button[data-glyph="restore"]::after {
  position: absolute;
  top: 5px;
  left: 2px;
  width: 4px;
  height: 3px;
  border: 1px solid #000;
  border-top-width: 2px;
  background: var(--face);
  content: "";
}

.title-bar-controls button[data-glyph="restore"]:disabled::before,
.title-bar-controls button[data-glyph="restore"]:disabled::after {
  border-color: var(--shadow);
}

.title-bar-controls button[data-glyph="close"]::before {
  top: 3px;
  left: 4px;
  width: 7px;
  height: 7px;
  background:
    linear-gradient(45deg, transparent 44%, #000 44%, #000 56%, transparent 56%),
    linear-gradient(-45deg, transparent 44%, #000 44%, #000 56%, transparent 56%);
}

/* The context-help button, which dialogs wear instead of minimize/maximize. The
   other glyphs are drawn out of gradients and borders; this one is a character,
   because a question mark is a character. */
.title-bar-controls button[data-glyph="help"]::before {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: none;
  color: #000;
  font: 700 12px Tahoma, "MS Sans Serif", sans-serif;
  line-height: 13px;
  text-align: center;
  content: "?";
}

/* --- menu bar -------------------------------------------------------------
 * Menus use the system menu font, which is not bold -- unlike every control on
 * this form, which inherits VB3's bold default.
 */

.menu-bar {
  display: flex;
  height: 19px;
  align-items: center;
  font: var(--font);
  user-select: none;
}

.menu-item {
  position: relative;
  padding: 2px 5px;
  cursor: default;
}

/* Only the open menu inverts. Windows 95 does not light a top-level menu item
   just because the pointer is over it. */
.menu-item.open {
  background: var(--hilight);
  color: var(--hilight-text);
}

.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 100;
  min-width: 120px;
  padding: 2px;
  background: var(--menu);
  color: var(--menu-text);
  box-shadow:
    inset -1px -1px 0 var(--dark),
    inset 1px 1px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow),
    inset 2px 2px 0 var(--light);
}

.dropdown-item {
  display: block;
  width: 100%;
  padding: 3px 18px 3px 8px;
  border: 0;
  background: none;
  box-shadow: none;
  color: var(--menu-text);
  font: var(--font);
  text-align: left;
  white-space: nowrap;
}

/* Not the disabled ones: Windows 95 lit a greyed entry no more than it
   answered it. */
.dropdown-item:hover:not(:disabled) {
  background: var(--hilight);
  color: var(--hilight-text);
}

/* Nothing to undo any more -- the pressed-button rule skips these -- but the
   selector stays as the statement that a menu entry does not move when picked. */
.dropdown-item:active {
  box-shadow: none;
}

.dropdown-separator {
  height: 2px;
  margin: 2px 1px;
  box-shadow: inset 0 1px 0 var(--shadow), inset 0 -1px 0 var(--highlight);
}

/* --- scrollbars -----------------------------------------------------------
 * 16px wide, with the 50% dither Windows 95 draws its trough with. The capture
 * shows that checkerboard plainly on every Quick Box.
 */

::-webkit-scrollbar {
  width: 16px;
  height: 16px;
}

::-webkit-scrollbar-track {
  background-color: var(--face);
  background-image:
    linear-gradient(45deg, var(--highlight) 25%, transparent 25%, transparent 75%, var(--highlight) 75%),
    linear-gradient(45deg, var(--highlight) 25%, transparent 25%, transparent 75%, var(--highlight) 75%);
  /* Phase matched to the capture: face in the top-left cell, not white. */
  background-position: 1px 0, 0 1px;
  background-size: 2px 2px;
}

::-webkit-scrollbar-thumb {
  background: var(--face);
  box-shadow:
    inset -1px -1px 0 var(--dark),
    inset 1px 1px 0 var(--highlight),
    inset -2px -2px 0 var(--shadow),
    inset 2px 2px 0 var(--light);
}

::-webkit-scrollbar-button:vertical:start {
  display: block;
  height: 16px;
  background: var(--face) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16'><path d='M8 5l4 5H4z' fill='black'/></svg>") no-repeat center;
  box-shadow:
    inset -1px -1px 0 #000, inset 1px 1px 0 #fff,
    inset -2px -2px 0 #808080, inset 2px 2px 0 #c0c0c0;
}

::-webkit-scrollbar-button:vertical:end {
  display: block;
  height: 16px;
  background: var(--face) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16'><path d='M8 11l-4-5h8z' fill='black'/></svg>") no-repeat center;
  box-shadow:
    inset -1px -1px 0 #000, inset 1px 1px 0 #fff,
    inset -2px -2px 0 #808080, inset 2px 2px 0 #c0c0c0;
}

::-webkit-scrollbar-corner {
  background: var(--face);
}
