/* ============================================================
   FURNITURE — real objects, drawn in CSS.

   These used to be flat rounded bars with the name printed across them,
   which is exactly why they read as "a big label you put things into"
   rather than furniture. Each kind now has actual structure: a fridge with
   a door seam and a handle, a slatted crate, a chest with a lid and hasp,
   a pegboard with holes, a glass case with panes.

   How a piece is built:
     .furn            the carcass — body colour, edges, shadow
     .furn::before    the STRUCTURE layer (seams, slats, panes, lid, holes)
     .furn::after     the HARDWARE layer (handle, hasp, knob, latch)
     .flabel          a small plate near the bottom, not the whole object

   Kind classes are `.k-<kind>` where <kind> is `kind` in data/rooms.json.
   Adding a kind there requires adding a skin here — validate.js checks the
   pair and refuses to boot if they disagree.
============================================================ */
.furn{
  position:absolute;z-index:4;
  border-radius:4px;
  border:1px solid rgba(0,0,0,.45);
  box-shadow:
    0 6px 12px rgba(0,0,0,.4),
    inset 0 1px 0 rgba(255,255,255,.18),
    inset 0 -2px 4px rgba(0,0,0,.28);
  cursor:pointer;
  display:flex;align-items:flex-end;justify-content:center;
  /* Lets everything inside size against THIS box rather than a fixed px
     value, so labels stay proportional at any zoom and on any screen. */
  container-type:size;
  /* NO overflow:hidden here. The badge strip deliberately sits ABOVE the
     furniture (top:-24cqh), so clipping the box hides the icons that tell
     you what's inside. Only the name plate clips — see .flabel. */
  isolation:isolate;
}
.furn::before,.furn::after{content:"";position:absolute;pointer-events:none}
/* structure fills the piece; hardware sits on top of it */
.furn::before{inset:0;z-index:1}
.furn::after{z-index:2}

/* ---------- NAME PLATE ----------
   A small plate low on the piece, the way a real drawer label sits — not
   the object's entire identity. */
/* HOW MANY CHARACTERS ACTUALLY FIT.

   "The Weather Station" showed as "THE / WE…" and "The Deep Sky Drawer" as
   "THE DEEP SKY…". Four things were each costing characters, and they
   compounded:

     1. The type was sized off container HEIGHT alone (17cqh) and capped at
        9.5px. On a tall narrow piece — a fridge, a glass case — that is a big
        type size in a plate barely wider than three letters, so the name
        broke after the first word and the second line ellipsised. Sizing off
        `min(cqh, cqi)` ties the type to whichever dimension is actually
        scarce, which is the one that decides how much text fits.
     2. Two lines. A three-word name has no chance in two lines at any size
        that is still legible; three lines is one more word for free, and the
        plate is small enough that the extra line costs the furniture nothing.
     3. The plate wasted 8% of the face on margins and another 8% on its own
        padding. 1% and 3% now — the same visual inset, a fraction of the
        cost. It is that tight because of exactly one label: "Unexplained" is
        the only word in the game long enough that the plate could not hold it
        whole, and it was being sliced as "UNEXPLAINE / D". Two percent more
        plate is cheaper than making every label in the game smaller to fix
        one of them.
     4. letter-spacing .03em on a plate this narrow is a whole character every
        two lines. Gone, and the leading is tighter with it.

   buildRoomEl() in js/main.js drops a leading "The " before it ever gets
   here, which is the fifth. Together it roughly doubles what you can read
   without touching a single name in data/rooms.json. */
.furn .flabel{
  position:relative;z-index:3;
  margin-bottom:5cqh;
  max-width:99%;
  font-size:clamp(4px, min(15cqh, 13cqi), 8.5px);
  font-weight:800;letter-spacing:0;text-transform:uppercase;
  text-align:center;line-height:1.05;
  padding:1.5cqh 1.5%;
  border-radius:2px;
  color:rgba(255,255,255,.94);
  background:rgba(0,0,0,.34);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.14), 0 1px 2px rgba(0,0,0,.35);
  text-shadow:0 1px 2px rgba(0,0,0,.65);
  pointer-events:none;
  overflow:hidden;
  display:-webkit-box;
  -webkit-line-clamp:3;
  -webkit-box-orient:vertical;
  /* A word longer than the plate used to be sliced mid-letter with nothing to
     show for it ("INSTRUMEN CASE" on a narrow glass case). Let it break. */
  overflow-wrap:anywhere;
}

.furn .badges{
  /* top was a fixed -15px, which drifted further from the furniture as the
     room scaled up. Proportional now. */
  position:absolute;top:-24cqh;left:0;right:0;height:22cqh;min-height:12px;
  display:flex;justify-content:center;align-items:flex-end;gap:1px;
  font-size:clamp(7px, 30cqh, 13px);line-height:1;
  pointer-events:none;white-space:nowrap;overflow:visible;z-index:4;
}
.furn .badges span{filter:drop-shadow(0 1px 1px rgba(0,0,0,.4))}
.furn .badges span.gold{
  filter:drop-shadow(0 0 3px rgba(245,197,66,1)) drop-shadow(0 0 6px rgba(245,197,66,.8));
}
/* Something in here doesn't live here. Same faint red as the cells inside
   (css/container.css), so the mark means one thing in both views. */
.furn .badges span.wrong{
  background:rgba(196,74,62,.42);
  border-radius:3px;
  box-shadow:0 0 0 1px rgba(226,110,96,.55);
}

/* ---------- STATES ---------- */
.furn.aura{
  box-shadow:0 0 14px 4px rgba(245,197,66,.75), 0 6px 12px rgba(0,0,0,.4);
  border-color:rgba(245,197,66,.9);
}
.furn.drophot{box-shadow:0 0 0 3px rgba(245,197,66,.75), 0 6px 12px rgba(0,0,0,.4)}

/* ---------- THE HOLDALL BOX ----------
   The one piece of furniture in the room that is not part of the house. It
   stands on the floor like everything else, placed once per room and shoving
   the clutter aside as it lands (bagEnsureSpot in js/main.js), and it is a drop
   target and a tap target exactly like a cupboard.

   SIZED IN ROOM PERCENTAGES, like .furn and .cache, because `room.bagSlot` is
   a KEEP-OUT with those exact coordinates (onHoldall in js/geometry.js) and a
   box drawn at some other size would drift from the rectangle the floor search
   believes is reserved. It was a fixed pixel size at first, painted over the
   floor rather than standing in it — and 71% of it was covered by clutter that
   swallowed the tap.

   `container-type:size` so the icon and the count scale with the box, the same
   trick .cache uses: the room's own fit scale means a percentage box is a
   different number of pixels in a small room.

   Blue, and the only blue thing on any floor. It shares the panel's colours
   (css/layout.css #bagPanel) so the box you tap and the panel it opens are
   visibly the same object — every other container in the game is wood. */
.bagbox{
  position:absolute;z-index:5;cursor:pointer;
  container-type:size;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2cqh;
  background:linear-gradient(#4a5a6e,#33404f);
  border:2px solid #26303b;border-radius:8px;
  box-shadow:0 4px 8px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,255,255,.14);
}
.bagbox .bagico{font-size:clamp(11px, 46cqh, 26px);line-height:1}
.bagbox .bagpips{
  font-size:clamp(7px, 20cqh, 12px);line-height:1;
  font-weight:800;letter-spacing:.04em;color:var(--gold);opacity:.95;
}
.bagbox.drophot{box-shadow:0 0 0 3px rgba(245,197,66,.8), 0 4px 8px rgba(0,0,0,.45)}
.bagbox.fullhit{animation:furnfull .4s}
/* Something went in. The lid-thump equivalent of .furn's gold flash — this box
   has no notion of right or wrong, so it acknowledges rather than judges. */
.bagbox.bagpop{animation:bagpop .38s ease-out}
@keyframes bagpop{
  0%  {transform:scale(1)}
  40% {transform:scale(1.12)}
  100%{transform:scale(1)}
}
@media (prefers-reduced-motion:reduce){
  .bagbox.bagpop{animation:none}
}
.furn.goldhit{animation:furngold .9s}
@keyframes furngold{20%{box-shadow:0 0 26px 9px rgba(245,197,66,.95)}}
.furn.pophit{animation:furnpop .28s}
@keyframes furnpop{40%{transform:scale(1.07)}}
.furn.fullhit{animation:furnfull .4s}
@keyframes furnfull{25%{transform:translateX(-4px)}60%{transform:translateX(4px)}}
/* Sixth Sense: "this is where the thing in your hand lives."

   This used to be an endless 1.1s pulse, which meant that from the moment
   you picked something up its home container strobed until your hands were
   empty — reads as a broken container, not a hint. It's a steady ring now.

   Cool white-blue on purpose: gold in this game means DONE, and a hint
   wearing the same colour as a completed container is ambiguous. Also
   static rather than animated because renderRoom() rebuilds these elements
   constantly, so any one-shot intro animation would restart on every
   repaint — which is how you get a strobe back by accident. */
.furn.sense{
  box-shadow:
    0 0 0 2px rgba(198,232,255,.95),
    0 0 16px 5px rgba(150,205,255,.55),
    0 6px 12px rgba(0,0,0,.4);
  border-color:rgba(198,232,255,.9);
}

/* Key-locked: solid gold edge, and the badge shows the key it wants. */
.furn.flocked{
  filter:saturate(.5) brightness(.8);
  border-color:rgba(245,197,66,.55);
}
/* Quest-sealed: no keyhole exists for this one, so it must not look like the
   above. The dashed edge and the cool tint carry that on their own —
   it used to pulse as well, and the rule now is that nothing on the board
   animates forever. Doors that lead somewhere new are the one exception, and
   they stop the moment you walk through them. */
.furn.fsealed{
  border:2px dashed rgba(190,210,235,.72);
  filter:saturate(.35) brightness(.78);
}
.furn .badges .pips{display:flex;align-items:center;gap:3px;margin-left:2px}
.pips i{
  width:5px;height:5px;border-radius:50%;
  background:rgba(245,197,66,.25);
  display:block;
}
.pips i.full{background:var(--gold);box-shadow:0 0 4px rgba(245,197,66,.9)}

/* ============================================================
   KINDS
============================================================ */

/* ---------- STEEL — a two-door fridge / metal cabinet ---------- */
.k-steel{
  background:
    linear-gradient(90deg, rgba(255,255,255,.22) 0 6%, rgba(255,255,255,0) 22%),
    linear-gradient(#e2e8ec, #b6c0c6 55%, #98a3aa);
  border-color:#6f7a81;
}
/* horizontal door seam across the whole face */
.k-steel::before{
  background:
    linear-gradient(rgba(0,0,0,.28), rgba(0,0,0,.28)) 0 38%/100% 2px no-repeat,
    linear-gradient(rgba(255,255,255,.45), rgba(255,255,255,.45)) 0 calc(38% + 2px)/100% 1px no-repeat;
}
/* vertical chrome handle, right of the seam */
.k-steel::after{
  right:9%;top:20%;height:56%;width:3.5%;min-width:2px;
  border-radius:2px;
  background:linear-gradient(90deg,#f4f7f9,#aab4ba);
  box-shadow:0 1px 2px rgba(0,0,0,.45);
}
.k-steel .flabel{color:#262e33;background:rgba(255,255,255,.5);text-shadow:0 1px 0 rgba(255,255,255,.6)}

/* ---------- WOOD — a chest of drawers ---------- */
.k-wood{
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.05) 0 3px, rgba(255,255,255,.03) 3px 7px),
    linear-gradient(#8a613a,#6a4629 60%,#573820);
  border-color:#432c18;
}
/* three drawer fronts */
.k-wood::before{
  background:
    linear-gradient(rgba(0,0,0,.42),rgba(0,0,0,.42)) 0 33%/100% 2px no-repeat,
    linear-gradient(rgba(255,255,255,.16),rgba(255,255,255,.16)) 0 calc(33% + 2px)/100% 1px no-repeat,
    linear-gradient(rgba(0,0,0,.42),rgba(0,0,0,.42)) 0 66%/100% 2px no-repeat,
    linear-gradient(rgba(255,255,255,.16),rgba(255,255,255,.16)) 0 calc(66% + 2px)/100% 1px no-repeat;
}
/* brass pull on the top drawer */
.k-wood::after{
  left:50%;top:16%;transform:translateX(-50%);
  width:22%;height:8%;min-height:2px;border-radius:999px;
  background:linear-gradient(#e6c079,#a9813c);
  box-shadow:0 1px 2px rgba(0,0,0,.5);
}

/* ---------- SLAT — an open produce crate ---------- */
.k-slat{
  background:linear-gradient(#a8794c,#8a5f3a);
  border:1px solid #5e4126;
  border-width:1px 4% 6% 4%;
  border-radius:2px;
}
/* horizontal slats with gaps you can see between */
.k-slat::before{
  background:repeating-linear-gradient(
    180deg,
    #b3835a 0 22%,
    rgba(40,24,10,.85) 22%, rgba(40,24,10,.85) 30%
  );
}
/* corner post down the left edge */
.k-slat::after{
  left:0;top:0;bottom:0;width:7%;
  background:linear-gradient(90deg,#6e4a2b,#8a5f3a);
  box-shadow:inset -1px 0 2px rgba(0,0,0,.4);
}

/* ---------- WICKER — a woven basket, tapering ---------- */
.k-wicker{
  background:
    repeating-linear-gradient(46deg,#cda667 0 5px,#b58c4e 5px 10px),
    repeating-linear-gradient(-46deg,rgba(0,0,0,.10) 0 5px,rgba(255,255,255,.06) 5px 10px);
  border-color:#8a683a;
  border-radius:3px 3px 12% 12%;
}
/* rim band around the top */
.k-wicker::before{
  background:linear-gradient(#e0bd82,#c6a165) 0 0/100% 16% no-repeat;
  box-shadow:inset 0 16% 0 -14% rgba(0,0,0,.25);
}
.k-wicker .flabel{color:#3a2a10;background:rgba(255,255,255,.42);text-shadow:0 1px 0 rgba(255,255,255,.5)}

/* ---------- DARK — a treasure chest with a domed lid and hasp ---------- */
.k-dark{
  background:linear-gradient(#4e3d43,#372a2f 60%,#281e22);
  border-color:#1d1417;
  border-radius:8% 8% 3px 3px;
}
/* lid band + the iron strap down the middle */
.k-dark::before{
  background:
    linear-gradient(#6a545c,#4a3a41) 0 0/100% 34% no-repeat,
    linear-gradient(rgba(0,0,0,.55),rgba(0,0,0,.55)) 0 34%/100% 3px no-repeat,
    linear-gradient(90deg,transparent 44%, rgba(196,160,92,.55) 44% 56%, transparent 56%);
}
/* brass hasp hanging over the seam */
.k-dark::after{
  left:50%;top:26%;transform:translateX(-50%);
  width:16%;height:22%;min-width:6px;min-height:5px;
  border-radius:2px;
  background:linear-gradient(#e3c07a,#a37f38);
  box-shadow:0 1px 3px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.4);
}

/* ---------- GLASS — a display case with panes ---------- */
.k-glass{
  background:linear-gradient(rgba(214,238,247,.5),rgba(150,196,214,.42));
  border-color:rgba(120,160,175,.85);
  backdrop-filter:blur(1px);
}
/* mullions: one vertical, one horizontal, plus a diagonal highlight */
.k-glass::before{
  background:
    linear-gradient(rgba(255,255,255,.5),rgba(255,255,255,.5)) 50% 0/2px 100% no-repeat,
    linear-gradient(rgba(255,255,255,.5),rgba(255,255,255,.5)) 0 46%/100% 2px no-repeat,
    linear-gradient(118deg, rgba(255,255,255,.5) 0 14%, transparent 15% 44%, rgba(255,255,255,.26) 45% 52%, transparent 53%);
}
/* thin metal frame edge */
.k-glass::after{
  inset:0;border:1px solid rgba(255,255,255,.45);border-radius:inherit;
}
.k-glass .flabel{color:#153039;background:rgba(255,255,255,.55);text-shadow:0 1px 0 rgba(255,255,255,.6)}

/* ---------- PLASTIC — a stacking tub with a ribbed lid ---------- */
.k-plastic{
  background:linear-gradient(#63b6ae,#4d9088 60%,#3d7871);
  border-color:#2c5a55;
  border-radius:5px;
}
/* lid across the top, plus moulded ribs below it */
.k-plastic::before{
  background:
    linear-gradient(#7fcfc6,#5aa9a1) 0 0/100% 26% no-repeat,
    linear-gradient(rgba(0,0,0,.35),rgba(0,0,0,.35)) 0 26%/100% 2px no-repeat,
    repeating-linear-gradient(90deg, transparent 0 12%, rgba(0,0,0,.10) 12% 14%);
}
/* side clip latch */
.k-plastic::after{
  right:6%;top:16%;
  width:9%;height:16%;min-width:4px;min-height:4px;
  border-radius:2px;
  background:linear-gradient(#8fdcd3,#4f938b);
  box-shadow:0 1px 2px rgba(0,0,0,.45);
}

/* ---------- PEG — a pegboard with holes and a tool rail ---------- */
.k-peg{
  background:linear-gradient(#c98a4b,#ad7239);
  border-color:#7d5327;
  border-radius:2px;
}
/* the hole grid */
.k-peg::before{
  background:
    radial-gradient(circle at 3px 3px, rgba(0,0,0,.42) 1.4px, transparent 1.8px) 0 0/9px 9px,
    radial-gradient(circle at 3px 3px, rgba(255,255,255,.20) 1.9px, transparent 2.2px) 0 0/9px 9px;
}
/* rail along the bottom */
.k-peg::after{
  left:0;right:0;bottom:0;height:14%;
  background:linear-gradient(#8a5a28,#6d451e);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.2);
}

/* ============================================================
   WORLD KINDS — hull, arcane, mesh

   A theme repaints the WALLS and nothing else (css/themes.css), which is
   correct: the HUD, the gold and the furniture are what stay put while the
   world changes. The cost is that a wizard's rune cabinet drawn as .k-wood is
   a chest of drawers standing in a purple room, and the player reads that as
   the same house with the lights off. These three are the smallest number of
   skins that give the ship, the tower and the zoo a silhouette of their own;
   the frat deliberately gets NONE, because a frat house is a house somebody
   wrecked and reusing the domestic furniture is the joke.
============================================================ */

/* ---------- HULL — a bulkhead locker, matte alloy and rivets ---------- */
.k-hull{
  background:
    linear-gradient(90deg, rgba(180,255,240,.10) 0 8%, rgba(255,255,255,0) 26%),
    linear-gradient(#7d8f92,#5c6d70 58%, #47585b);
  border-color:#31403f;
}
/* rivet line down each side, and a recessed centre panel */
.k-hull::before{
  background:
    radial-gradient(circle, rgba(255,255,255,.34) 1.1px, transparent 1.6px) 8% 0/100% 15%,
    radial-gradient(circle, rgba(255,255,255,.34) 1.1px, transparent 1.6px) 92% 0/100% 15%,
    linear-gradient(rgba(0,0,0,.16), rgba(0,0,0,.16)) 50% 50%/74% 62% no-repeat;
}
/* a lever latch, horizontal, low */
.k-hull::after{
  left:22%;bottom:16%;width:56%;height:6%;min-height:2px;
  border-radius:1px;
  background:linear-gradient(#cfe6e2,#7d9a95);
  box-shadow:0 1px 2px rgba(0,0,0,.5);
}
.k-hull .flabel{color:#0d1a1a;background:rgba(190,225,220,.62);text-shadow:none}

/* ---------- ARCANE — a rune cabinet: old wood with a lit band ---------- */
.k-arcane{
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.06) 0 4px, rgba(255,255,255,.02) 4px 9px),
    linear-gradient(#4a3663,#33244a 60%,#241a36);
  border-color:#191029;
}
/* the band of runes across the middle — the only lit thing on the piece */
.k-arcane::before{
  background:
    repeating-linear-gradient(90deg,
      rgba(198,160,255,.72) 0 3px, transparent 3px 8px,
      rgba(198,160,255,.40) 8px 10px, transparent 10px 17px) 0 46%/100% 9% no-repeat,
    linear-gradient(rgba(0,0,0,.34), rgba(0,0,0,.34)) 0 62%/100% 2px no-repeat;
  filter:drop-shadow(0 0 3px rgba(170,120,255,.55));
}
/* a small ring pull, centred high */
.k-arcane::after{
  left:50%;top:14%;transform:translateX(-50%);
  width:13%;height:13%;min-height:3px;border-radius:50%;
  border:1.5px solid rgba(214,186,255,.75);
  box-shadow:0 0 5px rgba(170,120,255,.5);
}

/* ---------- MESH — a wire cage ---------- */
.k-mesh{
  background:linear-gradient(rgba(30,34,28,.62), rgba(20,24,19,.72));
  border:1px solid #2b3327;
  border-width:5% 4%;
  border-radius:3px;
}
/* the wire itself: a real grid, so you can see the room through it */
.k-mesh::before{
  background:
    repeating-linear-gradient(0deg, rgba(214,224,206,.44) 0 1px, transparent 1px 9px),
    repeating-linear-gradient(90deg, rgba(214,224,206,.44) 0 1px, transparent 1px 9px);
}
/* hasp and hinge on the right edge */
.k-mesh::after{
  right:6%;top:32%;height:32%;width:5%;min-width:2px;
  border-radius:2px;
  background:linear-gradient(#d8ddd2,#8d968a);
  box-shadow:0 1px 2px rgba(0,0,0,.5);
}
.k-mesh .flabel{background:rgba(0,0,0,.52)}

/* ============================================================
   SHAPE KINDS — basin, tub, shelf, hook, bin, heap, frost, tank,
                 table, cubby, stand, couch

   The first eleven kinds are MATERIALS: steel, wood, wicker, glass. That is a
   real axis and it was the right first one, but it runs out the moment a room
   holds a fridge AND a sink and both of them are the steel skin — which is
   exactly what shipped. Two identical grey boxes in one room means the player
   is reading a name plate to tell furniture apart, and the whole reason these
   are drawn objects rather than labelled bars is so they don't have to.

   So this wave is drawn from the container's NAME instead of its material: a
   sink has a tap, a bin has a lid, a hook rail has hooks, a heap has no
   straight edge anywhere on it. `.flabel` moves off the bottom on the kinds
   whose bottom edge isn't solid (a table's legs, a hook rail's hooks), because
   a name plate floating in the gap under a tabletop reads as a bug.

   The rule they exist to make possible: NO TWO CONTAINERS IN ONE ROOM SHARE A
   KIND. validate.js warns when they do.
============================================================ */

/* ---------- BASIN — a sink unit: cabinet, bowl, tap ----------
   The one this wave was named for. "Under the Sink" and "The Sink" were both
   drawn as .k-steel, which is the FRIDGE skin, so the bathroom and the frat
   kitchen each had a sink that was a refrigerator with a different word on it. */
.k-basin{
  background:linear-gradient(#eef2f3,#d3dbdd 46%,#b9c3c6);
  border-color:#8d989b;
  border-radius:3px;
}
/* THE BOWL HAS TO BE THE DARKEST THING ON THE PIECE. The first pass drew it
   at .55 alpha and it read as a smudge on a grey cabinet, which is how a sink
   ends up looking like a toolbox. */
.k-basin::before{
  background:
    radial-gradient(ellipse 40% 86% at 50% 52%, rgba(28,42,48,.92) 0 62%, rgba(28,42,48,.55) 78%, transparent 84%) 0 4%/100% 46% no-repeat,
    linear-gradient(rgba(255,255,255,.85),rgba(255,255,255,.85)) 0 50%/100% 2px no-repeat,
    linear-gradient(rgba(0,0,0,.34),rgba(0,0,0,.34)) 0 52%/100% 2px no-repeat,
    linear-gradient(90deg,transparent 48%, rgba(0,0,0,.26) 49% 51%, transparent 52%) 0 54%/100% 46% no-repeat;
}
/* The tap, in four parts, because an outline of a rounded rectangle is a
   HANDLE and that is exactly what the first pass drew: an upstand, a spout arm
   reaching out over the bowl, and two taps either side of it. */
.k-basin::after{
  inset:0;
  background:
    linear-gradient(#f4f9fa,#b4c2c6) 50% 3%/4.5% 17% no-repeat,
    linear-gradient(#f0f6f7,#c0ccd0) 50% 17%/17% 4.5% no-repeat,
    radial-gradient(circle at 50% 50%, #f0f6f7 0 44%, transparent 48%) 33% 8%/9% 9% no-repeat,
    radial-gradient(circle at 50% 50%, #f0f6f7 0 44%, transparent 48%) 67% 8%/9% 9% no-repeat;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.45));
}
.k-basin .flabel{color:#283436;background:rgba(255,255,255,.62);text-shadow:0 1px 0 rgba(255,255,255,.6)}

/* ---------- TUB — a freestanding bath, rolled rim and feet ----------
   "How is a tub not part of a Cleansing Apparatus?" was a taxonomy bug (the
   robot had it filed under Comfort Objects) and it needed a skin as well: the
   bath now lives with the soap and looks like a bath. */
.k-tub{
  background:linear-gradient(#f6f8f8,#dfe6e6 52%,#c4cdcd);
  border-color:#98a4a4;
  border-radius:10px 10px 26% 26%/8px 8px 60% 60%;
}
/* rolled rim, then the water sheen down inside it */
.k-tub::before{
  border-radius:inherit;
  background:
    linear-gradient(#ffffff,#e4ebeb) 0 0/100% 22% no-repeat,
    linear-gradient(rgba(0,0,0,.26),rgba(0,0,0,.26)) 0 22%/100% 2px no-repeat,
    linear-gradient(160deg, rgba(150,205,215,.55) 0 40%, rgba(190,225,232,.3) 41% 100%) 0 24%/100% 76% no-repeat;
}
/* a tap at one end, and a pair of feet peeking out under the belly */
.k-tub::after{
  left:8%;top:4%;
  width:7%;height:16%;min-width:3px;min-height:3px;
  border-radius:2px 2px 0 0;
  background:linear-gradient(#e9d9a8,#b99a56);
  box-shadow:
    0 1px 2px rgba(0,0,0,.5),
    9px  calc(100cqh - 6px) 0 0 rgba(120,130,130,.9),
    calc(100cqw - 26px) calc(100cqh - 6px) 0 0 rgba(120,130,130,.9);
}
.k-tub .flabel{color:#23302f;background:rgba(255,255,255,.66);text-shadow:0 1px 0 rgba(255,255,255,.6)}

/* ---------- SHELF — open shelving: two uprights, three boards ----------
   The carcass is the DARK GAP, not the wood: an open shelf is defined by being
   able to see past it, so the boards are painted on top of a recess rather than
   the other way round. */
.k-shelf{
  /* Not black: at in-room size the recess is most of the piece, and at .88 it
     read as a void with a frame round it rather than shelving you can see the
     back of. */
  background:linear-gradient(rgba(40,31,21,.74),rgba(26,20,13,.80));
  border-color:#4a341d;
  border-radius:2px;
}
/* three boards, evenly spaced, each with a lit front edge */
.k-shelf::before{
  background:
    linear-gradient(#c1925c,#8d6337) 0 3%/100% 12% no-repeat,
    linear-gradient(#c1925c,#8d6337) 0 43%/100% 12% no-repeat,
    linear-gradient(#c1925c,#8d6337) 0 84%/100% 14% no-repeat,
    linear-gradient(rgba(255,255,255,.22),rgba(255,255,255,.22)) 0 4%/100% 1px no-repeat,
    linear-gradient(rgba(255,255,255,.22),rgba(255,255,255,.22)) 0 44%/100% 1px no-repeat,
    linear-gradient(rgba(255,255,255,.22),rgba(255,255,255,.22)) 0 84%/100% 1px no-repeat;
}
/* the uprights holding them up */
.k-shelf::after{
  inset:0;
  background:
    linear-gradient(#a9793f,#7d5227) 0 0/7% 100% no-repeat,
    linear-gradient(#a9793f,#7d5227) 100% 0/7% 100% no-repeat;
}

/* ---------- HOOK — a wall rail with hooks hanging off it ----------
   Shallow on purpose: the thing on the wall is a board, and the depth in the
   silhouette is the hooks. */
.k-hook{
  background:linear-gradient(#9d6f42,#7c5430);
  border-color:#553618;
  border-radius:2px;
}
/* grain plus the moulded top edge of the board */
.k-hook::before{
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.07) 0 5px, rgba(255,255,255,.04) 5px 11px),
    linear-gradient(rgba(255,255,255,.26),rgba(255,255,255,.26)) 0 0/100% 14% no-repeat,
    linear-gradient(rgba(0,0,0,.30),rgba(0,0,0,.30)) 0 16%/100% 2px no-repeat;
}
/* THE HOOKS ARE THE WHOLE KIND, so they are drawn as one element cloned by
   box-shadow rather than carved out of a stripe field with mask() — that first
   version rendered as four barely-visible slivers. The offsets are in `cqw`,
   which resolves against .furn's own box (it sets container-type:size), so the
   spacing holds at any zoom and any room scale. Same idiom as the tub's feet. */
.k-hook::after{
  left:10%;bottom:-30%;
  width:3.6%;height:36%;min-width:2px;min-height:5px;
  border-radius:1px 1px 999px 999px;
  background:linear-gradient(#f0d094,#a97f38);
  box-shadow:
    17.5cqw 0 0 0 #d9b473,
    35cqw   0 0 0 #d9b473,
    52.5cqw 0 0 0 #d9b473,
    70cqw   0 0 0 #d9b473,
    0 1px 2px rgba(0,0,0,.55);
}
/* the bottom edge is hooks, not carcass — the plate belongs up on the board */
.k-hook .flabel{margin-bottom:auto;margin-top:24cqh}

/* ---------- BIN — a lidded bin, narrow and slightly tapered ---------- */
.k-bin{
  background:linear-gradient(90deg, rgba(255,255,255,.14) 0 12%, transparent 30%),
             linear-gradient(#5d6a72,#47535a 60%,#37424a);
  border-color:#232c32;
  border-radius:4px 4px 12% 12%;
}
/* the lid, the dark gap under it, and vertical body ribs */
.k-bin::before{
  background:
    linear-gradient(#8d9ca4,#6a7981) 0 0/100% 19% no-repeat,
    linear-gradient(rgba(0,0,0,.72),rgba(0,0,0,.72)) 0 19%/100% 3px no-repeat,
    linear-gradient(rgba(255,255,255,.18),rgba(255,255,255,.18)) 0 calc(19% + 3px)/100% 1px no-repeat,
    repeating-linear-gradient(90deg, transparent 0 24%, rgba(0,0,0,.20) 24% 28%) 0 24%/100% 76% no-repeat;
}
/* THE OVERHANGING RIM IS WHAT MAKES IT A BIN. A lid painted flush inside the
   box is a seam, and a seam on a grey box is a cabinet — which is what the
   first pass looked like beside the steel fridge. This one sticks out past both
   sides, so the silhouette says lid before any of the shading does. */
.k-bin::after{
  left:-6%;right:-6%;top:-5%;height:10%;min-height:3px;
  border-radius:2px;
  background:linear-gradient(#a6b4bb,#74838b);
  box-shadow:0 2px 3px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.3);
}

/* ---------- HEAP — a pile. No straight edge anywhere on it ----------
   For every container whose name is a confession: The Clean-ish Pile, The
   Blanket Heap, The Charging Pile, Dry Feed Sacks. A pile drawn as a cabinet
   is the joke landing upside down. */
.k-heap{
  background:linear-gradient(#8e7a63,#6d5c48 60%,#544738);
  border-color:rgba(0,0,0,.35);
  /* deliberately lopsided: a symmetrical mound reads as a loaf */
  border-radius:52% 44% 16% 20% / 78% 68% 16% 18%;
  box-shadow:0 5px 10px rgba(0,0,0,.45), inset 0 2px 0 rgba(255,255,255,.14);
}
/* more lumps under the first, so the mass reads as several things */
.k-heap::before{
  border-radius:inherit;
  background:
    radial-gradient(ellipse 42% 60% at 26% 44%, rgba(255,255,255,.16), transparent 70%),
    radial-gradient(ellipse 36% 52% at 74% 58%, rgba(0,0,0,.22), transparent 72%),
    radial-gradient(ellipse 60% 30% at 50% 96%, rgba(0,0,0,.35), transparent 75%);
}
/* one thing sticking out of it, which is what makes it a pile of SOMETHING */
.k-heap::after{
  right:12%;top:-8%;
  width:16%;height:34%;min-width:3px;
  border-radius:999px;
  background:linear-gradient(#a4917a,#7a6a56);
  transform:rotate(24deg);
  box-shadow:0 1px 2px rgba(0,0,0,.4);
}

/* ---------- FROST — a chest freezer, lid seam and frost ---------- */
.k-frost{
  background:linear-gradient(#f2f8fa,#dae9ef 50%,#bed3dc);
  border-color:#8fa8b3;
  border-radius:3px;
}
/* the lid across the top, its gasket, and frost speckling the body */
.k-frost::before{
  background:
    linear-gradient(#ffffff,#e6f2f6) 0 0/100% 30% no-repeat,
    linear-gradient(rgba(120,160,175,.75),rgba(120,160,175,.75)) 0 30%/100% 2px no-repeat,
    radial-gradient(circle, rgba(255,255,255,.95) 1.1px, transparent 1.5px) 0 0/8px 8px,
    radial-gradient(circle, rgba(190,225,238,.7) 1.6px, transparent 2px) 4px 4px/13px 13px;
}
/* the temperature strip: the one cold-blue accent on the piece */
.k-frost::after{
  left:10%;bottom:16%;
  width:34%;height:12%;min-height:3px;
  border-radius:2px;
  background:linear-gradient(90deg,#7fd6f5,#3f9fc9);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.6), 0 1px 2px rgba(0,0,0,.3);
}
.k-frost .flabel{color:#1d3138;background:rgba(255,255,255,.66);text-shadow:0 1px 0 rgba(255,255,255,.7)}

/* ---------- TANK — a glass vivarium: mesh lid, substrate, water line ---------- */
.k-tank{
  background:linear-gradient(rgba(196,226,222,.34),rgba(140,186,190,.30));
  border:1px solid rgba(110,150,150,.9);
  border-radius:2px;
  backdrop-filter:blur(1px);
}
/* mesh lid on top, substrate in the bottom, one glass highlight across it */
.k-tank::before{
  background:
    repeating-linear-gradient(90deg, rgba(90,105,100,.85) 0 1px, transparent 1px 4px) 0 0/100% 13% no-repeat,
    linear-gradient(rgba(70,84,80,.9),rgba(70,84,80,.9)) 0 13%/100% 2px no-repeat,
    linear-gradient(#9a7f56,#7a6340) 0 100%/100% 16% no-repeat,
    linear-gradient(124deg, rgba(255,255,255,.42) 0 12%, transparent 13% 46%, rgba(255,255,255,.20) 47% 54%, transparent 55%);
}
/* the frame, which is what stops it reading as a pane of nothing */
.k-tank::after{
  inset:0;border:2px solid rgba(120,148,148,.75);border-radius:inherit;
}
.k-tank .flabel{color:#12292b;background:rgba(255,255,255,.55);text-shadow:0 1px 0 rgba(255,255,255,.55)}

/* ---------- TABLE — a top on legs, open underneath ---------- */
.k-table{
  background:transparent;
  border-color:transparent;
  box-shadow:none;
  border-radius:0;
}
/* the top plank and its lit front edge; the legs are ::after */
.k-table::before{
  background:
    linear-gradient(#a87c4c,#8a6136) 0 0/100% 26% no-repeat,
    linear-gradient(rgba(255,255,255,.30),rgba(255,255,255,.30)) 0 24%/100% 1px no-repeat,
    linear-gradient(rgba(0,0,0,.45),rgba(0,0,0,.45)) 0 26%/100% 3px no-repeat;
  filter:drop-shadow(0 4px 6px rgba(0,0,0,.45));
}
/* two legs and the stretcher between them */
.k-table::after{
  inset:0;
  background:
    linear-gradient(#7e5730,#5f3f20) 6% 26%/9% 74% no-repeat,
    linear-gradient(#7e5730,#5f3f20) 94% 26%/9% 74% no-repeat,
    linear-gradient(#6b4926,#6b4926) 0 74%/100% 7% no-repeat;
}
/* there is no carcass at the bottom to print on — the plate sits on the top */
.k-table .flabel{margin-bottom:auto;margin-top:3cqh}

/* ---------- CUBBY — a grid of pigeonholes ----------
   Shoes, scrolls, wine, nest boxes, discs: everything that is stored one-per-
   slot rather than tipped into a box. */
.k-cubby{
  background:linear-gradient(#8d6a44,#6d5133);
  border-color:#412d18;
  border-radius:2px;
}
/* The holes, as two crossed stripe fields multiplied together. Both were at
   .88 alpha in the first pass, and multiplied that is effectively black — a
   dark grid, not furniture with recesses in it. At .5 the wood still shows
   through the shadow, which is what makes it read as depth. */
.k-cubby::before{
  background:
    repeating-linear-gradient(90deg, transparent 0 4%, rgba(30,20,10,.5) 4% 29%, transparent 29% 33%),
    repeating-linear-gradient(180deg, transparent 0 6%, rgba(30,20,10,.5) 6% 44%, transparent 44% 50%),
    /* a lit lip along the bottom of each row, so the shelves read as shelves */
    repeating-linear-gradient(180deg, transparent 0 42%, rgba(214,170,110,.35) 42% 45%, transparent 45% 50%);
}
/* the frame, so the grid reads as built rather than printed */
.k-cubby::after{
  inset:0;
  border:2px solid rgba(150,110,68,.85);
  border-radius:inherit;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.18);
}

/* ---------- STAND — a tall narrow upright: umbrellas, brooms, cues ---------- */
.k-stand{
  background:linear-gradient(90deg, rgba(255,255,255,.16) 0 14%, transparent 34%),
             linear-gradient(#6a5a48,#4d4134 62%,#3a3128);
  border-color:#241d16;
  border-radius:3px 3px 20% 20%;
}
/* open mouth at the top, a band round the middle, a flared foot. The mouth is
   near-opaque: an upright you cannot see INTO is a bollard. */
.k-stand::before{
  background:
    radial-gradient(ellipse 74% 100% at 50% 6%, rgba(8,6,4,.96) 0 58%, rgba(8,6,4,.6) 74%, transparent 82%) 0 0/100% 22% no-repeat,
    linear-gradient(rgba(0,0,0,.35),rgba(0,0,0,.35)) 0 52%/100% 3px no-repeat,
    linear-gradient(rgba(255,255,255,.14),rgba(255,255,255,.14)) 0 calc(52% + 3px)/100% 1px no-repeat,
    linear-gradient(#57493a,#40372c) 0 100%/100% 11% no-repeat;
}
/* Handles leaning out of the mouth — the reason it's a stand and not a pipe.
   Cloned in cqw like the hooks and the couch arms, so the pair keeps its gap
   however narrow the piece is drawn. */
.k-stand::after{
  /* They poke ABOVE the box, which is also where the badge strip lives
     (top:-24cqh). That is fine and deliberate: .badges is z-index 4 and
     ::after is 2, so a badge always paints over a handle rather than being
     hidden behind one. Kept short enough that the overlap reads as depth. */
  left:50%;top:-20%;
  width:11%;height:42%;min-width:3px;
  border-radius:999px;
  background:linear-gradient(#a08e70,#645843);
  transform:rotate(12deg);
  box-shadow:-38cqw 5cqw 0 0 rgba(140,124,98,.95), 0 1px 2px rgba(0,0,0,.5);
}

/* ---------- COUCH — back, seat, arms ---------- */
.k-couch{
  background:linear-gradient(#7a5b6b,#5d4351 58%,#48333e);
  border-color:#2d1f27;
  border-radius:8px 8px 4px 4px;
}
/* the back cushion, its seam, and the seat cushion below */
.k-couch::before{
  background:
    linear-gradient(#8f6c7d,#6d4f5d) 0 0/100% 42% no-repeat,
    linear-gradient(rgba(0,0,0,.40),rgba(0,0,0,.40)) 0 42%/100% 2px no-repeat,
    linear-gradient(90deg, transparent 49%, rgba(0,0,0,.30) 49.5% 50.5%, transparent 51%) 0 0/100% 42% no-repeat,
    linear-gradient(#8a6878,#664956) 0 46%/100% 40% no-repeat;
}
/* An arm at each end, rolled — drawn as one element cloned by box-shadow so
   both get a real border-radius. Painted as two background stripes they came
   out square and only a shade off the body, which read as a purple box. */
.k-couch::after{
  left:0;top:8%;width:15%;height:92%;
  border-radius:7px 7px 2px 2px;
  background:linear-gradient(#b18b99,#7d5b69);
  box-shadow:
    85cqw 0 0 0 #a37e8c,
    inset 0 1px 0 rgba(255,255,255,.26);
}

/* LABEL MAKER's ghost badges: what this container is still waiting for.
   Deliberately the faintest thing in the strip. The badges that mean "this is
   inside" are the primary read and these sit behind them — outlined rather
   than filled, so a want can never be mistaken for a have at a glance. */
.furn .badges span.want{
  opacity:.45;
  filter:grayscale(.85) drop-shadow(0 1px 1px rgba(0,0,0,.4));
}
