/*
 * Homepage hero -- ported from the designer's reference prototype
 * (https://swizzel-profile-prototype.vercel.app/#/home, its styles.css).
 *
 * Class names are kept BYTE-IDENTICAL to the prototype's on purpose: the
 * prototype is the source of truth for BEHAVIOUR and transitions, so keeping the
 * names aligned makes the next design sync a 1:1 diff instead of a translation
 * exercise. Do not "Railsify" these names. Where the Figma frames (Web App >
 * "Homepage / Search" and "Home / Create") disagree with the prototype on a
 * VALUE, Figma wins -- the Search tab's rules (home_search.css, search_results.css)
 * say where they depart from the prototype.
 *
 * Why plain CSS and not Tailwind utilities:
 *   1. Tailwind v4 emits everything inside cascade layers, and UNLAYERED css
 *      beats every layer regardless of specificity. So these rules reliably win
 *      over utilities -- which also means you cannot tweak them with a utility
 *      class on the element. Change them here.
 *   2. The mesh orb is not expressible in utilities at all (six stacked
 *      conic-gradients driven by a registered custom property).
 *   3. Nearly every value is off-scale (10px gaps, 99px radii, -0.14px
 *      tracking), so the utility version would be arbitrary-value soup.
 *
 * Loaded automatically: `stylesheet_link_tag :app` in the layout expands to
 * every stylesheet in this directory (plus builds/tailwind.css, last).
 */

/* ---------------------------------------------------------------- tokens ---
 * Scoped rather than on :root -- the app has no global token layer and these
 * names (--text-primary etc.) are generic enough to collide with one later.
 */
.home-hero-root {
  --text-primary: #1c1917;
  --text-secondary: #57534d;
  --text-tertiary: #79716b;
  --text-quaternary: #a6a09b;
  --surface-subtle: #f3f3f2;
  --border: #f3f3f2;
  --border-secondary: #e7e5e4;
  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
  --tabs-dur: 250ms;

}

/* Inter is already <link>ed by the layout on every page but never applied --
 * --font-sans is still the system stack. Scoped deliberately (see the "Inter
 * font: homepage only" decision) rather than flipped app-wide.
 *
 * Scoped to the HERO and the detail modal specifically, not the whole homepage:
 * the discovery feed below renders the very same cards as /discover, and giving
 * them a different typeface here would just move the inconsistency rather than
 * contain it. The hero's -0.4px tracking assumes Inter. */
.home-hero,
.prompt-detail-modal {
  font-family: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  font-synthesis: none;
}

/* ------------------------------------------------------------- mesh orb ---
 * The gradient sphere on every chip and in the detail modal. NOT an image --
 * six conic-gradients rotated by an animated angle, blurred into a mesh. The
 * per-orb palette and hotspot positions arrive as inline --orb-* custom
 * properties (see MeshOrb in Ruby / mesh_orb.js), seeded from the item's name
 * so a given mind always looks the same.
 *
 * NOT scoped to .home-hero-root: orbs also render inside the #modal turbo
 * frame, which is a direct child of <body>.
 *
 * @property is MANDATORY. Without it --taxonomy-orb-angle is not an
 * interpolatable type and the orb sits frozen at 0deg.
 */
@property --taxonomy-orb-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.chip-mesh-orb {
  --orb-base: #0d9488;
  --orb-a: #5eead4;
  --orb-b: #0f766e;
  --orb-c: #99f6e4;
  --orb-phase: 0deg;
  --orb-blur: 0.65px;
  --orb-contrast: 1.15;
  --orb-shadow: 0.5px;
  --orb-spin-duration: 18s;
  position: relative;
  display: grid;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  grid-template-areas: "stack";
  overflow: hidden;
  isolation: isolate;
  border-radius: 50%;
  -webkit-clip-path: circle(50% at 50% 50%);
  clip-path: circle(50% at 50% 50%);
  /* With the clip-path alone the rim aliases badly in WebKit. */
  -webkit-mask-image: -webkit-radial-gradient(white, black);
}

.chip-mesh-orb::before {
  --orb-turn: calc(var(--orb-phase, 0deg) + var(--taxonomy-orb-angle));
  content: "";
  display: block;
  width: 100%;
  height: 100%;
  grid-area: stack;
  border-radius: 50%;
  /* inset bleeds 1px past the circle so the blur has something to eat into. */
  inset: -1px;
  transform: translateZ(0) rotate(var(--orb-rotation, 0deg));
  background:
    conic-gradient(from calc(var(--orb-turn) *  2) at var(--orb-spot-1-x, 25%) var(--orb-spot-1-y, 70%), var(--orb-c), transparent 20% 80%, var(--orb-c)),
    conic-gradient(from calc(var(--orb-turn) *  2) at var(--orb-spot-2-x, 45%) var(--orb-spot-2-y, 75%), var(--orb-b), transparent 30% 60%, var(--orb-b)),
    conic-gradient(from calc(var(--orb-turn) * -3) at var(--orb-spot-3-x, 80%) var(--orb-spot-3-y, 20%), var(--orb-a), transparent 40% 60%, var(--orb-a)),
    conic-gradient(from calc(var(--orb-turn) *  2) at var(--orb-spot-4-x, 15%) var(--orb-spot-4-y,  5%), var(--orb-b), transparent 10% 90%, var(--orb-b)),
    conic-gradient(from      var(--orb-turn)       at var(--orb-spot-5-x, 20%) var(--orb-spot-5-y, 80%), var(--orb-a), transparent 10% 90%, var(--orb-a)),
    conic-gradient(from calc(var(--orb-turn) * -2) at var(--orb-spot-6-x, 85%) var(--orb-spot-6-y, 10%), var(--orb-c), transparent 20% 80%, var(--orb-c)),
    var(--orb-base);
  box-shadow: inset var(--orb-base) 0 0 var(--orb-shadow) calc(var(--orb-shadow) * 0.2);
  filter: blur(var(--orb-blur)) contrast(var(--orb-contrast));
  /* Negative delay desynchronises orbs; without it they all spin in lockstep,
   * which reads as a rendering bug rather than a design. */
  animation: taxonomy-orb-spin var(--orb-spin-duration) linear
    calc(var(--orb-spin-duration) * var(--orb-spin-delay-factor, 0) * -1)
    infinite var(--orb-spin-direction, normal);
}

@keyframes taxonomy-orb-spin {
  to { --taxonomy-orb-angle: 360deg; }
}

/* Animating the angle rebuilds six conic-gradients plus a blur every frame.
 * Stop paying for that on orbs the user cannot see behind an open modal. */
body.modal-open .chip-mesh-orb::before {
  animation-play-state: paused;
}
body.modal-open .prompt-detail-modal .chip-mesh-orb::before {
  animation-play-state: running;
}

/* -------------------------------------------------------- hero + layout --- */
.home-hero {
  display: flex;
  width: 100%;
  max-width: 640px;
  flex-direction: column;
  gap: 64px;
  align-items: center;
  margin: 0 auto;
}

.home-hero-main {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: 56px;
  align-items: center;
}

.home-hero-copy {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: 16px;
  text-align: center;
}

.home-hero-copy h1 {
  margin: 0;
  font-size: 40px;
  font-weight: 600;
  line-height: 48px;
  /* Absolute px, not em: at 40px this is -0.01em. Tailwind's tracking-tight
   * (-0.025em) is visibly too tight here. */
  letter-spacing: -0.4px;
  color: var(--text-primary);
}

.home-hero-greeting,
.home-hero-question {
  display: block;
}

.home-hero-greeting[hidden] {
  display: none;
}

.home-hero-copy p {
  margin: 0;
  color: var(--text-tertiary);
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  letter-spacing: -0.16px;
  /* The subtitle fades out (160ms), the controller swaps the text, and it fades
   * back in -- a quick dip rather than a morph, which suits a whole sentence. */
  transition: opacity 160ms var(--resize-ease);
}

.home-hero-copy p.is-replacing { opacity: 0; }

/* The headline is morphed letter by letter by torph, which marks its root with
 * [torph-root]. It forces white-space: nowrap, so the root is centred as a block
 * (text_morph.js does not run it where the headline would not fit on one line). */
.home-hero-question[torph-root] {
  display: block;
  width: 100%;
  white-space: nowrap;
  text-align: center;
}

@media (max-width: 760px) {
  .home-hero { gap: 40px; }
  .home-hero-main { gap: 36px; }
  .home-hero-copy h1 { font-size: 30px; line-height: 38px; }
}

/* ------------------------------------------------------------ mode tabs ---
 * The pill is positioned by JS (home_tabs_controller) from the active tab's
 * offsetLeft/offsetWidth. The base rule leaves it width:0, so before JS runs
 * there is no white capsule -- home_tab_toggle_component renders an inline
 * width/transform as the no-JS fallback.
 */
.t-tabs {
  position: relative;
  display: inline-flex;
  align-items: center;
  border-radius: 48px;
  background: #fafaf9;
}

.t-tab {
  position: relative;
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 48px;
  z-index: 1;
  transition: color var(--tabs-dur) var(--ease-out-quint);
}

/* Hovering an unselected tab darkens it to exactly the selected colour -- the
 * only difference is the pill behind it. Deliberately no hover background. */
.t-tab:not([aria-selected="true"]):hover,
.t-tab[aria-selected="true"] {
  color: var(--text-primary);
}

.t-tabs-pill {
  position: absolute;
  top: 3px;
  left: 0;
  height: 30px;
  width: 0;
  background: #fff;
  border-radius: 48px;
  transform: translateX(0);
  transition:
    transform var(--tabs-dur) var(--ease-out-quint),
    width var(--tabs-dur) var(--ease-out-quint);
  will-change: transform, width;
  z-index: 0;
  pointer-events: none;
}

.home-mode-tabs.t-tabs {
  width: 264px;
  flex: 0 0 auto;
  gap: 0;
  padding: 2px;
}

.home-mode-tabs .t-tab {
  flex: 1 1 0;
  height: auto;
  min-height: 40px;
  padding: 8px;
  /* `font: inherit` FIRST to beat the UA button font, then the specifics --
   * reorder these and the shorthand wipes the rest. */
  font: inherit;
  font-size: 16px;
  font-weight: 500;
  line-height: 24px;
  letter-spacing: -0.16px;
}

.home-mode-tabs .t-tabs-pill {
  top: 2px;
  height: calc(100% - 4px);
  border: 0;
  border-radius: 24px;
  /* The hairline is the first shadow layer, not a border -- a real 1px border
   * would change the 44px bar height. */
  box-shadow:
    0 0 0 1px rgb(0 0 0 / 4%),
    0 2px 4px -1px rgb(3 7 18 / 5%),
    0 4px 8px -1px rgb(3 7 18 / 5%);
}

/* Brand blue at 45% alpha, not solid --brand. Tailwind's ring won't match. */
.home-mode-tabs .t-tab:focus-visible,
.compose-chip-open:focus-visible,
.compose-chip-remove:focus-visible,
.compose-add:focus-visible,
.compose-attach:focus-visible,
.compose-kits:focus-visible {
  outline: 2px solid rgb(0 147 255 / 45%);
  outline-offset: 2px;
}

/* ----------------------------------------------------------- mode panels ---
 * Create and Search are a true CROSSFADE, not one fading out and then the other in:
 * both panels sit in the same grid cell (grid-area 1 / 1), and while the outgoing
 * one fades to 0 the incoming one fades up from 0, over the same 300ms. The feed
 * under the hero swaps the same way (.home-feed-stage). home_tabs_controller
 * tweens each stage's HEIGHT between the two so whatever is below glides rather
 * than jumps (.t-resize, in search_shared.css).
 *
 * INVARIANT: none of .home-hero, .home-hero-main, .home-mode-stage,
 * .home-mode-panel or .home-feed-stage may get overflow other than visible, nor
 * contain:paint|content|strict, nor a transform or filter -- not even to hide the
 * tween. The suggestions dropdown is absolutely positioned INSIDE the stage and
 * hangs far below it (the stage is only as tall as the search field); clipping any
 * ancestor would cut it off at the field's bottom edge. The outgoing panel
 * spilling past a shrinking stage for 300ms is accepted (the prototype does too).
 */
.home-mode-stage,
.home-feed-stage {
  display: grid;
  width: 100%;
  align-items: start;
}

.home-mode-panel,
.home-feed {
  grid-area: 1 / 1;
  /* min-width:0 so a horizontally scrolling carousel inside a grid item cannot
   * widen the track and push the page sideways. */
  width: 100%;
  min-width: 0;
  opacity: 1;
  transition: opacity var(--resize-dur) var(--resize-ease);
}

.home-mode-panel.is-hiding,
.home-feed.is-hiding {
  opacity: 0;
  pointer-events: none;
}

/* ----------------------------------------------------------------- chips --- */
.compose-stack {
  position: relative;
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: 16px;
  align-items: stretch;
}

.compose-pills {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-start;
  justify-content: flex-start;
  width: 100%;
}

/* Raised: white with a hairline and a soft drop. Contrast with .compose-add,
 * which is recessed. Both are 40px tall with a 99px radius. */
.compose-chip {
  display: flex;
  flex: 0 0 auto;
  height: 40px;
  align-items: center;
  gap: 4px;
  padding: 8px;
  overflow: hidden;
  background: #fff;
  border: 1px solid rgb(0 0 0 / 4%);
  border-radius: 99px;
  box-shadow: 0 1px 2px 0 rgb(3 7 18 / 5%);
  transition: background-color 150ms ease-out;
}

.compose-chip:hover { background: #fafaf9; }

/* The open target and the remove button are SIBLINGS inside a non-interactive
 * wrapper. Do not collapse the chip into one button with a nested x -- that is
 * invalid nested-interactive markup and would then need stopPropagation. */
.compose-chip-open {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 4px;
  padding: 0;
  color: var(--text-primary);
  font: inherit;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-decoration: none;
}

.compose-chip-orb {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
}

/* The hero sphere at the top of the detail modal. Same orb, larger: the blur
 * and shadow are proportional to the box, so it scales without retuning. */
.prompt-detail-orb {
  width: 112px;
  height: 112px;
  flex: 0 0 112px;
  --orb-blur: 3px;
  --orb-shadow: 2px;
}

.compose-chip-label {
  /* On top of the 4px flex gap, so the icon-to-text gap reads as 8px. */
  padding: 0 4px;
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: -0.14px;
  white-space: nowrap;
}

.compose-chip-remove {
  display: grid;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  place-items: center;
  padding: 0;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  opacity: 1;
  transition: opacity 150ms ease-out;
}

/* Whole-button fade. No background pill, no colour change, no scale. */
.compose-chip-remove:hover { opacity: 0.5; }

.compose-chip-remove svg { display: block; width: 20px; height: 20px; }

/* Recessed: dashed hairline on the subtle surface, no shadow. */
.compose-add {
  display: flex;
  flex: 0 0 auto;
  height: 40px;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 10px;
  overflow: hidden;
  color: var(--text-tertiary);
  background: #fafaf9;
  border: 1px dashed rgb(0 0 0 / 12%);
  border-radius: 99px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: -0.14px;
  white-space: nowrap;
  text-decoration: none;
  transition:
    background-color 150ms ease-out,
    color 150ms ease-out;
}

.compose-add:hover { background: #f3f3f2; }
.compose-add-label { padding: 0 4px; }
.compose-add svg { display: block; width: 20px; height: 20px; flex: 0 0 20px; }

/* MAX_SELECTIONS lockout. The controller also blocks the click in the capture
 * phase; this is only the affordance. */
.compose-add[aria-disabled="true"] {
  opacity: 0.45;
  cursor: default;
}
.compose-add[aria-disabled="true"]:hover { background: #fafaf9; }

/* ----------------------------------------------------------- kit menu --- */
/* The "Use a kit" chip is a third .compose-add on the pills row; this wrapper
 * exists only to anchor the popover to it. */
.compose-kit-menu {
  position: relative;
  flex: 0 0 auto;
}

.menu-field-popover {
  position: absolute;
  top: calc(100% + 4px);
  left: -4px;
  z-index: 6;
  display: flex;
  flex-direction: column;
  min-width: max(100%, 224px);
  max-width: 280px;
  max-height: min(356px, calc(100vh - 24px));
  /* Even padding, NOT the prototype's `4px 4px 0`. That base rule leans on
   * .menu-field-list's own bottom padding for the bottom gap, which only works
   * while the list is the last child. Ours always ends with "Manage kits", an
   * option outside the list, so a zero bottom left its hover fill running into
   * the popover's rounded edge. (The prototype's sidebar menu, which has the
   * same shape, overrides to `padding: 4px` for exactly this reason.) */
  padding: 4px;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--border-secondary);
  border-radius: 12px;
  box-shadow:
    0 8px 16px -3px rgb(0 0 0 / 8%),
    0 4px 6px -4px rgb(0 0 0 / 12%);
  /* Closed state. `inert` (set by the controller) is what actually removes the
   * contents from the tab order -- visibility here is presentation only. */
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition:
    opacity 120ms var(--ease-out-quint),
    transform 120ms var(--ease-out-quint),
    visibility 0s linear 120ms;
}

.menu-field-popover.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition-delay: 0s;
}

.menu-field-list {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
  margin: 0;
  /* No bottom padding: the popover now provides the gap, and the separator's
   * own 4px margin spaces the list from what follows. */
  padding: 0;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
}

.menu-field-option {
  display: flex;
  flex: 0 0 auto;
  gap: 4px;
  align-items: center;
  width: 100%;
  min-height: 36px;
  padding: 8px;
  overflow: hidden;
  color: var(--text-primary);
  background: transparent;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: -0.14px;
  text-align: left;
  text-decoration: none;
}

.menu-field-option:hover,
.menu-field-option:focus-visible {
  background: var(--surface-subtle);
}

/* The hover background alone is a 4% shift against white -- fine as a pointer
 * affordance, not enough to tell a keyboard user where they are. Solid brand
 * blue rather than the 45% alpha used elsewhere in this file, and inset via a
 * negative offset because the popover is overflow:hidden and would otherwise
 * clip an outward ring on the first and last rows. Matches the treatment the
 * prototype gives its own menu options. */
.menu-field-option:focus-visible {
  outline: 2px solid #0093ff;
  outline-offset: -2px;
}

/* A long kit name truncates rather than widening the popover past its max. */
.menu-field-option-label {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.menu-field-option svg {
  display: block;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  color: var(--text-secondary);
}

.menu-field-empty {
  margin: 0;
  padding: 8px 12px;
  color: var(--text-quaternary);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: -0.14px;
}

/* The prototype calls this .sidebar-user-menu-sep, reusing the class from a
 * different menu. Renamed to match the .menu-field-* family it actually sits in
 * -- the one place these class names deliberately diverge from the prototype. */
.menu-field-sep {
  width: 100%;
  height: 1px;
  margin: 4px 0;
  background: var(--border);
}

@media (prefers-reduced-motion: reduce) {
  .menu-field-popover { transition: none !important; }
}

/* --------------------------------------------------------- compose box --- */
.compose {
  position: relative;
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: 12px;
  align-items: stretch;
  padding: 12px;
  overflow: visible;
  background: #fff;
  border: 0;
  border-radius: 24px;
  box-shadow:
    0 0 0 1px rgb(0 0 0 / 4%),
    0 2px 4px -1px rgb(3 7 18 / 5%),
    0 4px 8px -1px rgb(3 7 18 / 5%);
  transition: box-shadow 220ms var(--ease-out-quint);
}

.compose:focus-within {
  box-shadow:
    0 0 0 1px rgb(0 0 0 / 8%),
    0 1px 2px -1px rgb(3 7 18 / 5%),
    0 4px 16px -4px rgb(3 7 18 / 8%);
}

.compose-field {
  position: relative;
  display: flex;
  width: 100%;
  min-width: 0;
  align-items: center;
  padding: 4px 8px;
}

.compose-field textarea {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  min-height: 24px;
  max-height: 120px;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  resize: none;
  color: var(--text-primary);
  font: inherit;
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  letter-spacing: -0.16px;
  background: transparent;
  border: 0;
  outline: 0;
  /* Auto-grows to content between min and max with no JS. Unsupported in
   * Firefox, which just keeps the rows="1" height -- acceptable degradation. */
  field-sizing: content;
}

.compose-field textarea::placeholder { color: #a6a09b; }

.compose-toolbar {
  display: flex;
  gap: 8px;
  align-items: center;
  width: 100%;
}

.compose-leading {
  position: relative;
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 8px;
}

.compose-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: flex-end;
  flex: 1 1 auto;
  overflow: visible;
}

.compose-attach,
.compose-kits,
.compose-mic {
  display: inline-flex;
  width: 36px;
  height: 36px;
  flex: none;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0;
  color: var(--text-secondary);
  background: transparent;
  border: 0;
  border-radius: 999px;
  line-height: 0;
  cursor: pointer;
  transition: background 160ms var(--ease-out-quint), color 160ms var(--ease-out-quint);
}

.compose-attach:hover,
.compose-kits:hover { background: var(--surface-subtle); }

.compose-send {
  position: relative;
  display: inline-flex;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  cursor: pointer;
  color: #fff;
  background: #0c0a09;
  border-radius: 999px;
  transition:
    background 220ms var(--ease-out-quint),
    color 220ms var(--ease-out-quint),
    transform 120ms var(--ease-out-quint);
}

.compose-send:hover:not(.is-disabled, :disabled) { background: #1c1917; }
.compose-send:active:not(.is-disabled, :disabled) { transform: scale(0.96); }
.compose-send:focus-visible { outline: none; }

/* Create toggles the class (its button stays clickable so a click can surface the
 * validation message); the Search button also carries the real `disabled`
 * attribute, because there is nothing to submit. Same look either way. */
.compose-send.is-disabled,
.compose-send:disabled {
  color: #d6d3d1;
  background: var(--surface-subtle);
  cursor: default;
  transform: none;
}
.compose-send.is-disabled:hover,
.compose-send:disabled:hover { background: var(--surface-subtle); }

.compose-icon {
  display: block;
  width: 20px;
  height: 20px;
  min-width: 20px;
  min-height: 20px;
  flex: 0 0 20px;
  overflow: hidden;
  pointer-events: none;
}

/* -------------------------------------------------------------- ideas --- */
/* The Create panel stacks the compose box and the ideas block 56px apart. */
.home-compose-block {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: stretch;
  gap: 56px;
}

.compose-ideas-block {
  display: flex;
  width: 100%;
  flex-direction: column;
  gap: 20px;
  align-items: stretch;
}

.compose-ideas-header {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
  justify-content: space-between;
  /* Lines the kicker up with the compose box's inner padding, not its edge. */
  padding-left: 12px;
  width: 100%;
}

.compose-ideas-header-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 16px;
}

.compose-ideas-kicker {
  margin: 0;
  color: var(--text-tertiary);
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: -0.14px;
}

/* Both header controls are bare text buttons -- no border, no background, and
 * they DARKEN to tertiary on hover rather than lightening. */
.compose-ideas-shuffle,
.compose-ideas-include {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  padding: 0;
  overflow: hidden;
  color: var(--text-primary);
  background: transparent;
  border: 0;
  cursor: pointer;
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: -0.14px;
  white-space: nowrap;
  transition: color 150ms ease-out;
}

.compose-ideas-shuffle { gap: 4px; }
.compose-ideas-include { gap: 6px; }

.compose-ideas-shuffle:hover,
.compose-ideas-include:hover { color: var(--text-tertiary); }

.compose-ideas-shuffle:focus-visible,
.compose-ideas-include:focus-visible,
.compose-idea:focus-visible {
  outline: 2px solid rgb(0 147 255 / 45%);
  outline-offset: 2px;
}

.compose-ideas-shuffle-icon {
  display: block;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
}

/* The label spans carry their own padding on top of the flex gap. */
.compose-ideas-shuffle span:not(.compose-ideas-shuffle-icon),
.compose-ideas-include > span:not(.t-toggle) { padding: 0 4px; }

/* ------------------------------------------------------------- switch --- */
.t-toggle {
  position: relative;
  display: inline-block;
  width: 24px;
  height: 16px;
  flex: 0 0 24px;
  background: #e7e5e4;
  border: 0;
  border-radius: 999px;
  transition: background 250ms var(--ease-out-quint);
}

.t-toggle-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #a6a09b;
  translate: 0 0;
  transition:
    translate 250ms var(--ease-out-quint),
    background-color 250ms var(--ease-out-quint);
}

.t-toggle[data-on="true"] { background: #17b26a; }

.t-toggle[data-on="true"] .t-toggle-thumb {
  background: #fff;
  translate: 8px 0;
}

/* -------------------------------------------------------------- pills --- */
/* Height is tweened by the controller on shuffle; see its render(). */
.compose-ideas {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  transition: height 300ms var(--ease-out-quint);
}

/* A 10px radius, NOT the 99px of the selection chips -- these are a different
 * species of control and the design distinguishes them by corner.
 *
 * The questions wrap rather than being held on one line. The prototype keeps
 * them nowrap, which is fine at its 640px hero but not at 360px, where the
 * longer questions are wider than the ~328px content area -- and since the row
 * clips its overflow for the height tween, they were cut off mid-sentence and
 * could not be read. max-width caps the pill at the row so nothing escapes it.
 * No visible change on desktop: the longest question still fits on one line. */
.compose-idea {
  display: flex;
  flex: 0 1 auto;
  max-width: 100%;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px;
  color: var(--text-primary);
  background: #fff;
  border: 0;
  border-radius: 10px;
  box-shadow:
    0 0 0 1px rgb(0 0 0 / 4%),
    0 1px 2px 0 rgb(3 7 18 / 5%);
  cursor: pointer;
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 20px;
  letter-spacing: -0.14px;
  text-align: left;
  transition:
    background-color 150ms ease-out,
    opacity 300ms var(--ease-out-quint);
}

.compose-idea:hover { background: #fafaf9; }
.compose-idea.is-enter { opacity: 0; }
.compose-idea-label { padding: 0 4px; }

@media (prefers-reduced-motion: reduce) {
  .compose-ideas,
  .compose-idea,
  .t-toggle,
  .t-toggle-thumb { transition: none !important; }
}

/* ---------------------------------------------------- reduced motion --- */
@media (prefers-reduced-motion: reduce) {
  .chip-mesh-orb::before { animation: none !important; }
  .t-tabs-pill,
  .t-tab,
  .home-mode-panel,
  .home-feed,
  .home-hero-copy p,
  .compose,
  .compose-chip,
  .compose-send { transition: none !important; }
}
