/* Emoji picker styles, loaded by assets/js/kc-emoji-picker.js.

   THIS FILE IS SELF-LOADING. The picker injects a <link> to it once, so adding
   the picker to a page means adding ONE script tag and nothing else. That is
   deliberate: it runs on five surfaces and they do NOT share a stylesheet
   (create.css for the /create/ flows, refined-create.css for /music/create/).

   IT ALSO OWNS ITS OWN COLOR SCALE. It used to read --panel / --ink / --line
   from the host, which was wrong twice over: /music/create/ defines none of
   them, so an unfallback'd var() was an invalid declaration and the panel
   rendered transparent; and once fallbacks were added they were DARK values, so
   a LIGHT page got a dark overlay. The scale below is light by default and
   flips only when the page itself is dark, so the picker always matches the
   page it is standing on.

   ==========================================================================
   THE MODEL IS THE LANGUAGE DROPDOWN (.kc-lang__menu in cdo-watchtower.css).
   Kaʻo, 2026-07-30: "Have the interaction of the emojis overlay more like the
   languages drop down." That menu is the site's settled pattern for "a panel
   hanging off a control", so every value below that has a counterpart there is
   COPIED from it rather than invented: panel fill #fffdf9, 1px #e4e4df hairline,
   12px radius, the 0 14px 34px shadow, the #eef3ec row hover, and the search
   field's 1.5px #cdd5cd border with a soft focus ring instead of an outline.
   If the language menu is restyled, restyle this with it.
   ========================================================================== */

.kce {
  --kce-panel: #fffdf9;
  --kce-ink: #1a1a1a;
  --kce-muted: #8a938c;
  --kce-line: #e4e4df;
  --kce-field-line: #cdd5cd;
  --kce-hover: #eef3ec;
  /* BUTTON hover is a different color from ROW hover, and that is on purpose.
     Kaʻo, 2026-07-30: "match the color of the hover state, looks like a light
     tan for languages and other buttons in nav." The nav buttons all share one
     rule (cdo-watchtower.css:6500) and it fills with --wt-chip-bg, the tan,
     while the language dropdown's LIST ROWS fill with the green tint above.
     Two different jobs, so the picker carries both: --kce-chip for its two
     round buttons, --kce-hover for the emoji rows. */
  --kce-chip: #ede7da;
  --kce-accent: #2c5f4e;
  /* .30, not the language menu's .16: this halo is the ONLY focus indicator
     left once the outline is suppressed, so it has to carry that job alone. */
  --kce-ring: rgba(44, 95, 78, .30);
  --kce-btn-line: #e4ddcf;   /* the theme toggle's hairline, for the close button */
  --kce-shadow: rgba(40, 58, 49, .18);
  /* The word popup's edge. It sits on the panel in the panel's own fill, so
     unlike every other line here it is the ONLY thing separating two surfaces
     of the same color, and it is measured against 3:1 rather than inherited. */
  --kce-pop-line: #767d73;                  /* 4.17:1 on the panel */
  /* THE WORD LABEL IS AN INVERTED CHIP, and that is a contrast decision rather
     than a style one. It floats over the HOST PAGE, not over this component's
     own panel, and the five surfaces do not share a background: #ffffff and
     #faf7f2 in the create flows, #f7f4ee on the refined ones. A panel-colored
     chip with a hairline would have to be re-measured against each of them.
     A solid accent fill is 6.77:1 against the lightest of those backgrounds by
     luminance alone, so the chip is legible on every one of them without a
     border and without a per-surface palette. */
  --kce-tip-bg: #2c5f4e;                    /* = --kce-accent */
  --kce-tip-ink: #ffffff;                   /* 7.32:1 on the chip */
}
/* html[data-mode="batman"] is how every other stylesheet here switches to dark,
   so the picker follows the same switch rather than inventing its own. Values
   match .kc-lang__menu's dark block exactly. */
html[data-mode="batman"] .kce {
  --kce-panel: #0c1422;
  --kce-ink: #e7eefc;
  --kce-muted: #93a3bb;
  --kce-line: rgba(169, 200, 232, .30);
  --kce-field-line: rgba(169, 200, 232, .30);
  --kce-hover: rgba(143, 208, 180, .16);
  --kce-chip: rgba(143, 208, 180, 0.10);   /* = --wt-chip-bg dark */
  --kce-accent: #8fd0b4;
  --kce-ring: rgba(143, 208, 180, .38);
  --kce-btn-line: rgba(169, 200, 232, .40);
  --kce-shadow: rgba(0, 0, 0, .45);
  --kce-pop-line: rgba(169, 200, 232, .55);  /* 4.00:1 on the dark panel */
  /* Inverted the other way in dark: a light chip on a dark page, which is what
     every tooltip on every platform does and what keeps it from disappearing
     into the field it is pointing at. */
  --kce-tip-bg: #8fd0b4;                     /* = --kce-accent dark */
  --kce-tip-ink: #0c1422;                    /* 10.39:1 on the chip */
}

/* The picker owns its box model: host pages are inconsistent about the
   `* { box-sizing: border-box }` reset, and without it max-height applies to
   the content box and the panel overflows by its padding plus border. */
.kce, .kce *, .kce *::before, .kce *::after { box-sizing: border-box; }

/* The wrapper takes the slot the input used to occupy, and the FIELD FILLS IT.
   Kaʻo, 2026-07-30: a short field sitting beside a full-width primary button
   reads as broken, so the field runs to the end of its column and its right
   edge lines up with the button below it. */
.kce { position: relative; display: block; width: 100%; }
/* 46px of trailing padding = the 34px button plus its 6px inset each side, so
   typed text can never run underneath it. */
.kce > input { width: 100%; padding-right: 46px; }

/* TRIGGER: inside the field's trailing edge, vertically centered, adding NO
   height. Its exact left/top come from the JS, measured against the INPUT's
   box, because a grid host blockifies and stretches the wrapper and CSS alone
   would park the button out in the column.
   34px round, matching the header's light/dark toggle (.wt-batmode), which is
   the size Kaʻo pointed at for the close button; using it here too keeps the
   two circular controls in this component identical. */
.kce__trigger {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  /* 21px, not 17: Kaʻo, 2026-07-30, "make the emoji icon in the button 25%
     bigger so it is much larger in the circle." The BUTTON stays 34px, which
     is the 34px light/dark toggle it is matched to and also the tap target;
     only the glyph inside it grows. */
  width: 34px; height: 34px; padding: 0; font-size: 21px; line-height: 1;
  background: transparent; color: var(--kce-muted); cursor: pointer;
  border: 1px solid transparent; border-radius: 999px;
  transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}
/* Hover/focus/open mirror .kc-lang__btn: a hairline that takes the accent and a
   soft chip fill. No heavy outline, which is what made this feel clunky. */
.kce__trigger:hover { border-color: var(--kce-accent); background: var(--kce-chip); color: var(--kce-accent); }
.kce__trigger:focus-visible { outline: 2px solid var(--kce-accent); outline-offset: 2px; }
.kce__trigger[aria-expanded="true"] {
  border-color: var(--kce-accent); background: var(--kce-chip); color: var(--kce-accent);
}
@media (prefers-reduced-motion: reduce) { .kce__trigger { transition: none; } }

/* PANEL.
   Left edge on the field's left edge, right edge on the field's right edge:
   `width: 100%` of the wrapper is exactly the field's width, which is what
   removes the dead gap that used to sit between the panel and the field's
   trailing edge (the old rule capped it at 420px).

   The [hidden] rule below is load-bearing, not defensive. `display: flex` here
   carries more weight than the user agent's `[hidden] { display: none }`, so
   setting panel.hidden in JS did nothing and the overlay stood open on page
   load before anyone clicked anything. */
.kce__panel {
  position: absolute; z-index: 1400; top: calc(100% + 8px); left: 0;
  width: 100%;
  display: flex; flex-direction: column; min-height: 0;
  padding: 8px; border-radius: 12px;
  background: var(--kce-panel); color: var(--kce-ink);
  border: 1px solid var(--kce-line);
  box-shadow: 0 14px 34px var(--kce-shadow);
}
.kce__panel[hidden] { display: none; }
/* The panel carries tabindex="-1" so a pointer open can land focus on the
   dialog instead of the search box. It is a container, not a control, and it
   is already outlined by its own border, so it must not draw a focus ring of
   its own. :focus-visible is deliberately NOT suppressed: it never matches on
   a programmatic focus of a non-interactive element, so a keyboard user is
   unaffected either way. */
.kce__panel:focus { outline: none; }

.kce__head { display: flex; gap: 6px; align-items: center; flex: 0 0 auto; }

/* SEARCH FIELD, and why every rule here is scoped `.kce__panel .kce__search`.
   The picker sits INSIDE the host's phrase field wrapper, so a host rule
   written for that one field also matches this one. On /posters/create/ and
   /music/create/, refined-create.css has:
       .rc-entry input            (0,1,1)  height 46px, 17px, UPPERCASE, 8px radius
       .rc-entry input:focus-visible (0,2,1)  outline: 3px solid
   A bare `.kce__search` is (0,1,0) and `.kce__search:focus-visible` is (0,2,0),
   so BOTH lost. That is the whole reason the box rendered at phrase-field size
   with its placeholder shouting "SEARCH", and kept the 3px outline Kaʻo asked
   to remove. Prefixing with .kce__panel makes them (0,2,0) and (0,3,0), which
   wins on the class column without resorting to !important.
   The explicit height/text-transform/font-size resets are here for the same
   reason: they undo what the host field imposed, they are not defaults. */
.kce__panel .kce__search {
  flex: 1 1 auto; min-width: 0; height: auto;
  border: 1.5px solid var(--kce-field-line); border-radius: 9px;
  padding: 9px 11px;
  font-family: inherit; font-size: 13px; font-weight: 600; text-transform: none;
  letter-spacing: normal; color: var(--kce-ink); background: var(--kce-panel);
}
.kce__panel .kce__search::placeholder { color: var(--kce-muted); font-weight: 500; text-transform: none; }
/* NO outline on focus: Kaʻo, 2026-07-30, "Search should not be outlined. It
   feels clunky."

   `!important` is not laziness here, it is the only tool that works. The host
   rule is refined-create.css:385,
       #refined-create-root input:focus-visible { outline: 3px solid ...; }
   which is (1,1,1). An ID beats ANY number of classes, a point that file's own
   comment makes at line 47, so no selector I can write from inside the
   component outranks it. Scoping harder was tried first and does not work.

   THE FOCUS INDICATOR IS REPLACED, NOT REMOVED. Accessibility is a hard
   requirement on this site, and WCAG 2.4.7 needs a visible focus state.

   ONE LINE, ON the field, never a second ring outside it. Kaʻo, 2026-07-30:
   "it should not be double lines with an outline outside of the field", then
   "have the outline be like the nav search field". So this is copied from
   .kc-hsearch__field:focus-within in cdo-watchtower.css:6031, which is the
   header search Kaʻo pointed at:

       border-color: accent;  box-shadow: 0 0 0 2px accent;

   The trick is that the ring is the SAME COLOR as the border, so the two do
   not read as two lines: they merge into one ~3px accent edge hugging the
   field. A faint alpha ring, which is what was here before, reads as a halo
   sitting outside a separate border, which is the doubling being objected to.
   Nothing moves, because border-width never changes.

   Still WCAG 2.4.7, and by a wider margin than before: the edge both changes
   color (about 7:1 on the panel) and triples in thickness. */
.kce__panel .kce__search:focus,
.kce__panel .kce__search:focus-visible {
  outline: none !important;
  border-color: var(--kce-accent);
  box-shadow: 0 0 0 2px var(--kce-accent);
}

/* 34px round, the size of the header light/dark toggle, subtle hairline.
   Scoped like the search field above, for the same specificity reason: host
   flows style their buttons by element and would otherwise resize this. */
.kce__panel .kce__close {
  flex: 0 0 auto; width: 34px; height: 34px; min-width: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: inherit; font-size: 17px; line-height: 1; text-transform: none;
  background: transparent; color: var(--kce-muted);
  border: 1px solid var(--kce-btn-line); border-radius: 999px; cursor: pointer;
  transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}
.kce__panel .kce__close:hover { border-color: var(--kce-accent); background: var(--kce-chip); color: var(--kce-accent); }
.kce__panel .kce__close:focus-visible { outline: 2px solid var(--kce-accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .kce__close { transition: none; } }

.kce__hint { flex: 0 0 auto; margin: 8px 2px 2px; font-size: 12.5px; font-weight: 500; color: var(--kce-muted); }
/* Separate longhands, not a `font:` shorthand. `font: 500 11px inherit` is not
   valid CSS (the shorthand has no `inherit` family form), so the browser drops
   the whole declaration and the size and weight fall through to whatever the
   host page sets. Same trap applies to .kce__word below. */
.kce__group {
  margin: 8px 2px 2px;
  font-family: inherit; font-size: 11px; font-weight: 500;
  letter-spacing: .04em; text-transform: uppercase; color: var(--kce-muted);
  grid-column: 1 / -1;
}
/* 160px, up from 152: a column now carries a 26px word arrow as well as the
   glyph and the word, and 152 minus that put the nine-character words
   (GRATITUDE, PINEAPPLE, SAXOPHONE) back into "GRATIT...", which is what the
   152 was chosen to prevent in the first place. The 8px the columns lost is
   bought back on phones by the tighter sheet at the bottom of this file, so the
   two-column layout survives down to a 360px screen exactly as it did before.
   flex + min-height: 0 lets the grid shrink inside the JS-capped panel.
   overscroll-behavior stops the page scrolling once the grid hits its end. */
.kce__grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 1px 6px; flex: 1 1 auto; min-height: 0; overflow-y: auto;
  overscroll-behavior: contain; margin-top: 4px; padding: 0 2px 2px;
}
/* THE CELL IS THE GRID ITEM, and it holds a tile plus, where the emoji has more
   than one word, an arrow. The two are SIBLINGS: a button inside a button is
   invalid markup, and on a phone it would be a second tap target sitting inside
   the first, which is the least forgiving thing you can build for a thumb. */
.kce__cell { position: relative; display: flex; align-items: center; min-width: 0; }

/* Row treatment copied from .kc-lang__opt: no border, 8px radius, flat hover.
   Scoped for specificity, same reason as the search field and close button. */
.kce__panel .kce__item {
  display: flex; align-items: center; gap: 7px;
  flex: 1 1 auto; min-width: 0; min-height: 44px;
  padding: 9px 4px 9px 10px; text-align: left; cursor: pointer;
  font-family: inherit; text-transform: none; letter-spacing: normal;
  background: transparent; color: var(--kce-ink);
  border: none; border-radius: 8px;
}
/* Every cell now carries either an arrow or a same-width spacer, so the tile is
   never an only child and this rule is inert. Kept because a future cell built
   without either would otherwise lose its right padding silently. */
.kce__cell > .kce__item:only-child { padding-right: 10px; }
/* The arrow supplies the left gutter now, so the tile does not also indent. */
.kce__panel .kce__item { padding-left: 0; }
.kce__panel .kce__item:hover { background: var(--kce-hover); }
.kce__panel .kce__item:focus-visible { outline: 2px solid var(--kce-accent); outline-offset: -2px; }
.kce__glyph { font-size: 20px; line-height: 1; flex: 0 0 auto; }
.kce__eq { color: var(--kce-muted); font-weight: 600; flex: 0 0 auto; }
.kce__word {
  font-family: inherit; font-size: 13px; font-weight: 600; letter-spacing: .02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* THE WORD ARROW. Kaʻo, 2026-08-05: "Each tile has a small arrow opening the
   WORD choices for that glyph."

   26px wide is as narrow as the picture can be without looking like a stray
   character, and it is deliberately NOT the tap target: the ::after below
   stretches the hit area to 38px across the full 44px height, reaching into the
   6px gutter beside it rather than into the tile. So the tile keeps its 44px
   minimum and the arrow gets its own, and the two do not fight. */
.kce__panel .kce__more {
  position: relative; flex: 0 0 26px; align-self: stretch;
  min-width: 0; min-height: 44px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: inherit; line-height: 1; text-transform: none;
  background: transparent; color: var(--kce-muted); cursor: pointer;
  border: none; border-radius: 8px;
  /* NO BOX AT REST. Kaʻo, 2026-08-05: "the arrows also don't need to be in
     containers." A resting chevron is a hint, not a control to be framed; the
     hover and open states below are what make it look pressable. Explicit
     rather than inherited, because an unstyled <button> draws its own border
     and background, which is exactly the boxed look that was reported. */
  box-shadow: none; appearance: none; -webkit-appearance: none;
}
/* THE CARET, DRAWN WITH BORDERS so the shape is identical on every platform.
   A font glyph is not: U+25BE is tall and skinny, U+25BC varies by family, and
   Kaʻo asked for one specific squat triangle. Width 13, height 7, so it is
   noticeably wider than tall, and about 10% larger than the 11px glyph it
   replaces, which is the size increase he asked for. currentColor so it
   inherits the hover and open colors below without a second rule. */
.kce__panel .kce__caret {
  display: block; width: 0; height: 0;
  /* 70% of the 13x7 first pass, per Kaʻo 2026-08-05. 9.1 wide by 4.9 tall,
     rounded to whole and half pixels so the two edges stay symmetrical and the
     triangle does not render one row lopsided on a 1x screen. Still squat:
     wider than it is tall, which was the shape he asked for. */
  border-left: 4.5px solid transparent;
  border-right: 4.5px solid transparent;
  border-top: 5px solid currentColor;
  border-bottom: 0;
}
/* THE ARROW SITS LEFT OF THE EMOJI, and every tile reserves its width whether
   it has one or not, so the glyphs line up in a column.

   `order` rather than DOM position on purpose. The arrow stays AFTER the tile
   in the markup so Tab still lands on the tile first and the roving-tabindex
   pairing in rove() is untouched; only the painting moves. Reordering the DOM
   would have put a secondary disclosure control ahead of the primary action
   for every keyboard and screen reader user. */
.kce__panel .kce__more { order: -1; }
.kce__nomore { order: -1; flex: 0 0 26px; align-self: stretch; }
.kce__panel .kce__more::after { content: ""; position: absolute; inset: 0 -6px; }
.kce__panel .kce__more:hover,
.kce__panel .kce__more[aria-expanded="true"] { background: var(--kce-chip); color: var(--kce-accent); }
.kce__panel .kce__more:focus-visible { outline: 2px solid var(--kce-accent); outline-offset: -2px; }

/* THE POPUP LISTS WORDS ONLY. No glyph, no gender label, no legend: the tile it
   is hanging off has already said which picture this is, and the only decision
   left is which word gets sung. It is a child of the PANEL rather than of the
   cell, because the grid scrolls and would clip it. */
/* THE BORDER IS STRONGER THAN THE PANEL'S OWN, on purpose and by measurement.
   The popup floats over the panel and takes the SAME fill, so that 1px line is
   the entire visual boundary of the component: the panel's own --kce-line
   hairline measured 1.24:1 against it in light and 2.04:1 in dark, both under
   the 3:1 WCAG 1.4.11 asks of a boundary you need in order to see the control.
   --kce-pop-line is 4.17:1 light and 4.00:1 dark. The shadow cannot carry this
   job in dark mode, where a black shadow on a near-black panel does nothing. */
.kce__pop {
  position: absolute; z-index: 1500; min-width: 132px; max-width: 96%;
  display: flex; flex-direction: column; gap: 1px;
  padding: 5px; border-radius: 10px;
  background: var(--kce-panel); color: var(--kce-ink);
  border: 1px solid var(--kce-pop-line);
  box-shadow: 0 10px 26px var(--kce-shadow);
}
.kce__pop[hidden] { display: none; }
.kce__panel .kce__popitem {
  display: block; width: 100%; min-height: 40px; padding: 8px 12px;
  text-align: left; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 600; letter-spacing: .02em;
  text-transform: none; white-space: nowrap;
  background: transparent; color: var(--kce-ink);
  border: none; border-radius: 7px;
}
.kce__panel .kce__popitem:hover { background: var(--kce-hover); }
.kce__panel .kce__popitem:focus-visible { outline: 2px solid var(--kce-accent); outline-offset: -2px; }
/* :empty collapses it. It used to reserve 1.2em unconditionally, which is part
   of the dead band Kaʻo saw under the last row of emoji. */
.kce__status { flex: 0 0 auto; margin: 6px 2px 0; font-size: 12.5px; font-weight: 500; color: var(--kce-muted); }
.kce__status:empty { display: none; margin: 0; }

/* ==========================================================================
   THE WORD LABEL: what this emoji will be SUNG as, floating over the glyph.

   Kaʻo, 2026-08-05: "have a tool tip above the emoji pointing down to it,
   moving with the emoji moving, with the associated word in it. That way, as
   they type out the rest of the sentence, they know exactly what word will be
   in the song and can compose the phrase correctly."

   Scoped `.kce .kce__tip` (0,2,0) for the same reason the search field and the
   close button are: the picker sits inside the host's phrase-field wrapper, so
   a host rule written for that row also matches anything in here. `.rc-entry
   input` is (0,1,1) and it uppercases; a bare `.kce__tip` at (0,1,0) would lose
   to rules of that shape.
   ========================================================================== */
.kce .kce__tip {
  position: absolute; z-index: 1300;
  /* NEVER IN THE WAY OF THE FIELD. It sits over the row, so without this it
     would eat a tap aimed at the field or a click aimed at the caret, and the
     member could not put the cursor back where the label is pointing. */
  pointer-events: none;
  display: block; padding: 3px 8px; border-radius: 7px;
  font-family: inherit; font-size: 11.5px; font-weight: 700;
  letter-spacing: .04em; line-height: 1.35;
  /* The words are Latin and already uppercase in the lexicon. `ltr` keeps them
     laid out left to right inside an Arabic, Farsi or Urdu page, which
     kc-i18n.js marks dir="rtl"; `none` stops a host uppercase rule from
     double-transforming them. */
  direction: ltr; text-align: center; text-transform: none; white-space: nowrap;
  background: var(--kce-tip-bg); color: var(--kce-tip-ink);
  box-shadow: 0 2px 8px var(--kce-shadow);
  /* OPACITY IS THE ONLY THING THAT ANIMATES, and `left` deliberately does not.
     A transition on the horizontal position would make the label LAG behind
     its glyph on every keystroke, which is the one failure worse than having
     no label at all: for those 80ms it points at the wrong character. It
     tracks the text exactly, frame for frame, the way Kaʻo asked ("moving with
     the emoji moving"). The fade is only for appearing and disappearing. */
  opacity: 0; transition: opacity .12s ease;
}
.kce .kce__tip--on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .kce .kce__tip { transition: none; } }
/* THE POINTER, drawn with borders rather than typed, exactly like the word
   arrow above: a font triangle is a different shape on every platform, and this
   one has to line up with a specific glyph. Its horizontal position is set
   independently of the label's own box (--kce-tip-x, written by the JS), which
   is what lets two labels slide apart to avoid overlapping while each keeps
   pointing at its own emoji. */
.kce .kce__tip::after {
  content: ""; position: absolute; top: 100%;
  left: var(--kce-tip-x, 50%); transform: translateX(-50%);
  width: 0; height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 5px solid var(--kce-tip-bg);
}

/* THE MIRROR. An <input> exposes no per-character geometry: there is no range
   and no client rect to ask where a glyph sits. So the same string is laid out
   a second time in a div that carries the field's font, weight, spacing,
   text-transform, padding, border and width, with every emoji in a span that
   CAN be measured. Every property that affects width is copied from the live
   computed style by the JS, inline, because a host rule would otherwise
   out-specify anything written here and one wrong letter-spacing puts every
   label off by a few pixels per character.

   `visibility: hidden` and not `display: none`: a hidden box is still laid out,
   which is the entire point. It is aria-hidden and pointer-events: none, so it
   is invisible to a screen reader and to a thumb as well as to the eye. */
.kce .kce__mirror {
  position: absolute; top: 0; left: 0; z-index: -1;
  visibility: hidden; pointer-events: none;
  white-space: pre; overflow: hidden; margin: 0;
}

/* Bottom sheet on phones: always fully visible by construction, which is why
   the JS placement bails out when it sees position:fixed.

   THE TIGHTER INSETS ARE LOAD-BEARING, not tidying. The grid columns grew from
   152px to 160px to make room for the word arrow, and at the old 8px insets and
   8px panel padding that was enough to drop a 360px Android screen from two
   columns to one, halving how many emoji are visible in a sheet. Reclaiming
   14px of chrome puts it back: 360px keeps two columns, 320px stays at one as
   it always was. */
@media (max-width: 520px) {
  .kce__panel { position: fixed; left: 4px; right: 4px; top: auto; bottom: 8px; width: auto; max-height: 72vh; padding: 6px; }
  .kce__grid { gap: 1px 4px; padding: 0 1px 2px; }
}
@media (prefers-reduced-motion: no-preference) {
  .kce__panel { animation: kce-in .12s ease-out; }
  @keyframes kce-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
}

/* ACCESSIBILITY 2026-07-31, findings H-07 and M-04.
   --kce-muted carries the hint line, the group labels and the result status.
   At #8a938c on the #fffdf9 panel that is 3.12:1, below the 4.5:1 body-text
   minimum; the dark value already passed at 7.20:1 and is untouched. The
   search field's edge was #cdd5cd, 1.4:1 on the panel, so the one control in
   this picker had no perceivable boundary (WCAG 1.4.11 wants 3:1). */
.kce { --kce-muted: #677065; --kce-field-line: #767d73; }   /* 5.06:1 / 4.17:1 */
