/* ky-picker — the world switcher's skin.
   ==========================================================================
   Lives inside #ky-sw-panel, which index.html styles inline (dark glass, 8px
   padding, .ky-row at 11px). Those rules are the house here; everything below
   either matches them or is scoped to .kyw-* so the legacy rows are untouched.

   The panel is the ONE control that is always on screen, so it stays visually
   quiet: a thumbnail, a name, a two-word note on what the world feels like.
   No ratios, no badges, no chevrons. The wallpapers do the selling. */

/* ---- hide the eighteen legacy palette rows ---------------------------------
   HIDDEN, NOT REMOVED. ky-themes.js enhance() bails unless the panel's row
   count still equals its own table length, and its correct() maps rows to
   themes BY INDEX — so deleting a row silently disables the switcher and the
   picker's own Honey & Ink path with it. display:none keeps the DOM order and
   the index mapping exactly as ky-themes expects while taking the long menu
   off screen. */
#ky-sw-panel.kyw-on > .ky-row:not(.kyw-row),
#ky-sw-panel.kyw-on > .ky-hd:not(.kyw-hd),
#ky-sw-panel.kyw-on > .ky-grp {
  display: none !important;
}

/* the mode row is ky-mode.js's wallmode toggle — the picker now owns that
   decision (choosing a world turns wallmode on, Honey & Ink turns it off), so
   leaving a second control for the same state would let the two disagree */
#ky-sw-panel.kyw-on > #ky-mode-row { display: none !important; }

#ky-sw-panel.kyw-on { min-width: 232px; }

.kyw-hd { margin-bottom: 4px; }

/* ---- a world row ---------------------------------------------------------
   display/cursor/radius are declared here rather than inherited. index.html
   carries .ky-row rules inline, but the world pages get a panel the picker
   builds for itself and there is no inline block there to lean on — without
   display:flex the thumbnails collapsed to slivers. Declaring them costs
   nothing on index (it already resolves to the same values) and makes the row
   correct wherever it is mounted. */
#ky-sw-panel .kyw-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: 8px;
  cursor: pointer;
  user-select: none;
  transition: background .18s ease;
}
#ky-sw-panel .kyw-row:hover { background: rgba(255, 255, 255, .08); }

/* the button on the picker's own panel already reads "World", so the section
   heading below it is a duplicate — only on that panel */
#ky-sw-panel.kyw-own .kyw-hd { display: none; }

/* ky-edit.js appends its owner-only "Edit availability" toggle to whatever
   #ky-sw-panel it finds. On index that is the owner's own control panel and it
   belongs there; on a world page it is landing in a panel the picker built for
   visitors, next to six wallpapers, where it means nothing. Scoped to .kyw-own
   so index is untouched. */
#ky-sw-panel.kyw-own > .ky-cal-devrow { display: none !important; }

/* 38x24 rather than the palette chips' 34x16: a photograph needs enough area
   to be recognisable at a glance, and recognition is the whole job here —
   these are read as pictures, not as swatches. */
.kyw-chip {
  flex: 0 0 auto;
  width: 38px;
  height: 24px;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, .22);
  background-size: cover;
  background-position: center;
  background-color: #14110A;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .35);
}

/* Honey & Ink has no photograph to show, so it shows the palette itself:
   ink, honey, cream, in the order the site uses them. */
.kyw-chip-ink {
  background-image: linear-gradient(90deg,
    #14110A 0 34%, #E3AC33 34% 67%, #F7EDD3 67% 100%);
}

.kyw-txt {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.kyw-name {
  font-weight: 700;
  font-size: 11.5px;
  line-height: 1.15;
  letter-spacing: .005em;
}
.kyw-sub {
  font-family: montrealMono, 'montrealMono Fallback', ui-monospace, monospace;
  font-size: 8.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: #8f8f8f;
  line-height: 1.2;
  text-decoration: none;
}
#ky-sw-panel .kyw-row.on .kyw-sub { color: #c9c9c9; }

/* The selected world gets a honey edge rather than a heavier fill: the fill is
   already carrying hover, and two brightness steps for two different states
   read as one noisy state. */
#ky-sw-panel .kyw-row.on {
  background: rgba(255, 255, 255, .13);
  box-shadow: inset 0 0 0 1px rgba(227, 172, 51, .55);
}
#ky-sw-panel .kyw-row.on .kyw-chip {
  border-color: rgba(227, 172, 51, .75);
}

#ky-sw-panel .kyw-row:focus-visible {
  outline: 1.5px solid rgba(255, 255, 255, .7);
  outline-offset: -2px;
}

/* ---- reduced motion ------------------------------------------------------
   The row transition is inherited from index.html's .ky-row (background .18s);
   nothing here adds motion, so there is only the inherited one to stop. */
@media (prefers-reduced-motion: reduce) {
  #ky-sw-panel .kyw-row { transition: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   2026-08-29 — THE PICKER BECOMES A REAL CONTROL

   Owner call, with a screenshot: "Update your theme picker properly."

   WHAT THE SCREENSHOT SHOWED, and why each fault is a fault and not a taste
   difference:

   1. TWO ROWS THAT DO NOT BELONG. Under the five worlds sat "Liquid type
      (goo + ink)" and, below it, a toggle with NO LABEL AT ALL. Both are real
      controls that leaked in:

        .ky-zine        index.html's honeykit filter switch
        .ky-cal-devrow  ky-cal2.js's OWNER-ONLY "Edit availability" switch

      The second is invisible rather than merely misplaced, and the cause is
      exact: #ky-sw sets no `color`, index.html's `.ky-row` sets color:#eee but
      .ky-cal-devrow is not a .ky-row, so its label inherits the PAGE's
      foreground — dark ink — and paints dark-on-dark inside a dark panel. It
      has been an unlabelled mystery switch on every world page since it
      shipped.

      It was already guarded — but only under `.kyw-own`, the class the picker
      puts on a panel IT BUILT. The world pages are built by copying
      index.html, which already carries #ky-sw-panel inline, so hostPanel()
      finds one and returns early: `.kyw-own` is never set there and the guard
      never fired on the five pages that needed it. The scope moves to
      `.kyw-on` — "the picker owns this panel's contents" — which is true on
      both the borrowed panel and the built one.

   2. THE TRIGGER SHOWED THE WRONG THING. #ky-sw-btn is three vertical stripes
      of the current PALETTE (bg / main / side) — correct for the eighteen-
      palette switcher this panel used to be, meaningless now that the thing
      being chosen is a world. It now shows the live world's own poster (see
      markTrigger() in ky-picker.js), so the closed state answers "which world
      am I in" and the open state answers "which others are there" in the same
      vocabulary: a picture, both times.

   3. THE PANEL WAS NOT MADE OF THE SITE'S MATERIAL. rgba(15,15,15,.94) over
      blur(10px) is a near-opaque slab; every other floating surface here
      (#ky-music, #ky-cal-panel, .lg-surface) is liquid glass. Those values are
      inline in index.html's <style> block, so beating them needs !important —
      that is what the declarations below are for. The recipe reads the SAME
      --lg-* custom properties liquid-glass.css defines, so the picker follows
      the glass lane's tuning instead of forking a second copy of it.

   4. NO ENTRANCE. It appeared by display:none -> flex, which is the one thing
      this site does not do. Under FADE ABOLITION the answer is not to add a
      fade: it is physical motion, so the panel now drops out of the trigger it
      belongs to. An animation rather than a transition, because `display` is
      what is changing and a transition cannot run across that.
   ═════════════════════════════════════════════════════════════════════════ */

/* ---- 1. the two stray rows ------------------------------------------------
   The owner switch goes on every panel the picker owns: it is owner tooling,
   it has no visible label, and it sits under five wallpapers where it means
   nothing. HIDDEN, not removed — ky-cal2.js keeps its state in localStorage
   and re-appends the row on an interval, so deleting it from the DOM would
   only make it come back a second later. */
#ky-sw-panel.kyw-on > .ky-cal-devrow { display: none !important; }

/* The honeykit switch is a REAL control, so it is not hidden everywhere —
   only where it cannot do anything. It drives html.honeykit, the goo/roughen
   filter stack that belongs to Honey & Ink; on a wallpaper world there is no
   kit to toggle. index.html carries no data-ky-page, so the owner's own page
   keeps it. */
#ky-sw-panel.kyw-on > .ky-zine { display: none !important; }
html:not([data-ky-page]) #ky-sw-panel.kyw-on > .ky-zine,
html[data-ky-page="honey-ink"] #ky-sw-panel.kyw-on > .ky-zine {
  display: flex !important;
  border-top: 1px solid rgba(255, 255, 255, .10);
  margin-top: 5px;
  padding: 9px 10px 4px;
  color: #cfcfcf;
}

/* ---- 2. the trigger -------------------------------------------------------
   ky-picker.js stamps .kyw-btn and the poster once it knows the live world;
   until then the stripes are left alone, so a page where the picker never
   booted still has its original working button rather than an empty square. */
#ky-sw-btn.kyw-btn {
  width: 46px;
  height: 46px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, .30);
  background-size: cover;
  background-position: center;
  background-color: #14110A;
  position: relative;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .30),
    0 6px 20px rgba(0, 0, 0, .48);
  transition: transform .28s cubic-bezier(.22, 1, .36, 1),
              box-shadow .28s ease;
}

/* the palette stripes are the OLD trigger's content. index.html's apply()
   rewrites the button's innerHTML on every theme change, so they cannot be
   removed from JS and made to STAY removed — they are covered instead. */
#ky-sw-btn.kyw-btn > i { display: none !important; }

#ky-sw-btn.kyw-btn:hover  { transform: translateY(-2px) scale(1.04); }
#ky-sw-btn.kyw-btn:active { transform: translateY(0) scale(.97); }
#ky-sw-btn.kyw-btn:focus-visible {
  outline: 2px solid rgba(255, 255, 255, .8);
  outline-offset: 3px;
}

/* a hairline of light across the top of the chip, so the button reads as
   glass over a photograph rather than as a cropped photo */
#ky-sw-btn.kyw-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, .22) 0%,
    rgba(255, 255, 255, .04) 38%,
    rgba(0, 0, 0, .20) 100%);
}

/* open state: the trigger is the thing the panel came out of, so it stays lit
   while the panel is down */
#ky-sw.open #ky-sw-btn.kyw-btn,
#ky-sw-btn.kyw-btn[aria-expanded="true"] {
  border-color: rgba(227, 172, 51, .78);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .34),
    0 0 0 3px rgba(227, 172, 51, .16),
    0 6px 20px rgba(0, 0, 0, .48);
}

/* ---- 3. the panel, in the site's own glass --------------------------------
   The same four-part backdrop the glass lane tunes (blur / saturate /
   brightness / contrast) and the same sheen-over-tint fill. The picker is
   always dark chrome regardless of the world behind it, so it takes the
   dark-lum end of the recipe directly rather than waiting for ky-glassify to
   measure and stamp one. */
#ky-sw-panel.kyw-on {
  --kywp-blur: var(--lg-blur, 18px);
  --kywp-sat:  var(--lg-sat, 155%);
  padding: 9px !important;
  min-width: 254px;
  border-radius: 18px !important;
  border: 1px solid rgba(255, 255, 255, .17) !important;
  overflow: hidden;
  gap: 2px !important;

  background:
    linear-gradient(180deg,
      rgba(255, 255, 255, .12) 0%,
      rgba(255, 255, 255, .04) 42%,
      rgba(255, 255, 255, .07) 100%),
    rgba(14, 15, 17, .58) !important;

  backdrop-filter:
    blur(var(--kywp-blur)) saturate(var(--kywp-sat))
    brightness(.66) contrast(.86) !important;
  -webkit-backdrop-filter:
    blur(var(--kywp-blur)) saturate(var(--kywp-sat))
    brightness(.66) contrast(.86) !important;

  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .22),
    inset 0 0 0 1px rgba(0, 0, 0, .28),
    0 18px 48px -12px rgba(0, 0, 0, .62) !important;
}

/* ---- 4. the entrance ------------------------------------------------------
   Transform only, and no opacity anywhere: `display` is already doing the
   appear/disappear, so a fade on top of it would be exactly the crossfade
   this site does not use. The panel scales up out of its own top-right
   corner, which is where the trigger is. */
@keyframes kywPanelIn {
  from { transform: translateY(-8px) scale(.94); }
  to   { transform: translateY(0)    scale(1); }
}
#ky-sw.open #ky-sw-panel.kyw-on,
#ky-sw-panel.kyw-on:not([hidden]) {
  transform-origin: 100% 0;
  animation: kywPanelIn 300ms cubic-bezier(.22, 1, .36, 1) both;
}

/* ---- the rows, at the new scale ------------------------------------------
   38x24 -> 46x30. The thumbnail is the only thing in a row that identifies
   its world, and at 38px wide a photograph of a room and a photograph of a
   lake are the same grey rectangle. */
#ky-sw-panel.kyw-on .kyw-chip {
  width: 46px;
  height: 30px;
  border-radius: 7px;
}
#ky-sw-panel.kyw-on .kyw-row {
  padding: 7px 9px;
  border-radius: 11px;
  gap: 11px;
  color: #f0f0f0;
  transition: background .18s ease, transform .28s cubic-bezier(.22, 1, .36, 1);
}
/* the row moves toward the pointer rather than merely lighting up — physical
   motion is this site's hover vocabulary everywhere else */
#ky-sw-panel.kyw-on .kyw-row:hover { transform: translateX(3px); }
#ky-sw-panel.kyw-on .kyw-name { font-size: 12px; }

/* the section heading, now that the trigger carries a picture and the panel is
   glass: quieter, and separated by space rather than by a rule */
#ky-sw-panel.kyw-on .kyw-hd {
  border-bottom: 0;
  padding: 3px 9px 7px;
  margin-bottom: 2px;
  color: #a9a9a9;
  font-size: 8.5px;
  letter-spacing: .18em;
}

@media (prefers-reduced-motion: reduce) {
  #ky-sw.open #ky-sw-panel.kyw-on,
  #ky-sw-panel.kyw-on:not([hidden]) { animation: none; }
  #ky-sw-panel.kyw-on .kyw-row:hover { transform: none; }
  #ky-sw-btn.kyw-btn { transition: none; }
  #ky-sw-btn.kyw-btn:hover, #ky-sw-btn.kyw-btn:active { transform: none; }
}

/* ---- label colours, re-measured against the new glass ---------------------
   MEASURED on the Tuesday lake plate, sampling the panel's real composite
   (the wallpaper through blur 18 / sat 155% / bright .66 / contrast .86, then
   the tint and sheen over it) rather than trusting the flat token:

     row backdrop      ~rgb(52-65, 67-76, 72-93)
     .kyw-name #f0f0f0   7.79 - 9.02:1   PASS, unchanged
     .kyw-sub  #8f8f8f   2.75 - 3.00:1   FAIL
     .kyw-hd   #a9a9a9   3.82:1          FAIL

   #8f8f8f was chosen against the OLD panel — rgba(15,15,15,.94), an almost
   opaque slab, where it measured ~5.8:1. Making the panel genuinely
   transparent raised the backdrop under it by roughly 50 points of luma, and
   a grey that was quiet on near-black is illegible on that. The sub-label is
   8.5px uppercase, so it is small text and owes the full 4.5:1 — no
   large-text exemption.

   These are the greys that clear it with headroom on the brightest wallpaper
   in the set, re-measured the same way after the change. */
#ky-sw-panel.kyw-on .kyw-sub { color: #c2c2c2; }
#ky-sw-panel.kyw-on .kyw-row.on .kyw-sub { color: #e6e6e6; }
#ky-sw-panel.kyw-on .kyw-hd { color: #c8c8c8; }
