/* ── wool ────────────────────────────────────────────────────────────────
   The UI's material: the thing you are meant to act on, and the plate a
   message is written on. wool.js builds the two sheets, this file wears
   them.

       <button class="act wool"></button>
       <span class="wool-ink">what somebody said</span>

   **NO ANIMATION and no gloss.** Wool is matte: what gives it form is the
   shading across each coil, already in the sheet. Anything painted across
   an object on top of that is a second light source contradicting the
   first.
   ──────────────────────────────────────────────────────────────────── */

:root {
  /* The crown of the wool — everything the sheets do to it is subtraction,
     so this is the LIGHTEST the material ever gets and reads as its colour.
     Warm, and only just: pure white against a violet-black ground is a hole
     in the page, and a full cream reads as paper rather than fibre. */
  --wool-base: #f2eee7;
  /* The same wool where it has to survive being 17px tall — see
     `.wool-ink` — and the colour of the fine accents cut from it. */
  --wool-pale: #f8f5f0;
  /* The one flat colour on the site: what shows where a clipped ink cannot
     work at all. See `.field` in style.css. */
  --wool-flat: #ebe6dd;

  /* THE SHEETS' OWN PIXEL SIZE, so they are painted 1:1 and never
     resampled. This literal is the size wool.js generates them at, and the
     two are one number — `Surface.noise.size`. wool.js overwrites the
     property on load with that size divided by the screen's pixel ratio,
     which is what keeps the painting 1:1; the reasoning is at `fit` there.

     ABSOLUTE, and nothing overrides it per element. The wind belongs to the
     material, not to whatever wears it: a bigger object is a bigger window
     onto one sheet, the way a wider bolt of cloth does not get a coarser
     weave. */
  --wool-tile: 384px;

  /* Neutral until wool.js replaces them: white is a no-op under `multiply`
     and a transparent image adds nothing, so with no script an object is
     simply the base colour under `--wool-body`. Keep both defaults if you
     touch this — a coloured or opaque stand-in is what an object wears for
     the first frames of every load. */
  --wool-tex:  linear-gradient(#fff, #fff);
  --wool-lint: linear-gradient(#0000, #0000);

  /* The object's own form, over the sheet: lit across the top, falling away
     underneath. Multiplied, so the white end is where nothing happens. It
     is a variable rather than a literal in the stack so that `:active` can
     replace it without restating the whole positional list. */
  --wool-body: linear-gradient(180deg, #fff 0%, #fcfaf6 38%, #e0d9cd 100%);

  /* WHICH PART OF THE SHEET AN OBJECT IS CUT FROM. Every object otherwise
     shows the same top-left corner, and a room full of message plates all
     carrying one recognisable swirl reads as a repeated graphic rather than
     as a material. room.js sets it per message. */
  --wool-shift: 0 0;

  /* How much of the wind survives inside a letter — a legibility control,
     and the reason `.wool-ink` is not just `.wool` clipped. */
  --wool-ink-veil: rgba(248, 245, 240, .52);
}

/* Three images and a colour: the sheet, the fibres on it, and the object's
   own light over both. Blended into one element's background rather than
   stacked in pseudo-elements, because a button's label is a bare text node
   and an absolutely-positioned layer would paint over it.

   The `background-*` lists are POSITIONAL: adding a layer means adding an
   entry to all five. */
.wool {
  background-color: var(--wool-base);
  background-image:
    var(--wool-body),
    var(--wool-lint),
    var(--wool-tex);
  background-size:
    auto,
    var(--wool-tile) var(--wool-tile),
    var(--wool-tile) var(--wool-tile);
  /* The body light belongs to the OBJECT, so it stays at the origin while
     the two sheets shift together — they have to stay in register with each
     other or the fibres come off the coils they belong to. */
  background-position:
    0 0,
    var(--wool-shift),
    var(--wool-shift);
  background-repeat:
    no-repeat,
    repeat,
    repeat;
  background-blend-mode:
    multiply,
    normal,
    multiply;

  /* The material owns the ink that is legible on it, so `.act` never has to
     name a colour. */
  color: var(--ink-on-wool);
  /* No border: wool has no drawn edge. The cast shadow separates it from
     the tray behind it and the faint warm halo is the fibres standing off
     the silhouette — the closest a rounded rectangle gets to being fuzzy. */
  box-shadow: 0 3px 12px rgba(0, 0, 0, .5),
              0 0 10px rgba(248, 245, 240, .07);
}

/* `.act.wool` and not `.wool`, because the material is worn by things
   nobody presses: a message in a room is a plate of wool, and a plate that
   compresses while a thumb rests on it claims to be a control. */
.act.wool:active {
  /* Pressed is the light rolling over the top rather than the whole object
     dimming: the crown goes under, the near edge comes up. */
  --wool-body: linear-gradient(180deg, #d5cec2 0%, #f4f0e9 62%, #fffefb 100%);
  box-shadow: inset 0 2px 6px rgba(52, 40, 22, .3),
              0 2px 7px rgba(0, 0, 0, .5);
}

/* ── the material as an INK ───────────────────────────────────────────
   The same wool painted through the glyphs. Standalone, not a modifier of
   `.wool`: an object wants a cast shadow and a label colour, a word wants
   neither — and a word wants the fibres left off, which are lit specks that
   at 17px punch holes in a stroke rather than reading as fluff.

   A VEIL OVER THE SHEET, for the same reason `.surface-ink` has one:
   everywhere else the wind is the point and gets its full range, but inside
   a letter the dark seams break a stroke in half. So a near-opaque layer of
   the pale wool sits OVER the sheet and lets a fraction of it through.

   `background-color` is never transparent here: `--wool-tex` starts as
   plain white, so until it lands the base colour is what fills the glyphs.
   `color: transparent` with nothing painted behind it is invisible text,
   and that is the one way this construction fails badly. */
.wool-ink {
  background-color: var(--wool-pale);
  /* Front to back, so the veil is written first. */
  background-image:
    linear-gradient(var(--wool-ink-veil), var(--wool-ink-veil)),
    var(--wool-tex);
  background-size:
    auto,
    var(--wool-tile) var(--wool-tile);
  background-blend-mode:
    normal,
    multiply;
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  /* Safari needs the fill colour cleared as well as `color`; without it the
     glyphs paint solid over the clipped background. */
  -webkit-text-fill-color: transparent;
}

/* A forced-colours palette replaces backgrounds but not a transparent text
   fill, so a clipped word would come out invisible in exactly the mode
   somebody turned on to be able to read it. */
@media (forced-colors: active) {
  .wool-ink {
    background-image: none;
    -webkit-text-fill-color: revert;
    color: revert;
  }
}
