/* ==========================================================================
   CONTROLS — one raster for every widget
   --------------------------------------------------------------------------
   Text in this interface looks right because it sits on a grid: a face drawn
   on an 11px or 8px module, at a whole multiple of it. Widgets were not doing
   the same thing — the sliders were browser defaults wearing a border, which
   is why they read as foreign next to everything else.

   So every control here is built from the same three numbers:

     --u-track  16px  4 modules. Slider tracks, meters, progress bars.
     --u-ctl    24px  6 modules. Buttons, menu rows, slider thumbs.

   And from the same three parts:

     a sunken well      2px border, inset bevel        tracks, meters
     a raised block     1px outline, raised bevel      thumbs, buttons
     a segment overlay  6px on, 2px off                fills and tracks

   The segment overlay is what ties them together. The progress meter draws
   its blocks that way, so the slider track draws its blocks the same way and
   at the same pitch: a slider now reads as a meter you can grab.
   ========================================================================== */

body {
  --u-track: 16px;
  --u-ctl: 24px;
  --seg-on: 6px;                 /* block */
  --seg-off: 2px;                /* gap between blocks */
}


/* .seg and .well were the shared parts this file was built around: a sunken
   well for tracks and meters, and a segment overlay painted over a fill. The
   sliders below ended up drawing both inline on ::-webkit-slider-runnable-track
   and ::-moz-range-track — a native track cannot be given a child element —
   and the status-bar meter draws its own. Nothing carried either class, so
   both are gone; the numbers they were built from are still above, because
   the slider rules read them. */

/* --------------------------------------------------------------------------
   SLIDERS
   The track is a .well and the thumb is a raised block with a groove, drawn
   with the same bevels as a button. Both native pseudo-elements are given
   the same treatment so Chrome and Firefox agree.
   -------------------------------------------------------------------------- */

.mslider {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 10px 8px;
}
/* Slider names and readouts sit at the small-label size, matching .mticks
   above. At --f-sm they were the smallest text in the interface while naming
   the control beside them; the min-width goes up with the type so the labels
   still hold one line and the tracks all start on the same vertical. */
.mslider .lab {
  flex: none;
  min-width: 76px;
  font-size: var(--f-label);
  color: var(--ink-dim);
}

input[type="range"] {
  flex: 1;
  min-width: 0;
  height: var(--u-ctl);
  margin: 0;
  padding: 0;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  cursor: pointer;
}

/* -- track ---------------------------------------------------------------- */

input[type="range"]::-webkit-slider-runnable-track {
  height: var(--u-track);
  background-color: color-mix(in srgb, var(--ink) 20%, var(--face));
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 var(--seg-on),
    var(--face) var(--seg-on) calc(var(--seg-on) + var(--seg-off)));
  border: 2px solid var(--line);
  box-shadow: var(--bevel-down);
}
input[type="range"]::-moz-range-track {
  height: var(--u-track);
  background-color: color-mix(in srgb, var(--ink) 20%, var(--face));
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 var(--seg-on),
    var(--face) var(--seg-on) calc(var(--seg-on) + var(--seg-off)));
  border: 2px solid var(--line);
  box-shadow: var(--bevel-down);
}

/* -- thumb ---------------------------------------------------------------- */

input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px;
  height: var(--u-ctl);
  margin-top: calc((var(--u-track) - var(--u-ctl)) / 2 - 2px);
  background-color: var(--face);
  /* the groove: three pixel rules down the middle of the block */
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 4px,
    var(--edge-dk) 4px 5px,
    transparent 5px 8px);
  border: 1px solid var(--ink);
  box-shadow: var(--bevel-up);
}
input[type="range"]::-moz-range-thumb {
  width: 12px;
  height: var(--u-ctl);
  border-radius: 0;
  background-color: var(--face);
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 4px,
    var(--edge-dk) 4px 5px,
    transparent 5px 8px);
  border: 1px solid var(--ink);
  box-shadow: var(--bevel-up);
}

input[type="range"]:active::-webkit-slider-thumb { box-shadow: var(--bevel-down); }
input[type="range"]:active::-moz-range-thumb     { box-shadow: var(--bevel-down); }

/* the scale printed above a stepped slider. The end labels pull in by half a
   thumb so each number sits over the position it actually selects. */
.mticks {
  display: flex;
  justify-content: space-between;
  padding: 2px 16px 0;
  /* the pattern-size scale is the label for that slider, not an aside, so it
     reads at the small-label size rather than the smallest one in the set */
  font-size: var(--f-label);
  letter-spacing: 0;
  color: var(--ink-dim);
}
.mticks span { width: 0; display: flex; justify-content: center; }


/* --------------------------------------------------------------------------
   SWATCH ROW — colours picked without labels, on the same module
   -------------------------------------------------------------------------- */

.swrow {
  display: flex;
  gap: 3px;
  padding: 4px 10px 8px;
}
/* The colour chips are buttons that happen to be filled with a colour, so
   they lift and press like every other control — and, carrying .btn, they
   are in the sound path as well. */
.swrow label {
  position: relative;
  flex: 1;
  height: var(--u-ctl);
  border: 1px solid var(--ink);
  box-shadow: var(--bevel-up);
  cursor: pointer;
}
.swrow label:hover {
  box-shadow: var(--bevel-up), inset 0 0 0 2px var(--sel);
  translate: 0 -1px;
}
.swrow label:active {
  box-shadow: var(--bevel-down);
  translate: 0 1px;
}

/* THE ONE IN USE CARRIES A RING. Without it the row gave no reading at all —
   the chips are pure colour with nothing to mark them, so after a randomise,
   which picks a ground for you, there was no way to tell which of the five
   you had landed on short of clicking through them.

   Two rings rather than one, because a single colour cannot show on all five:
   a 1px edge in --ink, which is the darkest value the scheme has, and a 2px
   band in --face inside it, which is among the lightest. On a dark chip the
   inner band reads; on a light chip the outer edge does. It is drawn with
   inset shadows so it takes no space and cannot shift the row.

   It is drawn on a pseudo-element rather than on the chip itself. Put on the
   chip, the rule would out-specify .swrow label:hover and :active — a
   selector carrying an id beats one carrying a class — and the chip already
   in use would stop lifting and pressing like the other four. On ::after the
   ring is a separate layer, so the bevels underneath it still work.

   Generated by build_lists.py — CSS cannot ask which input a label points at
   without naming both ends, and this is the fourth list in the file that has
   to be kept in step with the markup. */
/* SWATCH-LIST-START */
body:has(#bg-1:checked) .swrow [for="bg-1"]::after,
body:has(#bg-2:checked) .swrow [for="bg-2"]::after,
body:has(#bg-3:checked) .swrow [for="bg-3"]::after,
body:has(#bg-4:checked) .swrow [for="bg-4"]::after,
body:has(#bg-5:checked) .swrow [for="bg-5"]::after
/* SWATCH-LIST-END */
{
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px var(--ink),
              inset 0 0 0 3px var(--face);
}


/* --------------------------------------------------------------------------
   SCROLLBARS — the classic Macintosh one
   --------------------------------------------------------------------------
   Four parts, all of them square: a dithered track, a flat thumb outlined in
   one pixel, and a stepped arrow at each end. No gloss and no rounding, which
   is why it belongs here — it is the same vocabulary as the rest of the
   interface, drawn thirty years earlier.

   The dither is the signature. A 2px checker of the rule colour over the face
   reads as the 50% stipple those bars were filled with, and because it is
   built from whole pixels it stays crisp at any size. The thumb is plain
   face with a 1px outline: on the original it was white on grey, here it is
   whatever the scheme calls paper on whatever it calls rule.

   The arrows are four stacked background layers, each a 1px-tall bar of a
   different width, positioned to build a stepped triangle. A glyph would
   depend on the font and a rotated rule would land between pixels — the same
   reasoning as the page arrows in the status bar. Scrollbar parts cannot
   carry pseudo-elements, so the shape has to come from backgrounds.

   15px wide, the width of the close box in the title bar: the interface has
   one measure for a small square control and this takes it. The lines are
   2px, which is what every structural edge in this interface is drawn at —
   the window, the menu bar, the status strip, the meter. A 1px bar read as
   something borrowed from the operating system sitting next to them.

   THE TWO SYNTAXES CANNOT BOTH BE DECLARED. Blink and WebKit switch
   ::-webkit-scrollbar styling OFF for any element that also sets the standard
   `scrollbar-width`, and fall back to a native bar — which on macOS is an
   overlay that stays invisible until something is actually scrolled. So the
   standard properties are scoped to the engine that needs them:
   `@supports not selector(::-webkit-scrollbar)` is true only where the
   pseudo-element is unsupported, which is Firefox. Everywhere else the block
   is skipped and ::-webkit-scrollbar is left free to draw. Firefox gets the
   colours without the dither, which is as close as it allows.
   -------------------------------------------------------------------------- */

/* SMOOTH INCREMENTS.

   A scrollbar arrow moves the box by a line, and by default it arrives there
   in one frame — the text jumps and you have to find your place again. With
   scroll-behavior the same step is animated, so the line you were reading
   travels to where it is going and you can follow it.

   It applies to every box here that scrolls, not only the reading pane: the
   category tree, the outline and a long menu all have arrows now and should
   all behave the same way. Dragging the thumb and using a wheel or trackpad
   are untouched, which is correct — those are continuous gestures already,
   and animating them would fight the hand.

   Turned off for anyone who asks their system for less motion, the same as
   the title screen. */
.abstracts, .pane, .tree, .outline, .mpanel { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  .abstracts, .pane, .tree, .outline, .mpanel { scroll-behavior: auto; }
}

/* HIDDEN BY PAINT, NOT BY WIDTH.

   The obvious way to hide this is width:0 and let the gated rules below put
   it back. It does not work: WebKit caches scrollbar METRICS and does not
   recompute them when a :has() condition flips, so toggling Reading scrollbar
   changed the stylesheet and nothing else — the bar stayed exactly as it was
   until something else forced a relayout. Colours and backgrounds do update.

   So the width never changes. The bar is always 15px and always laid out;
   switching it off paints every part of it transparent instead. Nothing
   reflows, the text does not jump, and the toggle works on the first press.
   Note this costs nothing when the page fits: overflow:auto reserves no space
   for a bar it is not showing. */
.abstracts::-webkit-scrollbar,
.pane::-webkit-scrollbar { width: 15px; height: 15px; }

.abstracts::-webkit-scrollbar-track,
.pane::-webkit-scrollbar-track {
  background: transparent;
  background-image: none;
  border: 0;
}
.abstracts::-webkit-scrollbar-thumb,
.pane::-webkit-scrollbar-thumb {
  background: transparent;
  background-image: none;
  border: 0;
}
.abstracts::-webkit-scrollbar-button,
.pane::-webkit-scrollbar-button { display: none; }

@supports not selector(::-webkit-scrollbar) {
  .tree, .outline, .mpanel, body:has(#show-scroll:checked) .abstracts {
    scrollbar-width: thin;
    scrollbar-color: var(--face) color-mix(in srgb, var(--ink) 18%, var(--face-alt));
  }
  .abstracts, .pane { scrollbar-width: none; }
}

.tree::-webkit-scrollbar ,
.outline::-webkit-scrollbar ,
.mpanel::-webkit-scrollbar ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar  {
  width: 15px;
  height: 15px;
}

/* the track: a 1px checker, and a rule down the edge that meets the content */
.tree::-webkit-scrollbar-track ,
.outline::-webkit-scrollbar-track ,
.mpanel::-webkit-scrollbar-track ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-track,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-track  {
  background-color: var(--face);
  /* a conic quartered into two on and two off is a checkerboard built from
     right angles — the 45deg construction gives the same picture but puts a
     diagonal in a UI part, which is the one thing this interface does not do */
  background-image: conic-gradient(var(--line) 0 25%, transparent 0 50%,
                                   var(--line) 0 75%, transparent 0);
  background-size: 2px 2px;
  border-left: 2px solid var(--ink);
}

/* the thumb: flat, outlined, no relief */
.tree::-webkit-scrollbar-thumb ,
.outline::-webkit-scrollbar-thumb ,
.mpanel::-webkit-scrollbar-thumb ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-thumb,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-thumb  {
  background-color: var(--face);
  /* the grip: three rules across the middle, the way XP marked a thumb as
     something you take hold of. Three separate 1px layers rather than a
     repeating gradient, so the spacing is exact and cannot drift with the
     thumb's height — and centred on 50%, so it stays in the middle whether
     the thumb is the 26px minimum or half the track. Scrollbar parts take no
     pseudo-elements, so like the arrows it has to be drawn in backgrounds. */
  background-image:
    linear-gradient(var(--ink), var(--ink)),
    linear-gradient(var(--ink), var(--ink)),
    linear-gradient(var(--ink), var(--ink));
  background-repeat: no-repeat;
  background-size: 7px 1px, 7px 1px, 7px 1px;
  background-position: center calc(50% - 3px), center 50%, center calc(50% + 3px);
  /* No right edge on any of this. The bar sits hard against the 2px rule the
     workspace grid draws between the centre pane and the outline, so a border
     on that side lands beside an identical line and reads as one 4px rule
     while the left side stays 2px. The divider is the right edge. */
  border: 2px solid var(--ink);
  border-right: 0;
  min-height: 26px;
}
.tree::-webkit-scrollbar-thumb:active ,
.outline::-webkit-scrollbar-thumb:active ,
.mpanel::-webkit-scrollbar-thumb:active ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-thumb:active,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-thumb:active  {
  background: color-mix(in srgb, var(--ink) 16%, var(--face));
}

/* the end buttons, one at each end, each with its stepped arrow */
.tree::-webkit-scrollbar-button:vertical:start:decrement ,
.outline::-webkit-scrollbar-button:vertical:start:decrement ,
.mpanel::-webkit-scrollbar-button:vertical:start:decrement ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-button:vertical:start:decrement,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-button:vertical:start:decrement ,
.tree::-webkit-scrollbar-button:vertical:end:increment ,
.outline::-webkit-scrollbar-button:vertical:end:increment ,
.mpanel::-webkit-scrollbar-button:vertical:end:increment ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-button:vertical:end:increment,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-button:vertical:end:increment  {
  display: block;
  /* border-box explicitly. Scrollbar parts are not covered by the * reset at
     the top of the site, so they default to content-box — which meant the top
     button, being the only one with a border on a horizontal edge, came out
     2px taller than the bottom one and sat its arrow 1px off. Pinning the box
     model makes both ends exactly 12px whatever edges they draw. */
  box-sizing: border-box;
  height: 12px;
  background-color: var(--face);
  background-repeat: no-repeat;
  /* Left rule only, always. Both ends of the bar now meet a rule whichever
     way it is scrolling — the menu bar and status strip when it spans the
     pane, the heading rule and the pane foot when it does not — and the
     inner edge meets the track, which is the same strip continuing. So the
     button draws the one line nothing else supplies. */
  border-width: 0 0 0 2px;
  border-style: solid;
  border-color: var(--ink);
}
.tree::-webkit-scrollbar-button:vertical:start:decrement ,
.outline::-webkit-scrollbar-button:vertical:start:decrement ,
.mpanel::-webkit-scrollbar-button:vertical:start:decrement ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-button:vertical:start:decrement,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-button:vertical:start:decrement  {
  background-image:
    linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink)),
    linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink));
  background-size: 1px 1px, 3px 1px, 5px 1px, 7px 1px;
  /* positioned from the middle rather than from the top, so the arrow stays
     centred whatever height the button is given */
  background-position: center calc(50% - 2px), center calc(50% - 1px),
                       center 50%, center calc(50% + 1px);
}
.tree::-webkit-scrollbar-button:vertical:end:increment ,
.outline::-webkit-scrollbar-button:vertical:end:increment ,
.mpanel::-webkit-scrollbar-button:vertical:end:increment ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-button:vertical:end:increment,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-button:vertical:end:increment  {
  background-image:
    linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink)),
    linear-gradient(var(--ink), var(--ink)), linear-gradient(var(--ink), var(--ink));
  background-size: 7px 1px, 5px 1px, 3px 1px, 1px 1px;
  /* positioned from the middle rather than from the top, so the arrow stays
     centred whatever height the button is given */
  background-position: center calc(50% - 2px), center calc(50% - 1px),
                       center 50%, center calc(50% + 1px);
}
.tree::-webkit-scrollbar-button:vertical:start:decrement:active ,
.outline::-webkit-scrollbar-button:vertical:start:decrement:active ,
.mpanel::-webkit-scrollbar-button:vertical:start:decrement:active ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-button:vertical:start:decrement:active,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-button:vertical:start:decrement:active ,
.tree::-webkit-scrollbar-button:vertical:end:increment:active ,
.outline::-webkit-scrollbar-button:vertical:end:increment:active ,
.mpanel::-webkit-scrollbar-button:vertical:end:increment:active ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-button:vertical:end:increment:active,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-button:vertical:end:increment:active  {
  background-color: color-mix(in srgb, var(--ink) 16%, var(--face));
}

/* THE TWO END BUTTONS TOGETHER MEASURE A CONTROL.

   12px each, so the pair comes to 24px — the height this interface uses for
   a control everywhere else, and the module the sliders and menu rows are
   built on. They were 15px, which made the pair 30px to match the outline
   pane's header box, and that was a shade too tall: the arrows read as two
   blocks capping the bar rather than as part of it.

   The box is identical whether or not the bar spans the whole pane. There
   used to be two versions, one closed and one open at the ends, from when
   the shorter bar floated inside the pane and had to close itself. It no
   longer floats — it reaches the heading rule at the top and the pane foot
   at the bottom — so both ends meet a line either way and one box serves. */

/* THERE ARE FOUR BUTTON SLOTS, NOT TWO.

   WebKit gives a scrollbar a button at each end for EACH direction: an up and
   a down at the top, and an up and a down at the bottom. Naming only the
   direction — :decrement, :increment — matches two of them each, so the
   stylesheet was quietly turning on a second button at the far end as well.
   It showed up the moment the top arrow was given a top edge: the rule
   matched the decrement button at the BOTTOM too, and drew a bar above the
   down arrow.

   Naming the position as well pins each rule to one slot, and the two
   crossed combinations are turned off outright. */
.tree::-webkit-scrollbar-button:vertical:start:increment,
.outline::-webkit-scrollbar-button:vertical:start:increment,
.mpanel::-webkit-scrollbar-button:vertical:start:increment,
.abstracts::-webkit-scrollbar-button:vertical:start:increment,
.pane::-webkit-scrollbar-button:vertical:start:increment,
.tree::-webkit-scrollbar-button:vertical:end:decrement,
.outline::-webkit-scrollbar-button:vertical:end:decrement,
.mpanel::-webkit-scrollbar-button:vertical:end:decrement,
.abstracts::-webkit-scrollbar-button:vertical:end:decrement,
.pane::-webkit-scrollbar-button:vertical:end:decrement {
  display: none;
}

/* ONE EDGE THE BAR HAS TO DRAW ITSELF.

   Every other end of it meets a rule that already exists and runs the full
   width of the window: the menu bar above, the status strip below. The top of
   the shorter bar does not. It begins at the page heading, and that heading's
   rule is drawn by .pg-head, which sits inside the pane's 34px padding — so
   it stops short of the pane edge and never reaches the bar at all. Nothing
   is there to serve as the edge, so the button supplies it.

   Only in that case. When the bar spans the pane its top meets the menu bar's
   rule and a border here would double it. */
body:not(:has(#scroll-all:checked)) .abstracts::-webkit-scrollbar-button:vertical:start:decrement {
  border-top-width: 2px;
}

/* no horizontal bar anywhere: nothing here is ever wider than its column */
.tree::-webkit-scrollbar-button:horizontal ,
.outline::-webkit-scrollbar-button:horizontal ,
.mpanel::-webkit-scrollbar-button:horizontal ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-button:horizontal,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-button:horizontal ,
.tree::-webkit-scrollbar-corner ,
.outline::-webkit-scrollbar-corner ,
.mpanel::-webkit-scrollbar-corner ,
body:has(#show-scroll:checked) .abstracts::-webkit-scrollbar-corner,
body:has(#show-scroll:checked) .pane::-webkit-scrollbar-corner  {
  display: none;
}
