:root {
  color-scheme: dark;
  --bg: #060606;
  --panel: rgba(24, 24, 27, 0.5);
  --panel-strong: rgba(24, 24, 27, 0.82);
  --border: rgba(63, 63, 70, 0.65);
  --border-soft: rgba(39, 39, 42, 0.75);
  --text: #f4f4f5;
  --muted: #a1a1aa;
  --dim: #71717a;
  --accent: #38bdf8;
  --green: #34d399;
  --yellow: #fbbf24;
  --rose: #fb7185;
  --mono: "JetBrains Mono", ui-monospace, monospace;
}

* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body {
  background:
    radial-gradient(circle at 18% 8%, rgba(56, 189, 248, 0.12), transparent 28rem),
    radial-gradient(circle at 88% 16%, rgba(52, 211, 153, 0.09), transparent 24rem),
    var(--bg);
  color: var(--text);
  font: 15px/1.5 "Inter", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

button, input { font: inherit; }
button { color: inherit; cursor: pointer; }
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
::selection { background: rgba(56, 189, 248, 0.35); }

/* Full-bleed shell — stretch edge-to-edge like the sibling Image Studio apps
   (image-scrollytelling / infinite-meme-wall) so the topbar switcher sits at
   the very top-right of the screen. */
.shell { width: 100%; margin: 0; padding: 0 clamp(16px, 4vw, 40px) 18px; }

/* Full-bleed bar flush to the top of the screen, 60px tall with a
   clamp(0.9rem, 3vw, 2rem) inset — the same geometry the sibling Image Studio
   apps use, so the studio selector lands on the same pixel in all three. It was
   an inset rounded card inside .shell's padding, which pushed the selector ~20px
   down and ~21px in from where the other two put it. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: grid;
  grid-template-columns: auto 1fr minmax(210px, 320px);
  gap: 14px;
  align-items: center;
  /* min-height, not height: the family chips are free to wrap, and a fixed
     height would let the row grow past the bar's own background and drag the
     selector down with it. */
  min-height: 60px;
  padding: 0 clamp(0.9rem, 3vw, 2rem);
  border: 0;
  border-bottom: 1px solid var(--border-soft);
  background: rgba(6, 6, 6, 0.84);
  backdrop-filter: blur(16px);
}

.brand { display: inline-flex; align-items: center; gap: 11px; min-width: 220px; }
.brand svg { width: 38px; height: 38px; flex: none; }
.brand strong { display: block; font-weight: 800; letter-spacing: 0; }
.brand small { display: block; color: var(--dim); font-size: 12px; }

.families { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.chip,
.device-button,
.ratio-button {
  min-height: 34px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(24, 24, 27, 0.64);
  color: #d4d4d8;
  padding: 0 12px;
  font-size: 13px;
}
.chip[aria-pressed="true"],
.device-button[aria-selected="true"],
.ratio-button[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--text);
  background: rgba(14, 116, 144, 0.24);
}

.search {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 38px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(9, 9, 11, 0.72);
}
.search span { color: var(--dim); font-size: 12px; font-family: var(--mono); text-transform: uppercase; }
.search input {
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text);
}

.hero {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  align-items: end;
  padding: 48px 2px 22px;
}
.eyebrow {
  margin: 0 0 8px;
  color: var(--accent);
  font: 700 12px/1.2 var(--mono);
  text-transform: uppercase;
  letter-spacing: 0;
}
h1 { margin: 0; max-width: 900px; font-size: clamp(38px, 7vw, 88px); line-height: 0.92; letter-spacing: 0; }

/* Share bars (ToolShare widget) — positioning only; the bar styles itself. */
.tool-share { margin-top: 16px; }
.pack-share { margin-top: 12px; }
h2 { margin: 0; font-size: 18px; letter-spacing: 0; }
p { margin: 0; }

.metrics { display: grid; grid-template-columns: repeat(3, minmax(90px, 1fr)); gap: 10px; min-width: min(440px, 100%); }
.metric {
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: var(--panel);
  padding: 11px 12px;
}
.metric strong { display: block; font: 800 24px/1 var(--mono); color: var(--text); }
.metric span { color: var(--dim); font-size: 12px; }

.workspace {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(390px, 520px);
  gap: 18px;
  align-items: start;
}
.catalog,
.preview {
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: rgba(9, 9, 11, 0.58);
}
.catalog { padding: 14px; }
.catalog-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.catalog-head p,
#selectedSource { color: var(--dim); font-size: 13px; }
.catalog-controls { display: flex; align-items: center; gap: 12px; }
.sort {
  display: flex;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(24, 24, 27, 0.64);
}
.sort span { color: var(--dim); font-size: 11px; font-family: var(--mono); text-transform: uppercase; }
.sort select {
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
}
.sort select option { background: #18181b; color: var(--text); }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
}
.card {
  display: grid;
  grid-template-rows: auto 1fr;
  min-height: 315px;
  overflow: hidden;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: rgba(24, 24, 27, 0.46);
  text-align: left;
  padding: 0;
  transition: border-color 0.16s, transform 0.16s, background 0.16s;
}
.card:hover,
.card:focus-visible,
.card.active {
  border-color: var(--accent);
  background: var(--panel-strong);
  transform: translateY(-2px);
}
.mosaic {
  display: grid;
  /* grid-template-columns is set inline per-card from the tile count */
  grid-template-columns: repeat(3, 1fr);
  gap: 3px;
  padding: 3px;
  background: #0a0a0b;
}
.asset-tile {
  position: relative;
  min-width: 0;
  min-height: 0;
  aspect-ratio: 4 / 3;
  border: 0;
  background: #111114;
  padding: 0;
  overflow: hidden;
}
/* Wallpaper packs: full-width landscape tiles so the previews read large. */
.mosaic-wide .asset-tile { aspect-ratio: 16 / 9; }
.asset-tile:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  z-index: 1;
}
.asset-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #111114;
  transition: transform 0.16s, filter 0.16s;
}
.asset-tile:hover img { transform: scale(1.04); filter: brightness(1.08); }
/* "+4" on the last tile when the mosaic is capped (see renderGrid). The count is
   what the card is NOT showing — the pack view below has every asset. */
.asset-more {
  position: absolute;
  right: 6px;
  bottom: 6px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(9, 9, 11, 0.78);
  backdrop-filter: blur(6px);
  color: #e4e4e7;
  padding: 2px 8px;
  font: 700 11px/1.35 var(--mono);
  pointer-events: none;
}
.card-body { display: flex; flex-direction: column; gap: 9px; padding: 12px; }
.kind {
  align-self: start;
  border: 1px solid rgba(56, 189, 248, 0.35);
  border-radius: 999px;
  color: #bae6fd;
  padding: 3px 8px;
  font: 700 11px/1.1 var(--mono);
  text-transform: uppercase;
}
.card h3 { margin: 0; font-size: 16px; line-height: 1.25; }
.card-meta {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: auto;
  color: var(--dim);
  font: 12px/1.3 var(--mono);
}
.card-select {
  min-height: 34px;
  margin-top: 2px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: rgba(9, 9, 11, 0.65);
  color: #d4d4d8;
  font-weight: 700;
}
.card-select:hover,
.card-select:focus-visible {
  border-color: var(--accent);
  color: var(--text);
}
/* Pinned = this pack is held in the sandbox and hover no longer swaps it.
   Green, not accent, so it reads as a different state from plain hover/active —
   and it must come after `.card:hover` (equal specificity, source order wins). */
.card.pinned {
  border-color: var(--green);
  background: var(--panel-strong);
}
.card-select.is-pinned {
  border-color: rgba(52, 211, 153, 0.6);
  background: rgba(52, 211, 153, 0.14);
  color: #d1fae5;
}

.preview {
  position: sticky;
  top: 88px;
  /* When the preview is taller than the viewport, keep it fully reachable by
     letting the panel itself scroll instead of letting its bottom get clipped
     under the sticky offset. */
  max-height: calc(100vh - 100px);
  overflow-y: auto;
  padding: 14px;
}
.preview.pulse {
  animation: previewPulse 0.75s ease-out;
}
@keyframes previewPulse {
  0% { border-color: var(--accent); box-shadow: 0 0 0 0 rgba(56, 189, 248, 0.32); }
  100% { border-color: var(--border-soft); box-shadow: 0 0 0 18px rgba(56, 189, 248, 0); }
}
.device-tabs { display: flex; gap: 8px; margin-bottom: 14px; }
.stage {
  min-height: 390px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background:
    linear-gradient(135deg, rgba(255,255,255,0.045) 25%, transparent 25%) 0 0/18px 18px,
    #09090b;
  overflow: hidden;
}
.device { display: none; position: relative; box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45); }
.device.active { display: block; }
.device img { width: 100%; height: 100%; object-fit: cover; }

.phone {
  width: 210px;
  aspect-ratio: 9 / 19.5;
  padding: 10px;
  border: 2px solid #3f3f46;
  border-radius: 34px;
  background: #0c0c0e;
}
.phone img { border-radius: 25px; }
.notch {
  position: absolute;
  top: 17px;
  left: 50%;
  width: 72px;
  height: 18px;
  transform: translateX(-50%);
  border-radius: 0 0 13px 13px;
  background: #050505;
  z-index: 2;
}
.laptop { width: min(430px, 100%); }
.laptop .screen {
  aspect-ratio: 16 / 10;
  padding: 12px;
  border: 2px solid #3f3f46;
  border-radius: 13px 13px 5px 5px;
  background: #0c0c0e;
}
.laptop .screen img { border-radius: 5px; }
.laptop .base {
  width: 72%;
  height: 14px;
  margin: 0 auto;
  border-radius: 0 0 20px 20px;
  background: linear-gradient(90deg, #27272a, #71717a, #27272a);
}
.watch {
  width: 188px;
  aspect-ratio: 1;
  padding: 12px;
  border: 12px solid #27272a;
  border-radius: 44px;
  background: #0c0c0e;
}
.watch::before,
.watch::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 78px;
  height: 62px;
  transform: translateX(-50%);
  background: #18181b;
}
.watch::before { top: -70px; border-radius: 28px 28px 8px 8px; }
.watch::after { bottom: -70px; border-radius: 8px 8px 28px 28px; }
.watch img { border-radius: 30px; }

.selected {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  align-items: start;
  padding: 16px 2px 12px;
}
.download-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.download,
.export {
  border: 1px solid rgba(56, 189, 248, 0.55);
  border-radius: 8px;
  background: rgba(56, 189, 248, 0.16);
  color: var(--text);
  padding: 9px 12px;
  font-weight: 700;
  white-space: nowrap;
}
.download[type="button"] { cursor: pointer; }
/* Zipping a pack fetches every file first, so the button carries the progress. */
.download[disabled] { opacity: 0.62; cursor: progress; }

.pin-note {
  margin: 6px 0 0;
  color: var(--green);
  font: 600 12px/1.5 var(--mono);
}
.pin-note kbd {
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
  font: inherit;
  color: var(--text);
}

.pack-browser {
  border-top: 1px solid var(--border-soft);
  padding-top: 14px;
  margin-bottom: 14px;
}
.pack-browser-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 10px;
}
.pack-browser-head p {
  color: var(--dim);
  font-size: 12px;
}
.asset-list {
  display: grid;
  gap: 7px;
  max-height: 320px;
  overflow-y: auto;
  padding-right: 3px;
}
.asset-item {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) auto auto;
  gap: 9px;
  align-items: center;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: rgba(24, 24, 27, 0.42);
  padding: 6px;
}
.asset-item.active {
  border-color: var(--accent);
  background: rgba(14, 116, 144, 0.18);
}
.asset-pick {
  width: 46px;
  height: 46px;
  border: 1px solid var(--border-soft);
  border-radius: 7px;
  background: #0a0a0b;
  padding: 0;
  overflow: hidden;
}
.asset-pick img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.asset-item strong {
  display: block;
  overflow: hidden;
  color: var(--text);
  font-size: 12px;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.asset-item span {
  color: var(--dim);
  font: 11px/1.3 var(--mono);
}
.asset-open,
.asset-download {
  min-height: 30px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: rgba(9, 9, 11, 0.65);
  color: #d4d4d8;
  padding: 0 8px;
  font-size: 12px;
  font-weight: 700;
}
/* One save chip per format the asset ships (PNG / ICO / SVG). */
.asset-formats {
  display: flex;
  gap: 4px;
}
.asset-download {
  display: inline-flex;
  align-items: center;
  padding: 0 7px;
  font: 700 11px/1 var(--mono);
  letter-spacing: 0.02em;
}
.asset-open:hover,
.asset-open:focus-visible,
.asset-download:hover,
.asset-download:focus-visible {
  border-color: var(--accent);
  color: var(--text);
}

.swatches { display: grid; grid-template-columns: repeat(6, 1fr); gap: 7px; margin-bottom: 14px; }
.swatch {
  height: 34px;
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: 8px;
}

.cropper {
  border-top: 1px solid var(--border-soft);
  padding-top: 14px;
}
.cropper-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}
.ratios { display: flex; gap: 7px; flex-wrap: wrap; justify-content: flex-end; }
canvas {
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  background: #0a0a0b;
}
.export { width: 100%; margin-top: 10px; }

.empty {
  padding: 44px 10px;
  color: var(--dim);
  text-align: center;
  border: 1px dashed var(--border);
  border-radius: 8px;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 4vmin;
  background: rgba(3, 3, 4, 0.86);
  backdrop-filter: blur(8px);
  animation: lightboxIn 0.16s ease-out;
}
.lightbox[hidden] { display: none; }
@keyframes lightboxIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
.lightbox-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  max-width: 100%;
  max-height: 100%;
}
.lightbox-figure img {
  max-width: min(1400px, 92vw);
  max-height: 82vh;
  width: auto;
  height: auto;
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.6);
  background: #09090b;
  object-fit: contain;
}
.lightbox-figure figcaption {
  color: var(--muted);
  font: 500 13px/1.3 var(--mono);
  text-align: center;
}
.lightbox-close {
  position: fixed;
  top: 18px;
  right: 22px;
  z-index: 61;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: rgba(24, 24, 27, 0.72);
  color: var(--text);
  font-size: 26px;
  line-height: 1;
}
.lightbox-close:hover,
.lightbox-close:focus-visible {
  border-color: var(--accent);
  background: rgba(14, 116, 144, 0.3);
}
.lightbox-nav {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  z-index: 61;
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: rgba(24, 24, 27, 0.72);
  color: var(--text);
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
}
.lightbox-prev { left: 22px; }
.lightbox-next { right: 22px; }
.lightbox-nav:hover,
.lightbox-nav:focus-visible {
  border-color: var(--accent);
  background: rgba(14, 116, 144, 0.3);
}
.lightbox-nav[hidden] { display: none; }
@media (max-width: 560px) {
  .lightbox-nav { width: 44px; height: 44px; font-size: 26px; }
  .lightbox-prev { left: 10px; }
  .lightbox-next { right: 10px; }
}

/* Bar only: below ~1280 the six family chips no longer fit beside the brand,
   search and selector on one 60px row, so the bar splits — brand + the studio
   selector on top (selector still hard in the top-right corner, as on the
   sibling apps), filters + search underneath. This is a wider breakpoint than
   the page layout's 1100 below on purpose: it is the width where the *bar*
   stops fitting, not where the page does. */
@media (max-width: 1280px) {
  .topbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 12px;
    min-height: 0;
    padding: 10px clamp(0.9rem, 3vw, 2rem);
  }
  /* `flex: 1 1 0` — a zero basis, so the brand can never be wide enough to push
     the selector onto a second row; it just takes what's left and ellipsises. */
  .brand { flex: 1 1 0; min-width: 0; min-height: 40px; }
  .studio-switch { order: 0; flex: 0 0 auto; justify-self: auto; margin-left: auto; }
  /* `flex-basis: 100%` — not `auto` — so the chips always take their own row.
     Left to size themselves they slot in beside the brand on row 1 and strand
     the selector in the middle of the bar instead of at its right edge. */
  .families { order: 1; flex: 1 1 100%; justify-content: flex-start; }
  .search { order: 2; flex: 1 1 100%; }
}

@media (max-width: 1100px) {
  .hero { display: grid; }
  .metrics { min-width: 0; }
  .workspace { grid-template-columns: 1fr; }
  .preview { position: static; order: -1; max-height: none; overflow: visible; }
}

@media (max-width: 620px) {
  .shell { padding: 10px; }
  /* Ellipsis rather than wrap: a two-line brand pushes the selector onto its own
     row and out of the corner on a 320px screen. */
  .brand svg { width: 32px; height: 32px; }
  .brand > span { min-width: 0; }
  .brand strong,
  .brand small { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .catalog-head { flex-wrap: wrap; }
  .catalog-controls { width: 100%; justify-content: space-between; }
  .metrics { grid-template-columns: 1fr; }
  .grid { grid-template-columns: 1fr; }
  .selected,
  .cropper-head { display: grid; }
  .download-actions { justify-content: stretch; }
  .download-actions > * { text-align: center; flex: 1 1 140px; }
  .asset-item { grid-template-columns: 44px minmax(0, 1fr) auto; }
  .asset-formats { display: none; }
  .swatches { grid-template-columns: repeat(3, 1fr); }
  h1 { font-size: 40px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

/* ---- Image Studio selector (topbar, far right) ------------------------- */
/* Three-way segmented selector, mirrors the Image Studio bar so every surface
   shows the same top-right selector. Hidden when embedded (shell bar covers it).
   On desktop the topbar gets a 4th column for it; on narrow screens the topbar
   already stacks to one column and the selector stacks with it (icon-only). */
/* The one-row bar carries a 4th column for the selector; pairs with the
   max-width: 1280px split above. The chips scroll rather than wrap here — a
   wrapped second line would grow the row past the bar's 60px and carry the
   selector down with it, which is exactly what we're keeping fixed. */
@media (min-width: 1281px) {
  .topbar { grid-template-columns: auto 1fr minmax(160px, 260px) auto; }
  .families {
    flex-wrap: nowrap;
    overflow-x: auto;
    /* flex-start, not the default centring: content centred inside a scroll
       container overflows both edges, and the part off the left edge can't be
       scrolled back to — the "All" chip becomes unreachable. */
    justify-content: flex-start;
    scrollbar-width: none;
    -ms-overflow-style: none;
    mask-image: linear-gradient(90deg, transparent, #000 12px, #000 calc(100% - 12px), transparent);
  }
  .families::-webkit-scrollbar { display: none; }
  .families .chip { flex: 0 0 auto; }
}
.studio-switch {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: rgba(6, 6, 6, 0.6);
}
.studio-switch[hidden] { display: none; }
.studio-seg {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.34rem 0.6rem;
  border-radius: 999px;
  font-size: 0.74rem;
  line-height: 1.5;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s, color 0.15s;
}
.studio-seg svg { width: 14px; height: 14px; }
.studio-seg:not(.is-active):hover { color: var(--text); background: rgba(255, 255, 255, 0.06); }
.studio-seg.is-active {
  color: var(--text);
  background: color-mix(in srgb, #a78bfa 20%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #a78bfa 50%, transparent);
  cursor: default;
}
.studio-seg.is-active svg { color: #a78bfa; }
@media (max-width: 820px) {
  .studio-seg span { display: none; }
  .studio-seg { padding: 0.4rem 0.5rem; }
}
