/* ───────────────────────────────────────────────────────────────────────────
   Re-enable page scrolling.

   app.css ships TWO unscoped `body, html { width:100vw; height:100vh;
   overflow:hidden }` blocks — "LAYOUT OVERFLOW FIXES" and "FLEXBOX OVERFLOW
   FIXES", the second with !important — written to pin the dashboard's fixed
   app shell. Every page that loads app.css inherits them, so a normal document
   is clamped to exactly one viewport with scrolling off.

   account.php and projects.php never noticed because .settings-main is its own
   scroll container; the body does not need to scroll there. These two pages
   render WITHOUT that shell for a logged-out visitor — the whole point of a
   public prompt page — so the body is the only thing that can scroll, and it
   could not. Measured on the live page: 5,117px of content in a 720px body
   with overflow-y computing to hidden.

   landing.css and register.css already carry the same override for the same
   reason; this is the third instance of that trap, and the comment there notes
   it must be unconditional rather than scoped to a breakpoint.

   The axes are set separately on purpose: a blanket `overflow: visible` would
   let anything wide (a long <pre>, a card grid) scroll the page sideways.

   Harmless for the signed-in layout: .settings-wrap is exactly 100vh, so the
   body still has nothing to overflow and no second scrollbar appears.
   ─────────────────────────────────────────────────────────────────────────── */
html, body {
  width: auto !important;
  height: auto !important;
  min-height: 100% !important;
  overflow-x: hidden !important;
  overflow-y: auto !important;
}

/* ───────────────────────────────────────────────────────────────────────────
   Prompt Library

   Everything here is built on the shared tokens (--surface, --border,
   --primary, --r-*, --shadow-*) rather than fixed colours, so the page follows
   both theme axes — the colour themes and the style "-isms" — without needing
   a single entry in style-themes.css. The one thing worth knowing: card
   radius and elevation come from the token aliases, which the style themes
   redefine, so a Brutalism card squares off on its own.
   ─────────────────────────────────────────────────────────────────────────── */

.pl-wrap { max-width: 1180px; margin: 0 auto; padding: 26px 24px 80px; }
/* Logged-out visitors get the shared sticky public nav above this instead of
   the settings sidebar, so the top padding has to clear it. */
.pl-wrap-guest { max-width: 1180px; padding-top: 34px; }

.pl-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
.pl-head > div:first-child { flex: 1; min-width: 0; }
.pl-h1 { margin: 0 0 4px; font-size: 1.5rem; font-weight: 800; letter-spacing: -.02em; }
.pl-sub { margin: 0; color: var(--muted); font-size: .86rem; }
.pl-quota {
  display: inline-block; margin-left: 8px; padding: 1px 8px;
  border-radius: var(--r-full, 99px); background: var(--surface-2);
  font-size: .74rem; color: var(--muted);
}

/* ── Tabs ── */
.pl-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 18px; flex-wrap: wrap; }
.pl-tab {
  padding: 9px 14px; font-size: .84rem; font-weight: 600;
  color: var(--muted); text-decoration: none;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.pl-tab:hover { color: var(--text); }
.pl-tab.active { color: var(--primary); border-bottom-color: var(--primary); }

/* ── Filters ── */
.pl-filters { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.pl-search {
  flex: 1; min-width: 200px; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: var(--r-md, 10px);
  background: var(--surface); color: var(--text); font-size: .86rem;
}
.pl-select {
  padding: 9px 10px; border: 1px solid var(--border); border-radius: var(--r-md, 10px);
  background: var(--surface); color: var(--text); font-size: .84rem;
}

.pl-tagrail { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 20px; }
.pl-tag {
  padding: 3px 10px; border-radius: var(--r-full, 99px);
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: .74rem; color: var(--muted); text-decoration: none;
}
.pl-tag:hover { color: var(--primary); border-color: var(--primary); }
.pl-tag.active { background: var(--primary); color: var(--on-accent, #fff); border-color: var(--primary); }

/* ── Card grid ── */
.pl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px;
}
.pl-card {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg, 14px); overflow: hidden;
  text-decoration: none; color: inherit;
  box-shadow: var(--shadow-1, none);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.pl-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-2, none); border-color: var(--primary); }
.pl-card-img { display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--surface-2); }
.pl-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* No example attached — which most imported prompts will never have, since a
   classifier can file a prompt but cannot invent a picture of its output. The
   blank state is branded rather than absent: the site mark over the prompt's
   own initial, so a full library of unillustrated prompts reads as deliberate
   instead of as a grid of failed images. */
.pl-card-img-none {
  display: flex; align-items: center; justify-content: center;
  background:
    radial-gradient(circle at 30% 25%, color-mix(in srgb, var(--primary) 16%, transparent), transparent 62%),
    color-mix(in srgb, var(--primary) 7%, var(--surface-2));
}
.pl-blank { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
/* Inline SVG, so it takes the accent colour directly — no filter, and it
   follows every colour theme without a per-theme rule.

   Nudged DOWN by 8.333%, which is exactly 2/24 of the viewBox. The bubble body
   spans y=3..17 of a 24-unit box, so its centre is y=10 while the box centre is
   y=12; shifting the whole mark down by that difference puts the BODY on the
   container's centre, which is where the letter is. The tail then hangs a
   little lower, which is what a speech-bubble tail does anyway.
   
   Doing it on the mark rather than the letter is what makes this size-
   independent: a percentage of the mark's own height is correct at 86px, at
   40px and at any size added later, where a per-context em nudge on the letter
   had to be recalculated each time and was wrong in two of three places. */
.pl-blank-mark {
  position: absolute; width: 44%; max-width: 86px; height: auto;
  color: var(--primary); opacity: .22;
  transform: translateY(8.333%);
}
/* The mark now carries the bubble-centring offset (above), so the letter only
   needs its own optical correction: with line-height 1 the box is 1em tall but
   a capital sits from about 0.08em to 0.80em, so the glyph's optical centre is
   ~0.06em above the box centre. Pushing it back down by that much lands the
   letter on the bubble's centre at every size, with no per-context value. */
.pl-blank-letter {
  position: relative; font-size: 1.9rem; font-weight: 800; letter-spacing: -.02em;
  line-height: 1; color: var(--primary);
  transform: translateY(0.06em);
}

/* The mark beside the title. Replaces a 150px page-width panel that existed
   only to say "no example" — a badge does that in a fifth of the space and
   leaves the title as the first thing read. */
.pl-head-row { display: flex; align-items: center; gap: 14px; margin-bottom: 6px; }
.pl-head-mark {
  flex: 0 0 auto; width: 54px; height: 54px;
  border-radius: var(--r-md, 12px); overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--primary) 10%, var(--surface-2));
  border: 1px solid var(--border);
}
/* The bubble and the letter are sized together, not independently. The cards
   settled at a letter:mark ratio of about 0.35 and read well; the header and
   the sidebar were built at 0.72, which is why the letter crowded an icon that
   looked too small for it. Both are brought back to the card's proportion. */
.pl-head-mark .pl-blank-mark { width: 40px; max-width: none; opacity: .26; }
.pl-head-mark .pl-blank-letter { font-size: .95rem; }
@media (max-width: 620px) { .pl-head-mark { width: 44px; height: 44px; } }
.pl-card-body { display: flex; flex-direction: column; gap: 5px; padding: 12px 13px 13px; }
.pl-card-cat { font-size: .68rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted-2, var(--muted)); font-weight: 700; }
.pl-card-title { font-size: .92rem; font-weight: 700; line-height: 1.3; }
.pl-card-sub {
  font-size: .78rem; color: var(--muted); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pl-card-meta { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-top: 2px; }
.pl-card-rating, .pl-card-uses { font-size: .72rem; color: var(--muted); }

/* ── Badges ── */
.pl-badge {
  display: inline-block; padding: 1px 7px; border-radius: var(--r-sm, 5px);
  font-size: .68rem; font-weight: 700; background: var(--surface-2); color: var(--muted);
  border: 1px solid var(--border);
}
.pl-badge-official { background: color-mix(in srgb, var(--primary) 14%, transparent); color: var(--primary); border-color: transparent; }
.pl-badge-pending  { background: color-mix(in srgb, var(--warning, #b7791f) 16%, transparent); color: var(--warning, #b7791f); border-color: transparent; }
.pl-badge-rejected { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); border-color: transparent; }
.pl-badge-nsfw     { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); border-color: transparent; }
.pl-badge-cat      { background: color-mix(in srgb, var(--primary) 10%, transparent); color: var(--primary); border-color: transparent; }

/* ── Empty states ── */
.pl-empty {
  text-align: center; padding: 60px 24px; color: var(--muted);
  border: 1px dashed var(--border); border-radius: var(--r-lg, 14px);
}
.pl-empty h3 { margin: 0 0 6px; font-size: 1.05rem; color: var(--text); }
.pl-empty p  { margin: 0 0 14px; font-size: .86rem; }

/* ── Collections ── */
.pl-collections { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px; }
.pl-col-card {
  display: block; text-align: left; padding: 16px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg, 14px); text-decoration: none; color: inherit;
  font: inherit; cursor: pointer;
}
.pl-col-card h4 { margin: 0 0 6px; font-size: .95rem; }
.pl-col-card p  { margin: 0 0 8px; font-size: .8rem; color: var(--muted); }
.pl-col-count   { font-size: .74rem; color: var(--muted-2, var(--muted)); }
.pl-col-new { border-style: dashed; color: var(--muted); text-align: center; }

/* ── Detail page ── */
/* A breadcrumb rather than a back link: it says where this page sits and gives
   a crawler a second route into the category, which a bare arrow does not. */
.pl-crumbs { display: flex; align-items: center; gap: 7px; margin-bottom: 16px; font-size: .78rem; flex-wrap: wrap; }
.pl-crumbs a { color: var(--muted); text-decoration: none; }
.pl-crumbs a:hover { color: var(--primary); }
.pl-crumbs span { color: var(--muted-2, var(--muted)); }
.pl-back { font-size: .82rem; color: var(--muted); text-decoration: none; }
.pl-back:hover { color: var(--primary); }

.pl-detail { display: grid; grid-template-columns: minmax(0, 1fr) 296px; gap: 34px; align-items: start; }
@media (max-width: 900px) { .pl-detail { grid-template-columns: 1fr; } }

.pl-detail-head h1 { margin: 0 0 6px; font-size: 1.7rem; font-weight: 800; letter-spacing: -.02em; }
.pl-detail-sub { margin: 0 0 10px; color: var(--muted); font-size: .95rem; }
.pl-detail-meta { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; font-size: .78rem; color: var(--muted); }
.pl-forked { margin: 10px 0 0; font-size: .78rem; color: var(--muted); }
.pl-forked a { color: var(--primary); }

.pl-detail-main section { margin-top: 34px; }
.pl-detail-main section:first-of-type { margin-top: 26px; }
.pl-detail-main h2 { font-size: 1rem; font-weight: 700; margin: 0 0 10px; }
.pl-detail-main h3 { font-size: .85rem; font-weight: 700; margin: 16px 0 6px; color: var(--muted); }
.pl-prose { font-size: .88rem; line-height: 1.7; }

/* Sits on the block it copies. The heading row is flex so the button hugs the
   right edge at any heading length. */
.pl-promptbox-hd { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.pl-promptbox-hd h2 { margin: 0; }
.pl-copy {
  margin-left: auto; display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit; font-size: .76rem; font-weight: 600; cursor: pointer;
  padding: 6px 12px; border-radius: var(--r-full, 99px);
  color: var(--muted); background: var(--surface); border: 1px solid var(--border);
  transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}
.pl-copy:hover { color: var(--primary); border-color: var(--primary); background: var(--accent-softer, var(--surface)); }
/* Confirmation lives in the button rather than a toast: a copy is not news, it
   just needs acknowledging where the click happened. */
.pl-copy.is-copied {
  color: var(--on-accent, #fff); background: var(--primary); border-color: var(--primary);
}

/* The page's own surface, NOT --code-bg.
   --code-bg is a fixed dark value (rgb(30,30,46)) meant for syntax-highlighted
   code inside a chat bubble, and it does not change with the theme. Using it
   here put a black slab in the middle of a white page — which is what read as
   "this page ignores light mode". A prompt is prose that happens to be
   monospaced, not code, so it belongs on a normal surface that follows both
   themes and every accent. */
.pl-pre {
  background: var(--surface-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--r-md, 10px);
  padding: 15px 17px;
  font-size: .82rem; line-height: 1.72;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: pre-wrap; word-break: break-word; margin: 0;
  /* Wide prompts scroll inside the block rather than widening the page. */
  overflow-x: auto;
}
.pl-pre-sys {
  border-left: 3px solid var(--primary);
  background: color-mix(in srgb, var(--primary) 5%, var(--surface-2));
}

/* ── Sample-output gallery ── */
.pl-gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 12px; }
.pl-shot { margin: 0; border: 1px solid var(--border); border-radius: var(--r-md, 10px); overflow: hidden; background: var(--surface); }
.pl-shot img { width: 100%; display: block; cursor: zoom-in; }
.pl-shot figcaption {
  padding: 7px 9px; font-size: .74rem; color: var(--muted);
  display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
}
.pl-shot figcaption em { font-style: normal; color: var(--muted-2, var(--muted)); font-size: .7rem; }
.pl-shot-pending { opacity: .75; border-style: dashed; }
.pl-shot-del { margin-left: auto; background: none; border: 0; color: var(--danger); cursor: pointer; font-size: .8rem; }

/* A non-image example: a labelled card that opens the file, not a preview
   attempt. A broken embed reads as a broken feature; a card does not. */
.pl-filecard {
  display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
  padding: 18px 14px; text-decoration: none; color: inherit;
  background: color-mix(in srgb, var(--primary) 6%, transparent);
  min-height: 96px; justify-content: center;
}
.pl-filecard:hover { background: color-mix(in srgb, var(--primary) 12%, transparent); }
.pl-filecard-ext {
  font-size: .68rem; font-weight: 800; letter-spacing: .06em;
  color: var(--on-accent, #fff); background: var(--primary);
  padding: 2px 7px; border-radius: var(--r-sm, 4px);
}
.pl-filecard-name { font-size: .82rem; font-weight: 600; word-break: break-word; }
.pl-filecard-size { font-size: .72rem; color: var(--muted); }

.pl-lightbox {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(0,0,0,.86); display: flex; align-items: center; justify-content: center;
  padding: 24px; cursor: zoom-out;
}
.pl-lightbox img { max-width: 100%; max-height: 100%; border-radius: var(--r-md, 10px); }

/* ── Variables + example ── */
.pl-vars ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.pl-vars li { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; font-size: .84rem; }
.pl-vars code { background: var(--surface-2); padding: 1px 6px; border-radius: var(--r-sm, 5px); font-size: .78rem; }
.pl-vars em { color: var(--muted); font-style: normal; font-size: .78rem; }
.pl-req { font-size: .68rem; color: var(--danger); font-weight: 700; }
.pl-example-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 700px) { .pl-example-grid { grid-template-columns: 1fr; } }

/* ── Reviews ── */
.pl-review-form { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; font-size: .82rem; }
.pl-review-form input { flex: 1; min-width: 180px; padding: 7px 10px; border: 1px solid var(--border); border-radius: var(--r-md, 8px); background: var(--surface); color: var(--text); }
.pl-star { background: none; border: 0; font-size: 1.1rem; color: var(--border-strong, var(--border)); cursor: pointer; padding: 0 1px; }
.pl-star.on { color: var(--primary); }
.pl-review { padding: 10px 0; border-bottom: 1px solid var(--border); font-size: .84rem; }
.pl-review p { margin: 4px 0 0; color: var(--muted); }
.pl-rate { color: var(--primary); font-weight: 600; }
.pl-rate em { font-style: normal; color: var(--muted); font-weight: 400; }

/* ── Sidebar ── */
.pl-actions { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.pl-actions .btn { width: 100%; justify-content: center; }
.pl-report { color: var(--danger); }
.pl-side-box {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg, 12px); padding: 13px 14px; margin-bottom: 12px;
}
.pl-side-box h4 { margin: 0 0 8px; font-size: .74rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }

/* Sticky, because the prompt itself is often long and the actions should not
   scroll away from it. Offsets differ by shell: a logged-out visitor has the
   sticky public nav above, a signed-in one scrolls inside .settings-main. */
.pl-detail-side { position: sticky; top: 18px; align-self: start; }
.pl-wrap-guest .pl-detail-side { top: 76px; }
@media (max-width: 900px) { .pl-detail-side { position: static; } }

.pl-sidesearch {
  display: flex; align-items: center; gap: 7px;
  padding: 7px 11px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-full, 99px);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.pl-sidesearch:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px var(--accent-softer, transparent); }
.pl-sidesearch svg { color: var(--muted); flex-shrink: 0; }
.pl-sidesearch input {
  flex: 1; min-width: 0; border: 0; background: none; outline: none;
  color: var(--text); font-size: .82rem; font-family: inherit;
}

/* "More in this category" as a list, not a grid: it is a menu of places to go
   next, and six titles read faster stacked than they do as cards. */
.pl-side-item {
  display: flex; align-items: center; gap: 9px;
  padding: 6px; margin: 0 -6px; border-radius: var(--r-md, 9px);
  text-decoration: none; color: inherit;
  transition: background-color .14s ease;
}
.pl-side-item:hover { background: var(--accent-softer, var(--surface-2)); }
.pl-side-item-mark {
  flex: 0 0 auto; width: 34px; height: 34px; overflow: hidden;
  border-radius: var(--r-sm, 7px);
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--primary) 9%, var(--surface-2));
}
.pl-side-item-mark .pl-blank-mark { display: none; }
/* No bubble in this chip, so no bubble to centre on — the letter sits plain. */
.pl-side-item-mark .pl-blank-letter { font-size: .8rem; transform: none; }
.pl-side-item-t {
  font-size: .81rem; line-height: 1.35; font-weight: 500;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pl-side-item:hover .pl-side-item-t { color: var(--primary); }
.pl-side-more {
  display: inline-block; margin-top: 9px;
  font-size: .76rem; color: var(--primary); text-decoration: none; font-weight: 600;
}
.pl-side-more:hover { text-decoration: underline; }
.pl-side-box p  { margin: 0; font-size: .84rem; }
.pl-side-box select, .pl-linkfield {
  width: 100%; padding: 7px 9px; font-size: .8rem;
  border: 1px solid var(--border); border-radius: var(--r-md, 8px);
  background: var(--surface); color: var(--text);
}
.pl-linkfield { margin-top: 8px; font-family: monospace; font-size: .72rem; }

.pl-share-row { display: flex; align-items: center; gap: 6px; font-size: .8rem; padding: 4px 0; }
.pl-share-row span { flex: 1; }
.pl-share-row em { font-style: normal; color: var(--muted); font-size: .72rem; }
.pl-share-row button { background: none; border: 0; color: var(--danger); cursor: pointer; }
.pl-share-add { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-top: 8px; }
.pl-share-add input[type=email] { flex: 1; min-width: 130px; padding: 6px 8px; font-size: .78rem; border: 1px solid var(--border); border-radius: var(--r-md, 8px); background: var(--surface); color: var(--text); }
.pl-share-add label { font-size: .74rem; color: var(--muted); display: flex; gap: 4px; align-items: center; }

/* ── More prompts (foot of the detail page) ── */
.pl-more { margin-top: 46px; }
.pl-more-hd {
  display: flex; align-items: baseline; gap: 12px; margin-bottom: 16px;
  padding-bottom: 10px; border-bottom: 1px solid var(--border);
}
.pl-more-hd h2 { margin: 0; font-size: 1.05rem; font-weight: 700; }
.pl-more-hd a { margin-left: auto; font-size: .8rem; color: var(--primary); text-decoration: none; white-space: nowrap; }
.pl-more-hd a:hover { text-decoration: underline; }
/* Denser than the browse grid — these are a footer, not the main event, and
   they now sit in the main column rather than across the page. */
.pl-more .pl-grid { grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 12px; }
.pl-more .pl-card-img { aspect-ratio: 16 / 9; }
.pl-more .pl-card-body { padding: 10px 11px 11px; gap: 4px; }
.pl-more .pl-card-title { font-size: .84rem; }
.pl-more .pl-card-sub { font-size: .74rem; -webkit-line-clamp: 2; }

/* ── Notices ── */
.pl-notice {
  padding: 11px 14px; border-radius: var(--r-md, 10px); font-size: .83rem;
  margin-bottom: 16px; line-height: 1.55;
}
.pl-notice-wait { background: color-mix(in srgb, var(--warning, #b7791f) 12%, transparent); color: var(--warning, #b7791f); }
.pl-notice-bad  { background: color-mix(in srgb, var(--danger) 10%, transparent); color: var(--danger); }

/* ── Editor modal ── */
.pl-modal-back {
  position: fixed; inset: 0; z-index: 9000; background: rgba(0,0,0,.5);
  display: flex; align-items: flex-start; justify-content: center; padding: 30px 16px; overflow-y: auto;
}
.pl-modal {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg, 16px); box-shadow: var(--shadow-4, 0 20px 60px rgba(0,0,0,.3));
  width: 100%; max-width: 640px; padding: 22px 24px;
}
.pl-modal h3 { margin: 0 0 14px; font-size: 1.1rem; }
.pl-field { display: block; margin-bottom: 13px; }
.pl-field > span { display: block; font-size: .76rem; font-weight: 600; color: var(--muted); margin-bottom: 4px; }
.pl-field input, .pl-field textarea, .pl-field select {
  width: 100%; padding: 8px 10px; font-size: .85rem; font-family: inherit;
  border: 1px solid var(--border); border-radius: var(--r-md, 8px);
  background: var(--surface); color: var(--text); box-sizing: border-box;
}
.pl-field textarea { min-height: 110px; resize: vertical; line-height: 1.55; }
.pl-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 560px) { .pl-field-row { grid-template-columns: 1fr; } }
.pl-modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px; }
.pl-modal-err { color: var(--danger); font-size: .8rem; margin: 8px 0 0; }
.pl-hint { font-size: .74rem; color: var(--muted); margin: 4px 0 0; }

/* ── Composer panel (dashboard) ── */
.pl-composer-panel {
  position: absolute; bottom: calc(100% + 8px); left: 14px; right: 14px;
  background: var(--surface); border: 1.5px solid var(--primary);
  border-radius: var(--r-lg, 14px); box-shadow: var(--shadow-3, 0 8px 32px rgba(0,0,0,.15));
  z-index: 500; max-height: 340px; display: flex; flex-direction: column; overflow: hidden;
}
.pl-cp-head { display: flex; gap: 8px; align-items: center; padding: 9px 12px; border-bottom: 1px solid var(--border); }
.pl-cp-head input { flex: 1; border: 0; background: none; color: var(--text); font-size: .86rem; outline: none; }
.pl-cp-head a { font-size: .74rem; color: var(--muted); text-decoration: none; }
.pl-cp-list { overflow-y: auto; padding: 6px; }
.pl-cp-item { display: flex; gap: 9px; align-items: center; padding: 8px 10px; border-radius: var(--r-md, 9px); cursor: pointer; }
.pl-cp-item:hover, .pl-cp-item.active { background: color-mix(in srgb, var(--primary) 10%, transparent); }
.pl-cp-item img { width: 32px; height: 24px; object-fit: cover; border-radius: var(--r-sm, 4px); flex-shrink: 0; }
.pl-cp-item .pl-cp-t { font-size: .84rem; font-weight: 600; }
.pl-cp-item .pl-cp-d { font-size: .76rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.pl-cp-section { padding: 7px 10px 3px; font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.pl-cp-empty { padding: 18px; text-align: center; color: var(--muted); font-size: .82rem; }

/* ── Homepage section ── */
.pl-home { padding: 60px 0; }
.pl-home-head { text-align: center; margin-bottom: 30px; }
.pl-home-head h2 { margin: 0 0 8px; font-size: 1.9rem; font-weight: 800; letter-spacing: -.02em; }
.pl-home-head p  { margin: 0; color: var(--muted); font-size: .95rem; }
.pl-home .pl-grid { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
.pl-home-more { text-align: center; margin-top: 26px; }
