/* ── User background layer ───────────────────────────────── */
.user-bg-layer {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  background: var(--bg);
}

.user-bg-layer img,
.user-bg-layer video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: blur(var(--bg-blur)) saturate(1.08) brightness(0.88);
  transform: scale(var(--bg-scale));
  opacity: 0;
  transition: opacity 0.22s ease, filter 0.22s ease, transform 0.22s ease;
}

body.has-user-bg .user-bg-layer img:not([hidden]),
body.has-user-bg .user-bg-layer video:not([hidden]) { opacity: 1; }

.user-bg-layer::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(0,0,0,var(--bg-safe-dim)), rgba(0,0,0,var(--bg-safe-dim-strong))),
    radial-gradient(80% 90% at 50% 0%, rgba(var(--accent-rgb),0.11), transparent 62%);
}

.shell { position: relative; z-index: 1; }

/* ── Accent-aware overrides ───────────────────────────────── */
.qbtn-settings,
.qbtn-tabs,
.qbtn-focus,
.qbtn-apps { color: var(--green); }

.status-dot-inline {
  background: var(--green);
  box-shadow: 0 0 12px rgba(var(--accent-rgb), 0.5);
}

.lang-seg.active {
  background: rgba(var(--accent-rgb), 0.18);
  color: #f2fff7;
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), 0.32);
}

.tab-card:hover { border-color: rgba(var(--accent-rgb),0.32); }
.tab-card.active {
  border-color: rgba(var(--accent-rgb),0.66);
  background: rgba(var(--accent-rgb),0.09);
}
.tab-icon {
  background: rgba(var(--accent-rgb),0.10);
  color: var(--green);
}
.tab-current {
  background: rgba(var(--accent-rgb),0.15);
  color: var(--green);
}

input[type="range"] { accent-color: var(--green); }

/* ── Settings modal ───────────────────────────────────────── */
.settings-overlay[hidden] { display: none !important; }
.settings-overlay {
  position: fixed;
  inset: 0;
  z-index: 220;
  display: grid;
  place-items: center;
  padding: 14px;
  /* The dimming scrim and its blur now follow the Aspetto sliders (oscuramento
     sfondo → --bg-safe-dim, sfocatura sfondo → --bg-blur) instead of being fixed,
     so the "haze" the user sees over the dashboard while in Settings actually
     responds to those controls. --bg-safe-dim keeps a readable floor (0.18). */
  background: rgba(0,0,0,var(--bg-safe-dim, 0.48));
  backdrop-filter: blur(var(--bg-blur, 0px));
}

.settings-panel {
  /* Size against the fixed overlay (% ), NOT the viewport (vw/vh). On the Xeneon
     Edge the page is rendered with CSS `zoom` for DPR sharpness, and vw/vh ignore
     that zoom — so a vw-sized panel would be magnified past the screen and clip on
     the right. The overlay's inset:0 box is already correct in the zoomed space. */
  width: 100%;
  height: 100%;
  max-height: 100%;
  overflow: hidden;
  display: grid;
  grid-template-rows: auto minmax(0,1fr) auto;
  border: 1px solid rgba(var(--accent-rgb),0.22);
  border-radius: 16px;
  /* Panel translucency + frosted glass track the Aspetto sliders (opacità pannelli
     → --panel-alpha, sfocatura/saturazione vetro → --glass-blur/--glass-saturate).
     A 0.6 opacity floor keeps the modal legible even when the user makes the
     dashboard tiles very translucent; at the default 0.94 the glass is masked, so
     the stock look is unchanged and the frost only appears as opacity is lowered. */
  background:
    radial-gradient(120% 110% at 0% 0%, rgba(var(--accent-rgb),0.12), transparent 48%),
    rgba(13,18,17, max(0.6, var(--panel-alpha, 0.94)));
  backdrop-filter: blur(var(--glass-blur, 22px)) saturate(var(--glass-saturate, 160%));
  box-shadow: 0 24px 90px rgba(0,0,0,0.68), 0 0 60px rgba(var(--accent-rgb),0.12);
}

.settings-head {
  position: relative; /* anchors the "try the native app" dropdown */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px 10px;
  border-bottom: 1px solid rgba(255,255,255,0.07);
}

.settings-head-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
}

.settings-title-wrap { min-width: 0; }
.settings-title {
  font-size: 18px;
  font-weight: 950;
  color: var(--text);
  letter-spacing: 0;
}
.settings-subtitle {
  margin-top: 3px;
  font-size: 12.5px;
  font-weight: 750;
  color: var(--muted-text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Store pill — the standout header action: a solid accent fill so the
   community catalog is one tap from any Settings category.
   The ink is --on-accent, never a hardcoded #fff: the palette derives it from
   the accent's own luminance and guards it to 4.5:1, so a light accent gets
   dark ink. Hardcoded white scored 2.15:1 on the stock amber — the label and
   the bag glyph both washed out. The fill is solid for the same reason: at 0.9
   the dark modal showed through and dragged the ratio down again. */
.settings-store-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  /* Sized to lead the header, not to match the close button beside it. At the
     old 31px it sat level with a 32px icon button and read as one more control
     in a row of controls, which is the opposite of what it is. */
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: var(--accent);
  color: var(--on-accent);
  font: inherit;
  font-size: 14px;
  font-weight: 850;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: 0 4px 14px rgba(var(--accent-rgb), 0.28);
  transition: background .15s ease, box-shadow .15s ease, transform .12s ease;
}
.settings-store-pill:hover { filter: brightness(1.07); box-shadow: 0 6px 18px rgba(var(--accent-rgb), 0.4); }
.settings-store-pill:active { transform: translateY(1px); }
/* The bag is an outline, so it must not inherit the filled-glyph treatment the
   rest of this header uses — a fill would close the handle and lose the shape. */
.store-glyph { fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.settings-store-pill svg { width: 19px; height: 19px; flex: 0 0 auto; }

.settings-close {
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 9px;
  display: grid;
  place-items: center;
  color: var(--muted-text);
  background: rgba(255,255,255,0.035);
  cursor: pointer;
}
.settings-close:hover { background: rgba(255,255,255,0.09); color: var(--text); }
.settings-close svg { width: 16px; height: 16px; stroke: currentColor; stroke-width: 2.3; }

/* Base body box; the actual layout is the sidebar flex further down
   (".settings-body { display:flex !important }"). The old named-grid layout
   that used to live here was dead code and has been removed. */
.settings-body {
  min-height: 0;
  overflow: hidden;
  padding: 10px;
}

.settings-preview {
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 14px;
  overflow: hidden;
  position: relative;
  background: var(--bg);
}
.settings-preview::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(80% 120% at 18% 8%, rgba(var(--accent-rgb),0.28), transparent 48%),
    linear-gradient(135deg, rgba(255,255,255,0.05), transparent 52%);
}
.settings-preview::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,var(--bg-dim));
}
/* Compact full-width strip: kicker + title on the left, the accent bar filling
   the rest. Replaces the old tall card that left a big empty area beside it. */
.settings-preview-card {
  position: relative;
  z-index: 1;
  margin: 10px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 15px;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 12px;
  background: var(--panel);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04);
}
.settings-preview-kicker {
  flex: 0 0 auto;
  color: var(--green);
  font-size: 10.5px;
  font-weight: 950;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.settings-preview-title {
  flex: 0 0 auto;
  color: var(--text);
  font-size: 17px;
  font-weight: 950;
}
.settings-preview-bar {
  flex: 1 1 auto;
  min-width: 60px;
  height: 5px;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
  overflow: hidden;
}
.settings-preview-bar span {
  display: block;
  width: 68%;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--green), rgba(var(--accent-rgb),0.58));
}

.settings-group {
  min-height: max-content;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px;
  background: rgba(255,255,255,0.035);
  overflow: hidden;
}
.settings-group-head {
  padding: 10px 16px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  color: var(--text);
  font-size: 13.5px;
  font-weight: 900;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.settings-grid {
  padding: 12px 16px 14px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0,1fr));
  gap: 8px;
}
.settings-row {
  min-width: 0;
  display: grid;
  gap: 7px;
}
.settings-row.full { grid-column: 1 / -1; }
.settings-label-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: var(--text);
  font-size: 12.5px;
  font-weight: 850;
}
.settings-hint,
.settings-value,
.settings-note {
  color: var(--muted-text);
  font-size: 11px;
  font-weight: 750;
}

.settings-note {
  display: block;
  margin-top: -3px;
}
/* "This colour is hidden by an active background" — reads as a reason, not a hint. */
.settings-bg-covered-note { color: var(--color-warn); margin-top: 2px; }
.settings-bg-covered-note[hidden] { display: none; }

/* ── Incoming calls: which apps may ring ────────────────────────────────────
   A row of on/off chips rather than a stack of toggle rows: there are seven of
   them plus anything the user added, they are a single question ("may this app
   ring?"), and seven full-width rows would push the rest of the Notifiche
   section off a 720px-tall panel. */
.settings-calls-apps-row { flex-direction: column; align-items: stretch; gap: 9px; }
.settings-calls-apps-row[hidden] { display: none; }
.settings-calls-apps { display: flex; flex-wrap: wrap; gap: 7px; }
.settings-chip {
  display: inline-flex; align-items: center;
  min-height: 34px; padding: 0 13px;
  border: 1px solid var(--panel-border);
  border-radius: 999px;
  background: var(--control-bg);
  color: var(--muted-text);
  font: inherit; font-size: 12px; font-weight: 750;
  cursor: pointer;
  transition: background 0.14s ease, color 0.14s ease, border-color 0.14s ease;
}
.settings-chip:hover:not(:disabled) { background: var(--hover-bg); color: var(--text); }
.settings-chip.is-on {
  background: rgba(var(--accent-rgb), 0.15);
  border-color: rgba(var(--accent-rgb), 0.36);
  color: var(--accent);
}
.settings-chip:disabled { opacity: 0.45; cursor: default; }
/* 34px is comfortable with a mouse and under the touch floor on a phone, where
   these chips are the only thing in the panel you tap repeatedly. */
@media (max-width: 560px) {
  .settings-chip { min-height: 44px; padding: 0 15px; font-size: 12.5px; }
  .settings-calls-apps { gap: 8px; }
}
/* The "why is there no Answer button on this machine" line. It is a reason, not
   a warning: the feature still rings and can still open the app. */
.settings-calls-cap { color: var(--color-warn); }
.settings-calls-cap[hidden] { display: none; }

/* ── Body inset for sections that DON'T use .settings-grid ──────────────
   Only .settings-grid (and a few other bodies) carry the 16px card inset, so
   sections that drop rows/toggles straight into the group had their controls
   touching the card border. Inset those bodies too — horizontal only, so the
   existing vertical rhythm of each section is left exactly as it was. Plain
   content wrappers get padding; bordered/standalone elements (toggle pills,
   segmented controls, buttons) get margin so the whole pill is pulled in.
   Scoped to DIRECT children of the group so the same classes used as items
   inside .settings-grid / .settings-toggle-grid are never double-inset. */
.settings-group > .settings-row,
.settings-group > .settings-backup-row,
.settings-group > .settings-ambient-row,
.settings-group > .settings-ambient-scenes,
.settings-group > .slideshow-assets,
.settings-group > .settings-vitals-items,
.settings-group > .settings-vitals-row,
.settings-group > .settings-hint,
.settings-group > .settings-note,
#topbar-personalize {
  padding-left: 16px;
  padding-right: 16px;
}
.settings-group > .settings-toggle-row,
.settings-group > .settings-segmented,
.settings-group > .settings-btn {
  margin-left: 16px;
  margin-right: 16px;
}
/* A link that belongs to the toggle above it but must not live INSIDE its
   <label>: several browsers toggle the checkbox when a nested link is clicked,
   so reading what a setting sends would switch it on. Pulled up tight against
   the row so it still reads as part of it. */
.settings-group > .settings-sublink {
  margin: -6px 16px 10px;
  padding-left: 2px;
}
.settings-sublink a {
  color: rgb(var(--accent-rgb));
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* Integration sub-panels render their card into a bare mount div with no inset
   (Smart Home, Cameras/UniFi, Spotify, Twitch). The Illuminazione and Controllo
   remoto hubs already pad themselves, so they are deliberately left out. */
#settings-smarthome-hub,
#settings-unifi-hub,
#settings-spotify-hub,
#settings-streaming-hub {
  padding: 12px 16px 14px;
}

/* Dynamic Island package contributions. Rows are deliberately generated from
   the installed catalog, so uninstalling an extension removes its switch. */
.island-source-list {
  display: grid;
  gap: 7px;
  margin: 12px 16px;
}
.island-source-row {
  min-height: 48px;
  padding: 9px 11px;
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 11px;
  background: rgba(255,255,255,0.035);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  cursor: pointer;
}
.island-source-copy {
  min-width: 0;
  display: grid;
  gap: 3px;
}
.island-source-copy strong {
  overflow: hidden;
  color: var(--text);
  font-size: 12.5px;
  font-weight: 850;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.island-source-capabilities,
.island-source-empty {
  color: var(--muted-text);
  font-size: 10.5px;
  font-weight: 700;
}
.island-source-empty {
  padding: 14px 4px;
  text-align: center;
}

/* ── Swatch preview (non-interactive) + hex combo ───────── */
.settings-color-wrap {
  display: grid;
  grid-template-columns: 34px minmax(0,1fr);
  gap: 7px;
  align-items: center;
}
/* Optional (auto-able) colours get a third column for the "Auto" reset button. */
.settings-color-wrap:has(.settings-color-clear) {
  grid-template-columns: 34px minmax(0,1fr) auto;
}
.settings-color-clear {
  height: 34px;
  padding: 0 11px;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 10px;
  background: rgba(255,255,255,0.04);
  color: var(--muted-text);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.settings-color-clear:hover { background: rgba(255,255,255,0.09); color: var(--text); }
.settings-color-preview {
  width: 34px;
  height: 34px;
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 9px;
  flex-shrink: 0;
  cursor: pointer; /* tap opens the in-app ColorPicker (openSettingsColorPicker) */
}
.settings-color-preview:hover {
  border-color: rgba(var(--accent-rgb), 0.5);
}
.settings-hex-input {
  width: 100%;
  height: 34px;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  background: rgba(0,0,0,0.26);
  color: var(--text);
  font-size: 13.5px;
  font-weight: 900;
  letter-spacing: 0.5px;
  padding: 0 11px;
  text-transform: uppercase;
  -webkit-user-select: text;
  user-select: text;
}
.settings-hex-input:focus {
  outline: none;
  border-color: rgba(var(--accent-rgb),0.48);
  background: rgba(0,0,0,0.38);
}
.settings-hex-input.invalid { border-color: rgba(var(--danger-rgb),0.6); }

.settings-text-input {
  width: 100%;
  height: 34px;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  background: rgba(0,0,0,0.26);
  color: var(--text);
  font-size: 13px;
  font-weight: 850;
  padding: 0 11px;
  -webkit-user-select: text;
  user-select: text;
}
.settings-text-input:focus {
  outline: none;
  border-color: rgba(var(--accent-rgb),0.48);
  background: rgba(0,0,0,0.38);
}
.settings-text-input:disabled,
.settings-text-input.disabled {
  cursor: not-allowed;
  color: var(--muted-text);
  opacity: 0.64;
}
/* The AI model pickers are <select class="settings-text-input"> upgraded to the
   shared custom dropdown; the native element is hidden and the wrapper is
   inserted right before it, so the wrapper has to carry the full-width sizing.
   Matched by that adjacency so the other custom selects in Settings, which are
   deliberately auto-width, are left alone. */
.cs-wrap:has(+ select.settings-text-input) { width: 100%; }
.cs-wrap:has(+ select.settings-text-input) .cs-trigger {
  width: 100%; height: 34px; font-size: 13px;
}

/* Code-defined animated background editor: a monospace code box + template row. */
.settings-code-field {
  width: 100%;
  box-sizing: border-box;
  min-height: 150px;
  resize: vertical;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  background: rgba(0,0,0,0.32);
  color: var(--text);
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
  font-size: 12px;
  line-height: 1.5;
  padding: 10px 11px;
  tab-size: 2;
  -webkit-user-select: text;
  user-select: text;
  white-space: pre;
  overflow: auto;
}
.settings-code-field:focus {
  outline: none;
  border-color: rgba(var(--accent-rgb),0.48);
  background: rgba(0,0,0,0.44);
}
/* Inline compile/runtime error surfaced from the sandboxed background frame, so a
   broken snippet reads as a real message instead of a silently-black backdrop. */
.settings-bgcode-error {
  margin: 6px 0 0;
  padding: 7px 10px;
  border-radius: 8px;
  font-size: 0.8rem;
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
  color: #ffd7d1;
  background: rgba(255, 86, 74, 0.12);
  border: 1px solid rgba(255, 86, 74, 0.34);
  white-space: pre-wrap;
  word-break: break-word;
}
.settings-bgcode-error[hidden] { display: none; }
/* Live character counter for the code editor — sits at the end of the label
   line, muted until you approach the cap (amber) or exceed it (red), so hitting
   the limit is visible instead of a silent truncation. */
.settings-bgcode-count {
  flex: 0 0 auto;
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
  font-size: 11px;
  color: var(--muted-text);
  opacity: 0.7;
  font-variant-numeric: tabular-nums;
}
.settings-bgcode-count.is-near { color: var(--color-warn); opacity: 1; }
.settings-bgcode-count.is-over { color: var(--color-danger); opacity: 1; font-weight: 600; }
.settings-label-lead { min-width: 0; display: inline-flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
/* Ready-made background gallery: a responsive grid of tap-to-apply tiles so a
   non-coder never has to touch the editor. */
.settings-bgcode-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: 8px;
  margin-top: 6px;
}
.settings-bgtpl {
  appearance: none;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 10px;
  background: rgba(255,255,255,0.04);
  color: var(--text);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  padding: 12px 8px;
  cursor: pointer;
  transition: background .14s ease, border-color .14s ease, transform .1s ease;
}
.settings-bgtpl:hover { background: rgba(var(--accent-rgb),0.14); border-color: rgba(var(--accent-rgb),0.4); }
.settings-bgtpl:active { transform: scale(0.97); }
.settings-bgcode-share-row { display: flex; flex-wrap: wrap; gap: 8px; }
.settings-bgcode-share-row .settings-btn { flex: 1 1 auto; }
.settings-bgcode-ai-hint { margin: 2px 0 4px; }

/* Bundled background images: thumbnail chips with a remove control. Touch-sized
   remove target — the Xeneon Edge is a touchscreen. */
.settings-bgasset-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 6px 0 8px;
}
.settings-bgasset-list[hidden] { display: none; }
.settings-bgasset-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 6px 5px 5px;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 10px;
  background: rgba(255,255,255,0.04);
  max-width: 100%;
}
.settings-bgasset-thumb {
  width: 34px;
  height: 34px;
  border-radius: 7px;
  object-fit: cover;
  background: rgba(0,0,0,0.35);
  image-rendering: pixelated; /* pixel-art stays crisp in the tiny preview */
  flex: 0 0 auto;
}
.settings-bgasset-name {
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
  font-size: 11.5px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
}
.settings-bgasset-size {
  font-size: 11px;
  color: var(--muted-text);
  flex: 0 0 auto;
}
.settings-bgasset-del {
  appearance: none;
  border: none;
  border-radius: 8px;
  background: rgba(255,255,255,0.06);
  color: var(--muted-text);
  font-size: 15px;
  line-height: 1;
  width: 28px;
  height: 28px;
  cursor: pointer;
  flex: 0 0 auto;
  transition: background .14s ease, color .14s ease;
}
.settings-bgasset-del:hover { background: var(--danger-bg); color: var(--color-danger); }

/* Collapsible "how to write the code" help for the power-user path. */
.settings-code-help { margin-top: 4px; }
.settings-code-help > summary {
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted-text);
  padding: 4px 0;
  list-style: none;
}
.settings-code-help > summary::-webkit-details-marker { display: none; }
.settings-code-help > summary::before { content: "▸ "; color: rgba(var(--accent-rgb),0.8); }
.settings-code-help[open] > summary::before { content: "▾ "; }
.settings-code-help-body { font-size: 12px; line-height: 1.55; color: var(--muted-text); }
.settings-code-help-body p { margin: 6px 0; }
.settings-code-help-example {
  margin: 8px 0 2px;
  border-radius: 10px;
  background: rgba(0,0,0,0.32);
  border: 1px solid rgba(255,255,255,0.08);
  padding: 10px 11px;
  overflow-x: auto;
  font-family: ui-monospace, "SF Mono", "Cascadia Code", Consolas, monospace;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text);
}
.settings-code-help-example code { white-space: pre; }

.settings-segmented {
  display: grid;
  grid-template-columns: repeat(2, minmax(0,1fr));
  gap: 6px;
  padding: 4px;
  border: 1px solid rgba(255,255,255,0.075);
  border-radius: 12px;
  background: rgba(0,0,0,0.18);
}
.settings-segment-btn {
  min-width: 0;
  height: 30px;
  border: 1px solid transparent;
  border-radius: 9px;
  background: transparent;
  color: var(--muted-text);
  font-size: 12px;
  font-weight: 900;
  cursor: pointer;
}
.settings-segment-btn:hover {
  color: var(--text);
  background: rgba(255,255,255,0.055);
}
.settings-segment-btn.active {
  border-color: rgba(var(--accent-rgb),0.45);
  background: rgba(var(--accent-rgb),0.15);
  color: var(--text);
}

/* ── Minimal-island element editor (reorder + show/hide) ──────
   A compact list of the island's segments; drag the grip to reorder, tap the
   eye to show/hide. Only shown in Minimal mode (js/settings.js gates it). */
.island-edit-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}
.island-edit-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap; /* the options panel below drops onto its own line */
  gap: 10px;
  padding: 7px 10px;
  border: 1px solid var(--floating-ui-border);
  border-radius: 11px;
  background: rgba(255,255,255,0.03);
  touch-action: pan-y; /* vertical scroll still works off the grip */
}
.island-edit-row.dragging {
  border-color: rgba(var(--accent-rgb),0.5);
  background: rgba(var(--accent-rgb),0.08);
  box-shadow: var(--shadow-lg);
}
.island-edit-list.reordering .island-edit-row:not(.dragging) { transition: transform 0.16s ease; }

/* Per-segment options, revealed by the chevron. It lives INSIDE the row (on a
   wrapped line) rather than as a sibling, so the reorder drag — which measures
   whole `.island-edit-row` rects to pick an insertion point — keeps measuring
   the whole item whether the panel is open or closed. */
.island-edit-caret {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--muted-text);
  cursor: pointer;
}
.island-edit-caret:hover { background: rgba(255,255,255,0.07); color: var(--text); }
.island-edit-caret svg { width: 15px; height: 15px; transition: transform 0.18s ease; }
.island-edit-row.is-open .island-edit-caret svg { transform: rotate(90deg); }
.island-edit-sub {
  flex: 0 0 100%;
  margin: 2px 0 2px 36px;
  padding-top: 8px;
  border-top: 1px solid var(--floating-ui-border);
}
.island-edit-sub[hidden] { display: none; }
.island-edit-sub .settings-toggle-row { margin: 0; }

@media (prefers-reduced-motion: reduce) {
  .island-edit-caret svg { transition: none; }
}
.island-edit-handle {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  color: var(--dim-text);
  cursor: grab;
  touch-action: none; /* the grip owns the drag; the panel still scrolls */
}
.island-edit-handle:active { cursor: grabbing; }
.island-edit-handle svg { width: 16px; height: 16px; }
.island-edit-label {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 750;
  color: var(--text);
}
.island-edit-eye {
  display: grid;
  place-items: center;
  width: 34px;
  height: 30px;
  flex-shrink: 0;
  border: 1px solid var(--floating-ui-border);
  border-radius: 9px;
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.island-edit-eye svg { width: 17px; height: 17px; fill: currentColor; }
.island-edit-eye:hover { background: rgba(var(--accent-rgb),0.1); }
.island-edit-eye.is-hidden { color: var(--dim-text); }
/* A row that may not be hidden (Settings) keeps its eye, dimmed and inert, with
   the reason on the tooltip. Removing the control instead would read as a bug. */
.island-edit-eye.is-locked {
  color: var(--dim-text);
  opacity: 0.45;
  cursor: default;
}
.island-edit-eye.is-locked:hover { background: transparent; }

/* Left/right chooser on a chrome-button row. Compact on purpose: it sits
   between a label that may be long and the eye, and the Edge is a touchscreen,
   so the two targets stay finger-sized while the control stays narrow. */
.island-edit-side {
  display: flex;
  flex: 0 0 auto;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--floating-ui-border);
  border-radius: 9px;
  background: rgba(255,255,255,0.03);
}
.island-edit-side-btn {
  min-width: 42px;
  padding: 4px 7px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--dim-text);
  font: inherit;
  font-size: 11px;
  font-weight: 750;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.island-edit-side-btn:hover { color: var(--text); }
.island-edit-side-btn.active { background: rgba(var(--accent-rgb),0.16); color: var(--accent); }

/* ── Appearance (light / dark / auto) segmented control ──── */
.settings-appearance-seg { grid-template-columns: repeat(3, minmax(0,1fr)); }
.settings-appearance-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 36px;
}
.settings-appearance-btn svg { width: 15px; height: 15px; flex-shrink: 0; }

/* ── Dashboard style (Liquid Glass / Pixel Retro) segmented control ── */
.settings-style-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 36px;
}
.settings-style-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
/* The shared display rules outrank the UA [hidden] style — restate it so
   `el.hidden = true` really hides rows/grids anywhere in Settings. */
.settings-toggle-row[hidden],
.settings-row[hidden],
.settings-grid[hidden] { display: none; }
/* A whole group that doesn't apply right now (e.g. Tema while Pixel Retro
   forces the dark CRT look) is dimmed and inert rather than lying active. */
.settings-group.is-disabled { opacity: 0.42; pointer-events: none; }

/* ── Language dropdown (inside presets header) ───────────── */
/* The list outgrew a row of toggle chips; it's now a compact custom-select
   dropdown (custom-select.js wraps the <select> in a .cs-wrap). */
.settings-lang-inline {
  display: inline-flex;
  justify-content: flex-end;
  min-width: 0;
}
.settings-lang-inline .cs-wrap { min-width: 128px; }
.settings-lang-inline .cs-trigger { height: 26px; }

/* ── Lock screen widget toggles ──────────────────────────── */
.settings-toggle-grid {
  padding: 10px 16px 12px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0,1fr));
  gap: 8px;
}
.settings-toggle-row {
  min-width: 0;
  min-height: 36px;
  display: flex;
  align-items: center;
  gap: 9px;
  border: 1px solid rgba(255,255,255,0.075);
  border-radius: 11px;
  background: rgba(0,0,0,0.16);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 850;
  padding: 0 10px;
  cursor: pointer;
}
.settings-toggle-row:hover { border-color: rgba(var(--accent-rgb),0.28); background: rgba(var(--accent-rgb),0.055); }
/* A sub-toggle that a master switch has turned off (e.g. pop-ups when notifications
   are disabled): dimmed and non-interactive, but still readable. */
.settings-toggle-row.is-disabled { opacity: 0.42; pointer-events: none; }
.settings-check {
  width: 16px;
  height: 16px;
  accent-color: var(--green);
  flex-shrink: 0;
}

/* ── Advanced AI features (Funzioni AI) ───────────────────── */
.settings-aifeat-group .settings-toggle-row { padding: 8px 10px; min-height: 44px; }
.aifeat-master-row { border-color: rgba(var(--accent-rgb),0.35); }
.aifeat-row-disabled { opacity: 0.45; pointer-events: none; }
.aifeat-cost-note {
  margin: 8px 12px 0;
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid rgba(245,158,11,0.3);
  background: rgba(245,158,11,0.08);
  font-size: 11.5px;
  line-height: 1.45;
}
.aifeat-hub-note { margin: 4px 12px 12px; font-size: 11.5px; }
.aifeat-hub-note a { color: var(--accent); font-weight: 800; text-decoration: none; }
.aifeat-hub-note a:hover { text-decoration: underline; }
.settings-range {
  width: 100%;
  height: 34px;
  cursor: pointer;
}

/* ── AI mic-sensitivity slider ───────────────────────────── */
.settings-slider-row {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.settings-slider-control {
  display: flex;
  align-items: center;
  gap: 10px;
}
.settings-slider {
  flex: 1;
  -webkit-appearance: none;
  appearance: none;
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(255,255,255,.08), rgba(var(--accent-rgb), .55));
  outline: none;
  cursor: pointer;
}
.settings-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid rgba(255,255,255,.92);
  box-shadow: 0 0 10px rgba(var(--accent-rgb), .55);
  cursor: pointer;
}
.settings-slider::-moz-range-thumb {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid rgba(255,255,255,.92);
  box-shadow: 0 0 10px rgba(var(--accent-rgb), .55);
  cursor: pointer;
}
.settings-slider-end {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgba(255,255,255,.52);
  min-width: 36px;
  text-align: center;
}
.settings-slider-value {
  font-size: 12px;
  font-weight: 700;
  color: rgba(var(--accent-rgb), .95);
  min-width: 30px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ── Xenon AI info block ─────────────────────────────────── */
.settings-ai-info {
  padding: 10px 13px 12px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  background: rgba(var(--accent-rgb), 0.035);
  /* Two columns: left = what it does, right = setup steps */
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: 14px 20px;
  align-items: start;
}

/* Left column wrapper */
.settings-ai-col--main {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}

/* Right column wrapper */
.settings-ai-col--setup {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}

/* Full-width bottom row (wake + privacy) */
.settings-ai-col--footer {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.settings-ai-desc-text {
  margin: 0;
  font-size: 11.5px;
  color: rgba(255,255,255,0.52);
  line-height: 1.55;
}

.settings-ai-caps-label {
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .055em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.36);
}

.settings-ai-caps {
  margin: 0;
  font-size: 11px;
  color: rgba(255,255,255,0.55);
  line-height: 1.55;
}

.settings-ai-wake {
  margin: 0;
  font-size: 11px;
  color: rgba(255,255,255,0.48);
  line-height: 1.45;
}

.settings-ai-privacy {
  margin: 0;
  font-size: 10.5px;
  color: rgba(255,255,255,0.30);
  line-height: 1.4;
}

.settings-ai-steps {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: ai-step;
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.settings-ai-steps li {
  counter-increment: ai-step;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 11.5px;
  color: rgba(255,255,255,0.42);
  line-height: 1.45;
}

.settings-ai-steps li a {
  color: var(--accent);
  text-decoration: none;
}
.settings-ai-steps li a:hover { text-decoration: underline; }

.settings-ai-steps li::before {
  content: counter(ai-step);
  flex-shrink: 0;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: rgba(var(--accent-rgb), 0.20);
  color: var(--accent);
  font-size: 9.5px;
  font-weight: 900;
  display: grid;
  place-items: center;
  margin-top: 1px;
}

.settings-subgroup {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid rgba(255,255,255,0.06);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.settings-subgroup-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.38);
}

@media (max-width: 680px) {
  .settings-ai-info {
    grid-template-columns: 1fr;
  }
  .settings-ai-col--footer {
    grid-column: 1;
  }
}

.theme-presets {
  padding: 10px 12px 12px;
  display: grid;
  grid-template-columns: repeat(5, minmax(0,1fr));
  gap: 8px;
}
.preset-btn {
  min-width: 0;
  min-height: 54px;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 12px;
  background: rgba(255,255,255,0.035);
  color: var(--text);
  cursor: pointer;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 6px;
  padding: 8px 6px;
}
.preset-btn:hover { border-color: rgba(var(--accent-rgb),0.34); background: rgba(255,255,255,0.06); }
.preset-btn.active { border-color: rgba(var(--accent-rgb),0.68); box-shadow: 0 0 0 1px rgba(var(--accent-rgb),0.14) inset; }
.preset-swatch {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--preset-accent);
  box-shadow: 0 0 18px var(--preset-glow);
}
.preset-name {
  max-width: 100%;
  font-size: 11px;
  font-weight: 850;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Temi gallery (built-in skins + imported themes) ─────────────────── */
.theme-gallery {
  padding: 10px 12px 4px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.theme-card-wrap { position: relative; min-width: 0; }
.theme-card {
  width: 100%;
  border: 1px solid rgba(255,255,255,0.09);
  border-radius: 14px;
  background: rgba(255,255,255,0.035);
  color: var(--text);
  cursor: pointer;
  display: grid;
  gap: 8px;
  padding: 8px 8px 9px;
  text-align: left;
  transition: border-color .12s ease, background .12s ease;
}
.theme-card:hover { border-color: rgba(var(--accent-rgb),0.34); background: rgba(255,255,255,0.06); }
.theme-card.active { border-color: rgba(var(--accent-rgb),0.7); box-shadow: 0 0 0 1px rgba(var(--accent-rgb),0.16) inset; }
/* Mini dashboard mock painted from the theme's own palette (CSS vars set inline). */
.theme-card-preview {
  position: relative;
  display: block;
  height: 46px;
  border-radius: 10px;
  background: var(--tc-bg);
  border: 1px solid rgba(255,255,255,0.09);
  overflow: hidden;
}
.theme-card-preview::before {
  content: '';
  position: absolute; left: 9px; top: 10px;
  width: 42%; height: 7px; border-radius: 4px;
  background: var(--tc-accent);
  box-shadow: 0 0 14px color-mix(in srgb, var(--tc-accent) 55%, transparent);
}
.theme-card-preview::after {
  content: '';
  position: absolute; left: 9px; top: 25px;
  width: 66%; height: 5px; border-radius: 3px;
  background: var(--tc-text); opacity: .5;
}
.theme-card-dot {
  position: absolute; right: 9px; bottom: 9px;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--tc-accent);
}
.theme-card-foot { display: flex; align-items: center; gap: 6px; min-width: 0; }
.theme-card-name {
  min-width: 0; flex: 1 1 auto;
  font-size: 11.5px; font-weight: 800;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.theme-card-badge {
  flex: 0 0 auto;
  font-size: 8.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  padding: 1px 6px; border-radius: 999px;
  background: rgba(var(--accent-rgb),0.16); color: var(--accent);
}
/* Always visible (not hover-reveal): the Xeneon Edge is a touchscreen with no
   hover, so an imported theme must stay removable by tap. Subtle until touched. */
.theme-card-remove {
  position: absolute; top: -6px; right: -6px;
  width: 22px; height: 22px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.16);
  background: var(--panel, #1a1c1b); color: var(--text);
  font-size: 11px; line-height: 1; cursor: pointer;
  display: grid; place-items: center;
  opacity: .55; transition: opacity .12s ease, border-color .12s ease, color .12s ease;
}
.theme-card-wrap:hover .theme-card-remove,
.theme-card-remove:focus-visible { opacity: 1; }
.theme-card-remove:hover { opacity: 1; border-color: rgba(var(--danger-rgb),0.6); color: var(--color-danger); }
/* Pixel Retro card reads as a CRT: sharp corners on the mock, no soft glow. */
.theme-card--retro .theme-card-preview,
.theme-card--retro .theme-card-preview::before,
.theme-card--retro .theme-card-preview::after,
.theme-card--retro .theme-card-dot { border-radius: 0; }
.theme-card--retro .theme-card-preview::before { box-shadow: none; }
.theme-gallery-actions {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 8px 12px 12px;
}

/* Subtle divider that groups the fine-tuning cards under one heading. */
.settings-section-divider {
  display: flex; align-items: baseline; gap: 10px;
  margin: 6px 2px 2px;
  padding-top: 8px;
  border-top: 1px solid rgba(255,255,255,0.07);
  font-size: 12px; font-weight: 850; letter-spacing: .01em;
}
.settings-section-divider .settings-hint { font-weight: 600; }

@media (max-width: 560px) {
  .theme-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .theme-card-remove { opacity: 1; }
}

.settings-upload-row {
  display: grid;
  grid-template-columns: minmax(0,1fr) auto;
  gap: 9px;
  align-items: center;
}
.settings-upload {
  min-height: 50px;
  border: 1px dashed rgba(var(--accent-rgb),0.36);
  border-radius: 12px;
  background: rgba(var(--accent-rgb),0.055);
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  cursor: pointer;
  min-width: 0;
}
.settings-upload:hover { background: rgba(var(--accent-rgb),0.09); }
.settings-upload input { display: none; }
.settings-upload svg { width: 18px; height: 18px; fill: var(--green); flex-shrink: 0; }
.settings-upload-copy { min-width: 0; }
.settings-upload-title {
  color: var(--text);
  font-size: 13.5px;
  font-weight: 900;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.settings-upload-sub {
  margin-top: 2px;
  color: var(--muted-text);
  font-size: 11px;
  font-weight: 750;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.settings-btn {
  min-height: 36px;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  background: rgba(255,255,255,0.05);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 900;
  padding: 0 12px;
  cursor: pointer;
  white-space: nowrap;
}
.settings-btn:hover { background: rgba(255,255,255,0.09); }
.settings-btn.primary {
  border-color: rgba(var(--accent-rgb),0.36);
  background: rgba(var(--accent-rgb),0.16);
  color: #f6fff9;
}
.settings-btn.danger { color: var(--color-danger); }
.settings-btn:disabled { opacity: 0.55; cursor: default; }

/* Microphone self-test: button + colour-coded result line */
.settings-mictest-control {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
}
.settings-mictest-result {
  margin: 0;
  min-height: 16px;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--muted-text);
}
.settings-mictest-result.is-rec  { color: var(--text); }
.settings-mictest-result.is-ok   { color: var(--color-success); }
.settings-mictest-result.is-warn { color: var(--color-warn); }

/* Game-mode: PresentMon install row, revealed only when the tool is missing */
.settings-gamemode-install {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
.settings-gamemode-install[hidden] { display: none; }
.settings-gamemode-install .settings-btn {
  border-color: rgba(var(--accent-rgb), 0.36);
  background: rgba(var(--accent-rgb), 0.16);
  color: #f6fff9;
}

.settings-status {
  min-width: 0;
  flex: 1 1 auto;
  min-height: 16px;
  color: var(--muted-text);
  font-size: 11px;
  font-weight: 750;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.settings-status.error { color: var(--color-danger); }
.settings-status.ok { color: var(--green); }

.settings-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-top: 1px solid rgba(255,255,255,0.07);
}
.settings-foot-note {
  min-width: 0;
  color: var(--muted-text);
  font-size: 11px;
  font-weight: 750;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (min-width: 900px) {
  .theme-presets {
    grid-template-columns: repeat(2, minmax(0,1fr));
  }

  .preset-btn {
    min-height: 42px;
    grid-template-columns: auto minmax(0,1fr);
    align-content: center;
    align-items: center;
    justify-items: start;
    text-align: left;
    padding: 7px 8px;
  }

  .preset-swatch {
    width: 18px;
    height: 18px;
  }
}

@media (min-width: 900px) and (max-height: 620px) {
  .settings-overlay { padding: 8px; }
  .settings-panel {
    /* % of the (correctly sized) fixed overlay — vw/vh bypass the Edge zoom. */
    width: 100%;
    max-width: 1500px;
    height: 100%;
    max-height: 100%;
    border-radius: 14px;
  }
  .settings-head { padding: 9px 14px 8px; }
  .settings-title { font-size: 15.5px; }
  .settings-subtitle { font-size: 11px; margin-top: 1px; }
  .settings-close { width: 28px; height: 28px; }
  .settings-store-pill { padding: 7px 10px; }
  .settings-store-pill span { display: none; }
  .settings-body { padding: 10px; gap: 9px; }
  .settings-preview-card { margin: 8px; padding: 9px 13px; gap: 12px; }
  .settings-preview-title { font-size: 16px; }
  .settings-preview-kicker { font-size: 10px; }
  .settings-group { border-radius: 12px; }
  /* Edge is short, so keep vertical padding tight but give real horizontal
     breathing room — content was touching the card edges. */
  .settings-group-head { padding: 9px 16px; font-size: 12.5px; }
  .settings-grid { padding: 10px 16px 12px; gap: 8px; }
  .settings-label-line { font-size: 11px; }
  .settings-hint, .settings-value { font-size: 10px; }
  .settings-color { height: 32px; border-radius: 8px; }
  .settings-range { height: 28px; }
  .theme-presets { padding: 9px 10px 10px; gap: 7px; }
  .preset-btn { min-height: 36px; border-radius: 9px; gap: 6px; }
  .settings-upload { min-height: 42px; padding: 8px 10px; border-radius: 10px; }
  .settings-upload-title { font-size: 12.5px; }
  .settings-upload-sub { font-size: 10px; }
  .settings-btn { min-height: 32px; border-radius: 9px; font-size: 11px; }
  .settings-foot { padding: 8px 12px; }
}

@media (max-width: 640px) {
  .settings-overlay { padding: 10px; place-items: stretch; }
  .settings-panel { width: 100%; max-height: calc(100vh - 20px); border-radius: 14px; }
  .settings-grid { grid-template-columns: 1fr; }
  .theme-presets { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .settings-upload-row { grid-template-columns: 1fr; }
  .settings-foot { align-items: stretch; flex-direction: column; }
  .settings-status { text-align: left; }
  .settings-foot-note { white-space: normal; }
}

/* ── Settings sidebar (category nav) — overrides the legacy 2-column grid ── */
/* overflow:hidden keeps the scroll on .settings-content (the min-width:900
   block above leaks overflow-y:auto onto the body, which split the scroll
   across two containers and could strand the inner content). */
.settings-body { display: flex !important; gap: 12px; align-items: stretch; overflow: hidden; }
.settings-nav {
  flex: 0 0 auto;
  width: 202px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.settings-nav-scroll {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow-y: auto;
  overflow-x: hidden;
}
.settings-nav-footer {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid rgba(255,255,255,0.07);
}
.settings-nav-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  /* Roomier finger target on the Xeneon Edge touchscreen: taller rows and more
     side padding so each category is easy to tap. */
  padding: 12px 14px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--muted-text);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.settings-nav-btn svg { width: 18px; height: 18px; flex: 0 0 auto; }
/* A category the platform doesn't have is hidden by settingsHideWindowsOnly()
   setting `hidden` on its button — which the UA's `[hidden] { display: none }`
   cannot deliver here, because the author `display: flex` above outranks it.
   Without this line every Windows-only category still listed itself on macOS
   and Linux and opened an empty pane. */
.settings-nav-btn[hidden] { display: none; }
.settings-nav-btn:hover { background: rgba(255,255,255,0.05); color: var(--text); }
.settings-nav-btn.active { background: rgba(var(--accent-rgb),0.14); color: var(--accent); }
/* Bit's own category — his pixel face in brand green so the mascot reads at a
   glance among the monochrome line icons. It keeps its own colours in every
   state (it's the mascot, not a themed glyph); it just lights up on hover/active
   and tints the row green so the resting sidebar stays calm. */
.bit-nav-sprite { transition: filter .15s ease; }
.settings-nav-btn-bit:hover .bit-nav-sprite,
.settings-nav-btn-bit.active .bit-nav-sprite { filter: drop-shadow(0 0 3px rgba(110,231,135,0.6)); }
.settings-nav-btn-bit.active { background: rgba(110,231,135,0.14); color: #6ee787; }
/* Sidebar section labels: quiet all-caps dividers between category clusters. */
.settings-nav-label {
  padding: 10px 12px 3px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted-text);
  opacity: 0.6;
  white-space: nowrap;
  user-select: none;
}
/* "Sostieni Xenon" — the one deliberately loud button in the sidebar. */
.settings-nav-btn-support {
  margin-top: 8px;
  color: #ff4d8d;
  background: rgba(255,77,141,0.10);
  border: 1px solid rgba(255,77,141,0.24);
}
.settings-nav-btn-support:hover { background: rgba(255,77,141,0.18); color: #ff6ba0; }
.settings-nav-btn-support.active { background: rgba(255,77,141,0.2); color: #ff6ba0; }
/* "Try the native app" promo — shown only on the browser/iCUE surfaces (never
   inside the native app) when the native kiosk isn't installed. A compact pill
   in the settings header opens the details as a dropdown. Both are revealed and
   wired by js/native-bridge.js. */
.native-promo-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 10px;
  border-radius: 999px;
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  background: rgba(var(--accent-rgb), 0.10);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s ease, border-color .15s ease;
}
.native-promo-chip[hidden] { display: none; }
.native-promo-chip:hover { background: rgba(var(--accent-rgb), 0.16); border-color: rgba(var(--accent-rgb), 0.5); }
.native-promo-chip svg { width: 15px; height: 15px; flex: 0 0 auto; color: rgb(var(--accent-rgb)); }
.native-promo-chip .native-promo-beta { margin-left: 2px; }

.native-promo {
  position: absolute;
  top: calc(100% + 6px);
  right: 12px;
  z-index: 40;
  width: min(320px, calc(100vw - 40px));
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  border-radius: 14px;
  border: 1px solid rgba(var(--accent-rgb), 0.35);
  background:
    radial-gradient(120% 120% at 100% 0%, rgba(var(--accent-rgb),0.14), transparent 55%),
    rgba(16,22,21,0.98);
  box-shadow: 0 18px 60px rgba(0,0,0,0.6), 0 0 40px rgba(var(--accent-rgb),0.12);
}
.native-promo[hidden] { display: none; }
/* Tight header: drop the pill's text, keep the icon + Beta badge. */
@media (max-width: 560px) {
  .native-promo-chip .native-promo-chip-label { display: none; }
}
.native-promo-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
}
.native-promo-head svg { width: 16px; height: 16px; flex: 0 0 auto; color: rgb(var(--accent-rgb)); }
.native-promo-beta {
  margin-left: auto;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: rgb(var(--accent-rgb));
  background: rgba(var(--accent-rgb), 0.16);
}
.native-promo-desc { margin: 0; font-size: 12px; color: var(--text); opacity: .92; }
.native-promo-benefits {
  margin: 0;
  padding-left: 16px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 11.5px;
  color: var(--muted-text);
}
.native-promo-benefits li { line-height: 1.35; }
.native-promo-warn { margin: 0; font-size: 11px; color: var(--muted-text); opacity: .85; }
.native-promo-install {
  margin-top: 2px;
  padding: 9px 12px;
  border: none;
  border-radius: 10px;
  font-size: 12.5px;
  font-weight: 700;
  color: #fff;
  background: rgb(var(--accent-rgb));
  cursor: pointer;
  transition: filter .15s ease, opacity .15s ease;
}
.native-promo-install:hover { filter: brightness(1.08); }
.native-promo-install:disabled { opacity: .6; cursor: default; }
.native-promo-status { font-size: 11px; color: var(--muted-text); }
.native-promo-status:empty { display: none; }

.settings-nav-support {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.settings-nav-support-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  border-radius: 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted-text);
  text-decoration: none;
  opacity: 0.85;
  transition: opacity .15s ease, background .15s ease, color .15s ease;
}
.settings-nav-support-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.settings-nav-support-btn svg { width: 15px; height: 15px; flex: 0 0 auto; }
.settings-nav-support-btn.is-donate svg { color: #ff4d8d; }
.settings-nav-support-btn.is-discord svg { color: #5865F2; }
.settings-nav-support-btn:hover {
  opacity: 1;
  background: rgba(255,255,255,0.06);
  color: var(--text);
}
.settings-nav-support-btn.is-donate:hover svg { color: #ff2d77; }
.settings-nav-support-btn.is-discord:hover svg { color: #7983f5; }

/* Featured actions (Support + Community Discord): tinted, full-contrast pills so
   they stand out from the quieter "Report a bug" link below them. Text stays
   var(--text) so it reads in both light and dark; the icon carries the accent. */
.settings-nav-support-btn.is-featured {
  opacity: 1;
  color: var(--text);
  border: 1px solid transparent;
  font-size: 12.5px;
}
.settings-nav-support-btn.is-featured.is-donate {
  background: rgba(255,77,141,0.12);
  border-color: rgba(255,77,141,0.26);
}
.settings-nav-support-btn.is-featured.is-donate:hover { background: rgba(255,77,141,0.2); }
.settings-nav-support-btn.is-featured.is-discord {
  background: rgba(88,101,242,0.14);
  border-color: rgba(88,101,242,0.28);
}
.settings-nav-support-btn.is-featured.is-discord:hover { background: rgba(88,101,242,0.24); }
/* "macOS / Linux is beta", above the version stamp. Amber and not the accent:
   the accent means a feature is on, and a caveat that borrows it stops reading
   as a caveat. Built only where it is true (see renderPlatformBeta). */
.settings-platform-beta {
  margin: 0 8px 8px;
  padding: 9px 11px;
  border-radius: 10px;
  background: rgba(255, 196, 77, 0.09);
  border: 1px solid rgba(255, 196, 77, 0.22);
}
.settings-platform-beta[hidden] { display: none; }
.settings-platform-beta-head { display: flex; align-items: center; gap: 7px; }
.settings-platform-beta-chip {
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #ffc44d;
  background: rgba(255, 196, 77, 0.16);
}
.settings-platform-beta-os { font-size: 11.5px; font-weight: 700; color: var(--text); }
.settings-platform-beta-note {
  margin: 5px 0 0;
  font-size: 10.5px;
  line-height: 1.45;
  color: var(--muted-text);
}
.settings-platform-beta-link {
  display: inline-block;
  margin-top: 5px;
  font-size: 10.5px;
  font-weight: 700;
  color: #ffc44d;
  text-decoration: none;
}
.settings-platform-beta-link:hover { text-decoration: underline; }

.settings-nav-version {
  margin-top: 0;
  padding: 4px 12px 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--muted-text);
  opacity: 0.7;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 7px;
}
/* Brand mark before the version text: the glow-on-black logo, with `screen` blend
   so its black backdrop drops out onto the dark sidebar (no visible box). Kept small
   and quiet to read as an "about" stamp, not a banner. */
.settings-nav-version::before {
  content: "";
  flex: 0 0 auto;
  width: 20px;
  height: 15px;
  background: url("/public/images/logo/logo-mark.png") center / contain no-repeat;
  mix-blend-mode: screen;
}
.settings-nav-version:empty { display: none; }
/* "Update available" pill: appears above the version only when a newer GitHub
   release exists. A real link to the release page — accent-tinted but quiet. */
.settings-update-pill {
  display: block;
  margin: 0 8px 6px;
  padding: 6px 10px;
  border-radius: 9px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: rgb(var(--accent-rgb));
  background: rgba(var(--accent-rgb), 0.12);
  border: 1px solid rgba(var(--accent-rgb), 0.3);
}
.settings-update-pill:hover { background: rgba(var(--accent-rgb), 0.2); }
/* Backup export/import button pair. */
.settings-backup-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.settings-content {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  /* Touch: keep vertical panning on this container (the Xeneon Edge is a
     touchscreen) and don't chain the scroll to the page behind. A thin,
     visible thumb makes it obvious the category scrolls. */
  touch-action: pan-y;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  display: grid;
  grid-template-columns: 1fr;
  /* max-content (not auto): auto rows get squeezed to fit the container
     because .settings-group has overflow:hidden, causing groups to overlap. */
  grid-auto-rows: max-content;
  gap: 10px;
  align-content: start;
}
/* General: two even columns via grid; scrolls vertically if taller than the
   panel (never horizontally). */
#settings-content[data-cat="general"] {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-content: start;
  align-items: start;
}
/* Appearance: two even columns. Wide items (live preview, theme gallery, mode
   switch, the "Personalizza" divider) span the full width via .settings-span-all;
   the detail cards sit in two columns, ordered so the two tall cards (Colori and
   Superficie) pair up and the short ones follow, keeping ragged gaps small. */
#settings-content[data-cat="appearance"] {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-content: start;
  align-items: start;
}
#settings-content[data-cat="appearance"] > .settings-span-all { grid-column: 1 / -1; }
#settings-content[data-cat="general"] [data-settings-cat] { grid-area: auto !important; }
#settings-content [data-settings-cat][hidden] { display: none !important; }

/* Visible scroll thumb so a taller category (e.g. Performance) reads as
   scrollable instead of looking clipped. */
.settings-content::-webkit-scrollbar,
.settings-nav-scroll::-webkit-scrollbar { width: 9px; }
.settings-content::-webkit-scrollbar-thumb,
.settings-nav-scroll::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.settings-content::-webkit-scrollbar-thumb:hover,
.settings-nav-scroll::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.30); background-clip: padding-box; }
:root[data-appearance="light"] .settings-content::-webkit-scrollbar-thumb,
:root[data-appearance="light"] .settings-nav-scroll::-webkit-scrollbar-thumb { background: rgba(15, 25, 30, 0.22); background-clip: padding-box; }

/* A flex item's automatic minimum size is its CONTENT, so any row inside the
   panel that cannot fit pushes the panel's own children wider than the panel —
   which has `overflow: hidden`, so the excess is not scrollable, it is gone.
   Measured at 390px: the panel was 369px and its head and body were 516px, with
   the close button sitting at x479, off the screen entirely and unreachable.
   These four are the panel's structure; none of them has anything to gain from
   being wider than the panel it is inside. */
.settings-panel > .settings-head,
.settings-panel > .settings-body,
.settings-panel > .settings-foot,
.settings-body > .settings-nav { min-width: 0; }

@media (max-width: 720px) {
  .settings-body { flex-direction: column !important; }
  .settings-nav { width: 100%; min-width: 0; flex-direction: column; min-height: 0; }

  /* On a phone the sidebar is a PICKER, not a list. Wrapping every category
     into rows of chips filled the whole screen before a single setting was
     visible, put the section dividers (WIDGET, INTEGRAZIONI, SISTEMA) inline
     between two chips wherever the wrap happened to land, and squeezed
     .settings-content to zero height — the panel showed nothing but its own
     navigation. Collapsed, the nav is one row saying where you are; tapping it
     opens the grouped list, and picking a category closes it again. */
  .settings-nav-scroll {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 6px;
    /* No shrinking: the nav is the scroller here, and a shrunk list with
       overflow:visible doesn't scroll, it draws the footer on top of the last
       three rows of categories. */
    flex: 0 0 auto;
    overflow: visible;
    max-height: none;
  }
  .settings-nav-btn {
    width: auto;
    min-width: 0;
    justify-content: flex-start;
    gap: 9px;
    padding: 11px 12px;
    /* Each category needs to read as its own tappable object: side by side with
       no fill they ran together as one block of text. */
    background: rgba(255,255,255,0.05);
    /* Half a phone's width is not enough for "Ambient / Screensaver" on one
       line. The grid equalises the row, so the second line costs nothing and a
       name is worth more than an ellipsis. */
    white-space: normal;
    line-height: 1.22;
    font-size: 13px;
  }
  .settings-nav-btn > span { min-width: 0; overflow-wrap: anywhere; }
  /* A divider belongs to the rows under it, so it takes the full width instead
     of sitting in a chip slot. */
  .settings-nav-label { grid-column: 1 / -1; padding: 9px 4px 1px; }

  .settings-nav:not(.is-open) .settings-nav-btn,
  .settings-nav:not(.is-open) .settings-nav-label,
  .settings-nav:not(.is-open) .settings-nav-footer { display: none; }
  .settings-nav:not(.is-open) .settings-nav-btn.active { display: flex; grid-column: 1 / -1; }
  .settings-nav:not(.is-open) .settings-nav-btn.active::after {
    content: '';
    flex: 0 0 auto;
    margin-left: auto;
    width: 7px;
    height: 7px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    opacity: .75;
  }

  /* Open, the list carries its own scroll. .settings-body is overflow:hidden,
     so an unbounded nav doesn't push the last categories out of view — it has
     them CLIPPED, with no way to reach them. The cap is a % of the body rather
     than vh: the Edge renders with CSS zoom, which vh ignores. */
  .settings-nav.is-open {
    max-height: 62%;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
  }
  /* The scroll is on the NAV, not on the list inside it, so the support links
     and the version scroll past at the end of the categories instead of taking
     a fixed 186px off a 342px picker and leaving room for two rows. */
  .settings-nav.is-open .settings-nav-scroll { overflow: visible; }
  .settings-nav-footer { margin-top: 8px; }
  .settings-content,
  #settings-content[data-cat="general"],
  #settings-content[data-cat="appearance"] { grid-template-columns: 1fr; }
}

/* ── Xenon AI provider selector ─────────────────────────────── */
.ai-provider-toggle { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 8px; }
.ai-provider-toggle label {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 10px 14px; min-height: 44px;
  border: 1px solid rgba(255,255,255,0.10); border-radius: 10px;
  background: rgba(255,255,255,0.03);
  transition: border-color .18s ease, background .18s ease;
}
.ai-provider-toggle label:hover { border-color: rgba(var(--accent-rgb),0.45); }
.ai-provider-toggle input[type="radio"] { accent-color: rgb(var(--accent-rgb)); width: 18px; height: 18px; }
.ai-provider-toggle input[type="radio"]:checked ~ .ai-prov-name { color: rgb(var(--accent-rgb)); font-weight: 600; }
.ai-prov-ic { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; flex: 0 0 auto; }
.ai-prov-ic svg { width: 100%; height: 100%; display: block; }
.ai-provider-toggle input[type="radio"]:disabled { cursor: not-allowed; }
.ai-provider-toggle label:has(input:disabled) { opacity: 0.5; cursor: not-allowed; }

.settings-subpanel {
  grid-column: 1 / -1; /* span both grid columns like .settings-row.full */
  margin-top: 12px; padding: 14px;
  border: 1px solid rgba(255,255,255,0.08); border-radius: 12px;
  background: rgba(255,255,255,0.03);
}
.settings-subpanel[hidden] { display: none; }
/* The Gemini key row is a flex .settings-row, so [hidden] needs an explicit
   display:none to override the flex display when the local provider is active. */
#settings-gemini-key-row[hidden] { display: none; }

.ai-hw-block { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.ai-hw-line { font-weight: 600; }
.ai-hw-stats { font-size: 0.85rem; opacity: 0.85; }
.ai-hw-block.ai-incompatible { border-left: 3px solid #ff5555; padding-left: 10px; }
.ai-hw-block.ai-incompatible .ai-hw-line { color: var(--color-danger); }
.ai-hw-block .settings-btn { align-self: flex-start; }

.ai-status-block { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.ai-status-item { display: flex; align-items: center; gap: 8px; font-size: 0.85rem; flex-wrap: wrap; }
.ai-status-item .settings-btn { margin-left: auto; }
.ai-status-dot-ok::before { content: '●'; color: var(--color-success); margin-right: 4px; }
.ai-status-dot-bad::before { content: '●'; color: var(--color-danger); margin-right: 4px; }
.ai-status-dot-warn::before { content: '●'; color: var(--color-warn); margin-right: 4px; }
.ai-autostart-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.82rem; opacity: 0.9; cursor: pointer;
  margin: 2px 0 4px; padding-left: 2px;
}
.ai-autostart-row .settings-check { width: 16px; height: 16px; }
.ai-status-block > .settings-btn { align-self: flex-start; }

.ai-pull-progress {
  height: 8px; background: rgba(255,255,255,0.08); border-radius: 4px;
  overflow: hidden; position: relative; margin-top: 8px;
}
.ai-pull-progress[hidden] { display: none; }
.ai-pull-bar { height: 100%; width: 0%; background: rgb(var(--accent-rgb)); transition: width 0.3s ease; }
.ai-pull-progress #ai-pull-label {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 0.7rem; line-height: 1; color: rgba(255,255,255,0.9);
}

.settings-advanced { margin-top: 14px; }
.settings-advanced > summary { cursor: pointer; font-size: 0.85rem; opacity: 0.85; padding: 4px 0; }
.settings-advanced > summary:hover { color: rgb(var(--accent-rgb)); }
.settings-advanced .settings-text-input { margin-top: 8px; }

/* ── External calendars (ICS feed subscriptions) ─────────────── */
.feed-list { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
/* Flex-wrap keeps the dense touchscreen layout from overflowing horizontally. */
.feed-row {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 10px; border-radius: 10px;
  border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
}
.feed-row input[type="text"], .feed-row input[type="url"] {
  flex: 1 1 160px; min-width: 0; min-height: 36px;
  padding: 6px 10px; border-radius: 8px;
  border: 1px solid rgba(255,255,255,0.12); background: rgba(0,0,0,0.25); color: var(--text);
}
.feed-swatches { display: inline-flex; gap: 4px; flex: 0 0 auto; }
.feed-swatch {
  width: 20px; height: 20px; border-radius: 50%; padding: 0; cursor: pointer;
  border: 2px solid transparent; box-shadow: 0 0 0 1px rgba(0,0,0,0.3) inset;
}
.feed-swatch.selected { border-color: var(--text); }
.feed-toggle {
  display: inline-flex; align-items: center; gap: 4px;
  white-space: nowrap; font-size: 0.82rem; min-height: 36px; cursor: pointer;
}
.feed-toggle input[type="checkbox"] { width: 16px; height: 16px; accent-color: rgb(var(--accent-rgb)); }
.feed-status { font-size: 0.78rem; opacity: 0.8; min-width: 64px; flex: 1 1 auto; }
.feed-status.is-error { color: var(--color-danger); opacity: 1; }
.feed-remove {
  flex: 0 0 auto; min-width: 36px; min-height: 36px;
  background: transparent; border: none; color: var(--text);
  font-size: 1rem; cursor: pointer; opacity: 0.7;
}
.feed-remove:hover { opacity: 1; color: var(--color-danger); }
.feed-actions { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 8px; }
.feed-add, .feed-refresh {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 38px; padding: 0 16px; border-radius: 10px;
  font-size: 12.5px; font-weight: 800; cursor: pointer;
  transition: background 0.15s ease, transform 0.06s ease;
}
.feed-add {
  border: 1px solid rgba(var(--accent-rgb), 0.36);
  background: rgba(var(--accent-rgb), 0.16); color: #f6fff9;
}
.feed-add:hover { background: rgba(var(--accent-rgb), 0.26); }
.feed-add:active { transform: translateY(1px); }
.feed-refresh {
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.05); color: var(--text);
}
.feed-refresh:hover:not(:disabled) { background: rgba(255,255,255,0.1); }
.feed-refresh:active:not(:disabled) { transform: translateY(1px); }
.feed-refresh:disabled { opacity: 0.45; cursor: default; }
.feed-refresh.is-loading { pointer-events: none; }
.feed-refresh.is-loading::before {
  content: '↻'; display: inline-block;
  animation: feed-spin 0.7s linear infinite;
  will-change: transform;
}
.feed-refresh.is-loading { color: transparent; position: relative; }
.feed-refresh.is-loading::before { color: var(--text); position: absolute; inset: 0; display: grid; place-items: center; }
@keyframes feed-spin { to { transform: rotate(360deg); } }

/* Help + warnings: two scannable groups instead of a flat text wall. */
.feed-help { margin-top: 16px; display: flex; flex-direction: column; gap: 12px; }
.feed-help-group {
  padding: 12px 14px; border-radius: 12px;
  border: 1px solid rgba(255,255,255,0.07); background: rgba(255,255,255,0.025);
}
.feed-help-group.is-warn {
  border-color: rgba(245,158,11,0.22); background: rgba(245,158,11,0.05);
}
.feed-help-title {
  margin: 0 0 9px; font-size: 0.82rem; font-weight: 800; letter-spacing: 0.01em;
  color: var(--text);
}
.feed-help-group.is-warn .feed-help-title { color: var(--color-warn); }
.feed-help-steps, .feed-help-warnings {
  margin: 0; padding: 0; list-style: none;
  display: flex; flex-direction: column; gap: 7px;
}
.feed-help-steps li, .feed-help-warnings li {
  position: relative; padding-left: 18px;
  font-size: 0.8rem; line-height: 1.45; opacity: 0.82;
}
.feed-help-steps li::before {
  content: '→'; position: absolute; left: 0; top: 0;
  color: rgb(var(--accent-rgb)); font-weight: 700;
}
.feed-help-warnings li::before {
  content: ''; position: absolute; left: 3px; top: 0.55em;
  width: 5px; height: 5px; border-radius: 50%; background: #f59e0b;
}
.feed-help-steps strong, .feed-help-warnings strong {
  color: var(--text); opacity: 1; font-weight: 800;
}

/* Source badge on external (read-only) events in the day modal */
.event-source-badge {
  width: 10px; height: 10px; border-radius: 50%;
  display: inline-block; flex: 0 0 auto;
}

/* ── Streaming (Twitch) connect panel ─────────────────────────── */
.streaming-card {
  padding: 14px 16px; border-radius: 12px;
  border: 1px solid rgba(255,255,255,0.08); background: rgba(255,255,255,0.03);
  display: flex; flex-direction: column; gap: 10px;
}
.streaming-card-head { display: flex; align-items: center; gap: 8px; }
.streaming-card-title { font-size: 0.95rem; font-weight: 850; }
.streaming-dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: #6b7280; box-shadow: 0 0 0 3px rgba(107,114,128,0.18);
}
.streaming-dot.on { background: #22c55e; box-shadow: 0 0 0 3px rgba(34,197,94,0.2); }

/* Streamer.bot test-connection feedback line. */
.settings-sb-status { margin-top: 8px; }
.settings-sb-status.is-ok { color: var(--color-success); }
.settings-sb-status.is-err { color: var(--color-danger); }
.settings-sb-status.is-busy { color: var(--muted-text); }
.streaming-connected { font-size: 0.85rem; font-weight: 700; margin: 0; }
.streaming-warn { color: var(--color-warn); }
.streaming-card .settings-btn { align-self: flex-start; }
.streaming-login {
  display: flex; flex-direction: column; gap: 8px; align-items: flex-start;
  padding-top: 6px; border-top: 1px solid rgba(255,255,255,0.07);
}
.streaming-code {
  font-size: 1.6rem; font-weight: 900; letter-spacing: 0.18em;
  font-variant-numeric: tabular-nums; color: #f6fff9;
  padding: 8px 14px; border-radius: 10px;
  background: rgba(var(--accent-rgb),0.14); border: 1px solid rgba(var(--accent-rgb),0.32);
  user-select: all;
}
.streaming-url { font-size: 0.85rem; color: rgb(var(--accent-rgb)); word-break: break-all; }
/* Credential-entry form (shown until a provider is configured). */
.streaming-setup { display: flex; flex-direction: column; gap: 9px; }
.streaming-setup-steps { margin: 0; padding-left: 1.25em; display: flex; flex-direction: column; gap: 5px; }
.streaming-setup-steps li { margin: 0; }
.streaming-setup-link { font-size: 0.82rem; font-weight: 700; color: rgb(var(--accent-rgb)); align-self: flex-start; }
.streaming-field { display: flex; flex-direction: column; gap: 5px; }
.streaming-field-label { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-dim, #8b91a1); }
.streaming-input { width: 100%; box-sizing: border-box; }
.streaming-setup .settings-btn { align-self: flex-start; }
.streaming-cred-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.streaming-cred-actions .settings-btn { align-self: flex-start; }
/* Discord-only: notification-mirroring toggles at the bottom of the card. */
.streaming-notif {
  display: flex; flex-direction: column; gap: 8px;
  padding-top: 8px; border-top: 1px solid rgba(255,255,255,0.07);
}
.streaming-notif .settings-note { margin: 0; }
.streaming-poll { font-size: 0.8rem; opacity: 0.7; margin: 0; }
.streaming-err { color: var(--color-danger); opacity: 1; }

/* Copyable value row (e.g. the OAuth redirect URI) — read-only text + Copy button. */
.streaming-copy-row {
  display: flex; align-items: stretch; gap: 8px; width: 100%;
}
.streaming-copy-val {
  flex: 1 1 auto; min-width: 0; box-sizing: border-box;
  display: flex; align-items: center; padding: 8px 11px; border-radius: 9px;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 0.8rem;
  color: var(--text, #e7e9ee); background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.12);
  overflow-x: auto; white-space: nowrap; user-select: all; -webkit-user-select: all;
}
.streaming-copy-btn { flex: 0 0 auto; align-self: stretch; }

/* Spotify settings section: "what you get" perks + numbered setup steps. */
.settings-spotify-perks {
  list-style: none; margin: 4px 0 10px; padding: 0; display: flex; flex-direction: column; gap: 6px;
}
.settings-spotify-perks li {
  position: relative; padding-left: 24px; font-size: 0.86rem; line-height: 1.4; color: var(--text, #e7e9ee);
}
.settings-spotify-perks li::before {
  content: ''; position: absolute; left: 6px; top: 0.55em; width: 8px; height: 8px; border-radius: 50%;
  background: #1ed760; box-shadow: 0 0 0 3px rgba(30,215,96,0.18);
}
.settings-spotify-premium {
  border-left: 3px solid rgba(30,215,96,0.55); padding-left: 10px; margin: 2px 0 14px;
}
.settings-spotify-setup-head {
  font-size: 0.78rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--text-dim, #8b91a1); margin: 6px 0 8px;
}
.settings-spotify-steps {
  margin: 0 0 14px; padding-left: 20px; display: flex; flex-direction: column; gap: 7px;
}
.settings-spotify-steps li { font-size: 0.86rem; line-height: 1.45; color: var(--text, #e7e9ee); }
.settings-spotify-steps li::marker { color: var(--color-success); font-weight: 800; }

/* ── Shareable presets: export/import buttons + the share/import modal ── */
.settings-share-buttons { display: flex; flex-wrap: wrap; gap: 8px; }

.preset-modal-overlay {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: center; justify-content: center; padding: 18px;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(4px);
  animation: preset-modal-fade 0.16s ease;
}
@keyframes preset-modal-fade { from { opacity: 0; } to { opacity: 1; } }
.preset-modal {
  width: min(440px, 100%);
  max-height: calc(100vh - 36px);
  overflow-y: auto;
  /* Deliberately OPAQUE: panels use the user-tunable --panel-alpha glass
     transparency, but a dialog with actionable content becomes unreadable when
     see-through (as reported at a low panel alpha) — keep a solid surface
     regardless of the theme, matching ColorPicker. */
  background: rgb(var(--panel-rgb, 17, 19, 20));
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  padding: 18px;
}
.preset-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.preset-modal-title { margin: 0; font-size: 1.02rem; font-weight: 700; color: var(--text, #e7e9ee); }
.preset-modal-close {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  color: var(--text-dim, #8b91a1); font-size: 1rem; line-height: 1; padding: 6px; border-radius: 8px;
}
.preset-modal-close:hover { background: rgba(255, 255, 255, 0.08); color: var(--text, #e7e9ee); }
.preset-modal-what { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; min-width: 0; }
.preset-modal-kind {
  flex: none; font-size: 0.72rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px; color: var(--accent, #35e08e);
  background: rgba(var(--accent-rgb, 53, 224, 142), 0.14); border: 1px solid rgba(var(--accent-rgb, 53, 224, 142), 0.3);
}
.preset-modal-whatname { font-weight: 600; font-size: 0.92rem; color: var(--text, #e7e9ee); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.preset-modal-desc { margin: 0 0 12px; font-size: 0.85rem; line-height: 1.5; color: var(--text-dim, #8b91a1); }
.preset-code-field {
  width: 100%; box-sizing: border-box; resize: vertical;
  padding: 9px 11px; font: inherit; font-size: 0.8rem; font-family: ui-monospace, monospace;
  color: var(--text, #e7e9ee); background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
  border-radius: 10px; word-break: break-all;
}
.preset-modal-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.preset-modal-actions .settings-btn { flex: 1 1 auto; }
.preset-page-list { display: flex; flex-direction: column; gap: 8px; max-height: 46vh; overflow-y: auto; }
.preset-page-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; box-sizing: border-box; text-align: left; cursor: pointer;
  padding: 11px 13px; font: inherit; color: var(--text, #e7e9ee);
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
  border-radius: 11px; transition: background 0.14s ease, border-color 0.14s ease;
}
.preset-page-item:hover:not(:disabled) { background: rgba(var(--accent-rgb, 53, 224, 142), 0.1); border-color: rgba(var(--accent-rgb, 53, 224, 142), 0.35); }
.preset-page-item:disabled { opacity: 0.45; cursor: default; }
.preset-page-name { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; font-size: 0.92rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.preset-page-cur {
  flex: none; font-size: 0.66rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase;
  padding: 2px 7px; border-radius: 999px; color: var(--accent, #35e08e);
  background: rgba(var(--accent-rgb, 53, 224, 142), 0.16);
}
.preset-page-meta { flex: none; font-size: 0.78rem; color: var(--text-dim, #8b91a1); }

/* ── Export picker (Settings → Condividi & Importa → Esporta…) ───────────── */
/* One door replacing nine buttons: a scannable list of what can be exported,
   each row a single tap straight into that kind's existing export dialog. */
.export-pick-list { display: flex; flex-direction: column; gap: 6px; }
.export-pick-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; cursor: pointer; font: inherit;
  padding: 11px 12px; border-radius: 10px; color: var(--text, #e7e9ee);
  background: var(--control-bg, rgba(255, 255, 255, 0.05));
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
  transition: background 0.15s ease, border-color 0.15s ease;
}
.export-pick-row:hover { background: rgba(var(--accent-rgb), 0.09); border-color: rgba(var(--accent-rgb), 0.45); }
.export-pick-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.export-pick-txt b { line-height: 1.2; }
.export-pick-row .preset-modal-kind { flex: none; padding: 2px 6px; font-size: 0.62rem; }

/* ── Bundle ("Pacchetto Xenon") export checklist + import widget list ────── */
.preset-check-list { display: flex; flex-direction: column; gap: 6px; max-height: 46vh; overflow-y: auto; margin-bottom: 4px; }
.preset-check-group {
  margin: 8px 2px 2px; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-dim, #8b91a1);
}
.preset-check-group:first-child { margin-top: 0; }
/* `display: flex` below beats the UA's `[hidden] { display: none }`, so a row
   hidden from JS would stay on screen. Same trap `.settings-overlay[hidden]`
   already guards against — it cost the share card a "use a real screenshot"
   checkbox that was offered even when capture had been refused. */
.preset-check-row[hidden] { display: none !important; }
.preset-check-row {
  display: flex; align-items: center; gap: 11px; cursor: pointer;
  padding: 10px 12px; border-radius: 11px;
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
  transition: background 0.14s ease, border-color 0.14s ease;
}
.preset-check-row:hover:not(.is-static) { background: rgba(var(--accent-rgb, 53, 224, 142), 0.09); border-color: rgba(var(--accent-rgb, 53, 224, 142), 0.3); }
.preset-check-row input[type="checkbox"] { flex: none; width: 17px; height: 17px; accent-color: var(--accent, #35e08e); cursor: pointer; }
.preset-check-row:has(input:disabled) { opacity: 0.45; cursor: default; }
.preset-check-row.is-static { cursor: default; }
.preset-check-main { display: flex; align-items: baseline; gap: 8px; min-width: 0; flex: 1 1 auto; }
.preset-check-name { font-weight: 600; font-size: 0.9rem; color: var(--text, #e7e9ee); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.preset-check-meta { flex: none; font-size: 0.76rem; color: var(--text-dim, #8b91a1); }
.preset-bundle-widgets { margin: 0 0 12px; }
/* Live "your package will contain" footer + why-disabled note. */
.preset-bundle-summary { font-weight: 600; color: var(--text, #e7e9ee); margin-top: 10px; }
.preset-bundle-note { font-size: 0.78rem; font-style: italic; }

/* Deck-profile import review: the action-type chips and the trust caution. */
.preset-deck-acts { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
.preset-deck-act {
  font-size: 0.78rem; font-weight: 600; padding: 4px 9px; border-radius: 999px;
  color: var(--text, #e7e9ee); background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
}
.preset-deck-caution { font-size: 0.8rem; color: var(--warn, #ffb454); }
/* "Keep your import code" reminder — a helpful accent note, not a warning. */
.preset-keep-code {
  font-size: 0.8rem; color: var(--text, #e7e9ee);
  padding: 8px 10px; border-radius: 8px;
  border: 1px solid rgba(var(--accent-rgb, 30, 215, 96), 0.28);
  background: rgba(var(--accent-rgb, 30, 215, 96), 0.08);
}
.preset-modal-note { font-style: italic; }

/* ── Share card — canvas preview modal. Wider than the other preset dialogs
      because the preview is a 16:9 (or 9:16) card, not a code field. ── */
.sharecard-modal { width: min(760px, 100%); }
.sharecard-canvas {
  width: 100%; height: auto; display: block; margin: 0 0 12px;
  border-radius: 12px; border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
  background: #000;
}
/* The composer redraws the canvas outright, so "busy" is a dim, not a spinner —
   anything animated here would also have to be hidden during a capture. */
.sharecard-canvas.is-busy { opacity: 0.55; transition: opacity 160ms ease; }
.sharecard-modal .preset-check-row { margin-bottom: 4px; }
.sharecard-formats { display: flex; gap: 8px; margin-bottom: 10px; }
.sharecard-formats .settings-btn.active {
  border-color: rgba(var(--accent-rgb, 30, 215, 96), 0.55);
  background: rgba(var(--accent-rgb, 30, 215, 96), 0.14);
  color: var(--accent, #1ed760);
}
.sharecard-note {
  margin: 6px 0 10px; font-size: 0.78rem; line-height: 1.45;
  color: var(--text-dim, rgba(231, 233, 238, 0.55));
}
/* The link the QR encodes, spelled out — a QR is for a camera, a post needs a
   URL you can paste. Also the only place the destination is legible. */
.sharecard-link { display: flex; gap: 8px; align-items: center; margin: 4px 0; }
.sharecard-link[hidden] { display: none !important; }   /* flex beats [hidden] */
.sharecard-field-label {
  margin: 10px 0 2px; font-size: 0.74rem; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--text-dim, rgba(231, 233, 238, 0.5));
}
.sharecard-link-field {
  flex: 1 1 auto; min-width: 0;
  padding: 9px 11px; font-size: 0.8rem; font-family: var(--mono, ui-monospace, monospace);
  color: var(--text, #e7e9ee); background: var(--input-bg, rgba(0, 0, 0, 0.28));
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12)); border-radius: 10px;
  text-overflow: ellipsis;
}
.sharecard-link-field:focus {
  outline: none; border-color: rgba(var(--accent-rgb, 30, 215, 96), 0.5);
}
/* The card's own link is an OUTPUT — it must not look like somewhere to type. */
.sharecard-link-field.is-readonly {
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-muted, rgba(231, 233, 238, 0.72));
  cursor: default;
}
.sharecard-link .settings-btn { flex: none; }

/* The catalog's "may use more resources" note, repeated inside the import dialog. */
.preset-perf-note {
  font-size: 0.8rem; color: var(--warn, #ffb454);
  padding: 8px 10px; border-radius: 8px;
  border: 1px solid rgba(255, 180, 84, 0.3);
  background: rgba(255, 180, 84, 0.08);
}

/* ══ Community gallery ("Store") — premium storefront overlay ══════════════ */
.cgal-overlay { padding: 3.2vh 3vw; }
.cgal-modal {
  width: min(1080px, 100%);
  /* Locked height so switching category filters — which only swaps the scroll
     area's contents — can't resize the whole dialog on every click (#2). The
     scroll body (.cgal-scroll, flex:1) absorbs the difference and scrolls
     internally instead. Capped to the viewport on short screens. */
  height: min(880px, calc(100vh - 6vh));
  max-height: calc(100vh - 6vh);
  padding: 0; overflow: hidden;
  display: flex; flex-direction: column;
  border-radius: 22px;
}
.cgal-ic { display: inline-flex; line-height: 0; }
.cgal-ic svg { width: 1em; height: 1em; display: block; }

/* ── Storefront header ── */
.cgal-topbar {
  display: flex; align-items: center; gap: 14px; flex: none;
  padding: 16px 18px;
  border-bottom: 1px solid var(--glass-border, rgba(255, 255, 255, 0.08));
  background: linear-gradient(180deg, rgba(var(--accent-rgb), 0.09), transparent);
}
.cgal-brand { display: flex; align-items: center; gap: 13px; min-width: 0; flex: 1; }
.cgal-brand-mark {
  flex: none; width: 42px; height: 42px; border-radius: 13px; display: grid; place-items: center;
  color: var(--accent, #35e08e); font-size: 23px;
  background: rgba(var(--accent-rgb), 0.14); border: 1px solid rgba(var(--accent-rgb), 0.32);
}
.cgal-brand-txt { min-width: 0; }
.cgal-brand-title { margin: 0; font-size: 1.3rem; font-weight: 800; letter-spacing: -0.015em; color: var(--text, #e7e9ee); }
.cgal-brand-sub { margin: 2px 0 0; font-size: 0.8rem; color: var(--text-dim, #8b91a1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cgal-head-actions { display: flex; align-items: center; gap: 8px; flex: none; }
.cgal-trust {
  display: inline-flex; align-items: center; gap: 6px; font-size: 0.74rem; font-weight: 600;
  color: var(--accent, #35e08e); padding: 7px 12px; border-radius: 999px;
  background: rgba(var(--accent-rgb), 0.1); border: 1px solid rgba(var(--accent-rgb), 0.24);
}
.cgal-trust svg { width: 14px; height: 14px; }
.cgal-iconbtn {
  appearance: none; cursor: pointer; width: 40px; height: 40px; border-radius: 12px; flex: none;
  display: grid; place-items: center; color: var(--text-dim, #8b91a1);
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
  transition: background 0.15s ease, color 0.15s ease;
}
.cgal-iconbtn:hover { color: var(--text, #e7e9ee); background: rgba(255, 255, 255, 0.09); }
.cgal-iconbtn svg { width: 18px; height: 18px; }

/* ── Tabs: the catalog vs what this machine already has ── */
/* Underline tabs, not pills: the rail below already uses pills for kind
   filtering, so the two levels must not read as the same control. */
.cgal-tabs {
  display: flex; gap: 4px; flex: none; padding: 0 18px;
  border-bottom: 1px solid var(--glass-border, rgba(255, 255, 255, 0.08));
}
.cgal-tab {
  appearance: none; display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 13px 14px; font: inherit; font-size: 0.88rem; font-weight: 650;
  color: var(--text-dim, #8b91a1); background: none; border: 0;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.cgal-tab svg { width: 16px; height: 16px; }
.cgal-tab:hover { color: var(--text, #e8eaf0); }
.cgal-tab.active { color: var(--accent, #35e08e); border-bottom-color: var(--accent, #35e08e); }

/* ── Scroll body ── */
/* overflow-x is pinned rather than left to compute: `overflow-y: auto` alone
   turns the x axis into `auto` too, so ONE child that refuses to shrink pans
   the entire storefront sideways — headers, shelves and cards together, cut off
   at both edges with the cause nowhere near where it looks wrong. That is what
   a phone was getting. Anything genuinely wider than the panel (the card shelf,
   a card's screenshots) carries its own horizontal scroller, so clipping here
   costs nothing and keeps a future too-wide element a local defect. */
.cgal-scroll { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 18px; min-height: 220px; }

/* ── Installed tab (js/installed-manager.js) ── */
/* Deliberately NOT a second gallery: this is an operational list, so rows are
   dense and text-first. Kind chips reuse the rail's visual language. */
.inst-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.inst-chip {
  display: inline-flex; align-items: center; white-space: nowrap; cursor: pointer;
  padding: 8px 14px; border-radius: 999px; font: inherit; font-size: 0.82rem; font-weight: 600;
  color: var(--text-dim, #8b91a1); background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.08));
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.inst-chip:hover { color: var(--text, #e8eaf0); background: rgba(255, 255, 255, 0.08); }
.inst-chip.active { color: var(--accent, #35e08e); background: rgba(var(--accent-rgb), 0.16); border-color: rgba(var(--accent-rgb), 0.4); }

.inst-list { display: flex; flex-direction: column; gap: 8px; }
.inst-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 12px 14px; border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
}
/* Legacy = imports from before receipts existed; they are removed as one group,
   so the dashed edge marks them as a different kind of row. */
.inst-row.is-legacy { border-style: dashed; }

/* Thumbnail: the catalog screenshot when the entry publishes one, otherwise the
   kind glyph. A fixed box either way so the rows stay on one rhythm — a list
   that jumps between framed and unframed rows reads as broken. */
.inst-thumb {
  flex: none; width: 52px; height: 52px; border-radius: 10px; overflow: hidden;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
}
.inst-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.inst-thumb.is-glyph { color: var(--text-dim, #8b91a1); background: rgba(var(--accent-rgb), 0.07); border-color: rgba(var(--accent-rgb), 0.18); }
.inst-thumb.is-glyph svg { width: 22px; height: 22px; }

.inst-row-info { display: flex; flex-direction: column; gap: 5px; min-width: 0; flex: 1; }
.inst-row-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; min-width: 0; }
.inst-row-name { font-size: 0.94rem; line-height: 1.25; overflow-wrap: anywhere; color: var(--text, #e7e9ee); }
.inst-row-meta { font-size: 0.76rem; line-height: 1.4; color: var(--text-dim, #8b91a1); overflow-wrap: anywhere; }
.inst-kind {
  flex: none; padding: 2px 7px; border-radius: 999px;
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-dim, #8b91a1); background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
}
.inst-origin {
  flex: none; padding: 2px 7px; border-radius: 999px; font-size: 0.62rem; font-weight: 700;
  color: var(--text-dim, #8b91a1); background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
}
.inst-origin.is-mine { color: var(--accent, #35e08e); background: rgba(var(--accent-rgb), 0.12); border-color: rgba(var(--accent-rgb), 0.3); }
/* Live activity chip fed by the widget perf probe (ok / busy / heavy / paused). */
.inst-activity {
  flex: none; padding: 2px 7px; border-radius: 999px; font-size: 0.62rem; font-weight: 700;
  color: var(--text-dim, #8b91a1); background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
}
.inst-activity.is-busy { color: var(--warn, #ffb454); background: rgba(255, 180, 84, 0.1); border-color: rgba(255, 180, 84, 0.3); }
.inst-activity.is-heavy { color: var(--red, #ff5b6a); background: rgba(255, 91, 106, 0.1); border-color: rgba(255, 91, 106, 0.32); }
.inst-activity.is-paused { color: var(--text-dim, #8b91a1); background: rgba(255, 255, 255, 0.08); border-style: dashed; }
.inst-row-btns { display: flex; align-items: center; gap: 8px; flex: none; }
/* The publisher's note about what a pending update changes. */
.inst-row-changelog {
  font-size: 0.76rem; line-height: 1.4; color: var(--accent, #35e08e);
  overflow-wrap: anywhere; font-style: italic;
}
/* "N updates available · Update all" — sits above the list, so the answer to
   "is anything waiting?" is the first thing the tab says. */
.inst-updbar {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  margin: 0 0 14px; padding: 10px 14px; border-radius: 12px;
  background: rgba(var(--accent-rgb), 0.1);
  border: 1px solid rgba(var(--accent-rgb), 0.28);
}
.inst-updbar-txt { font-size: 0.82rem; font-weight: 600; color: var(--text, #e7e9ee); }
.inst-updbar .settings-btn { flex: none; }
@media (max-width: 560px) {
  .inst-updbar { flex-direction: column; align-items: stretch; gap: 10px; }
}

/* Widget folders the scan refused. Warning-toned, not error-toned: nothing is
   broken, a folder just needs renaming — and it must read as actionable rather
   than alarming. Uses the theme's warning role so it follows light/dark and the
   Comic/Retro skins instead of pinning its own colour. */
.inst-rejected {
  margin: 0 0 14px; padding: 11px 14px; border-radius: 12px;
  background: color-mix(in srgb, var(--warning, #e0a33e) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--warning, #e0a33e) 34%, transparent);
}
.inst-rejected-title {
  margin: 0 0 8px; font-size: 0.82rem; font-weight: 600;
  color: var(--text, #e7e9ee);
}
.inst-rejected-list { display: flex; flex-direction: column; gap: 7px; margin-bottom: 8px; }
.inst-rejected-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 9px; }
.inst-rejected-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.76rem; padding: 2px 7px; border-radius: 6px;
  background: rgba(0, 0, 0, 0.22); color: var(--text, #e7e9ee);
  /* A pasted folder name can be long and has no spaces to break on. */
  overflow-wrap: anywhere;
}
.inst-rejected-why { font-size: 0.78rem; color: var(--muted-text, #aab1c0); flex: 1 1 220px; min-width: 0; }
.inst-rejected .cgal-status { margin: 0; }

.inst-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  margin-top: 18px; padding-top: 16px;
  border-top: 1px solid var(--glass-border, rgba(255, 255, 255, 0.08));
}
.inst-foot .cgal-status { padding: 0; text-align: left; font-size: 0.76rem; }
.inst-foot .settings-btn { flex: none; }

.inst-empty { padding: 52px 6px; text-align: center; }
.inst-empty-title { margin: 0 0 6px; font-size: 1.02rem; font-weight: 700; color: var(--text, #e7e9ee); }
.inst-empty .cgal-status { padding: 0 0 18px; max-width: 46ch; margin: 0 auto; }

@media (max-width: 560px) {
  .inst-row { flex-direction: column; align-items: stretch; }
  .inst-row-btns { justify-content: flex-end; }
  .inst-foot { flex-direction: column; align-items: stretch; }
  .inst-foot .settings-btn { width: 100%; }
}

/* ── Toolbar: search + selects + icon rail ── */
.cgal-toolbar { display: flex; flex-direction: column; gap: 12px; margin-bottom: 20px; }
.cgal-searchrow { display: flex; gap: 8px; align-items: center; }
.cgal-searchbox { flex: 1; position: relative; display: flex; align-items: center; min-width: 0; }
.cgal-search-ic { position: absolute; left: 14px; color: var(--text-dim, #8b91a1); font-size: 18px; pointer-events: none; }
input.cgal-search {
  width: 100%; box-sizing: border-box; padding: 12px 14px 12px 42px;
  font: inherit; font-size: 0.92rem; color: var(--text, #e7e9ee);
  background: rgba(255, 255, 255, 0.05); border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12)); border-radius: 13px;
}
input.cgal-search::placeholder { color: var(--text-dim, #8b91a1); }
input.cgal-search:focus { outline: none; border-color: rgba(var(--accent-rgb), 0.55); background: rgba(255, 255, 255, 0.07); }
/* Wrap the category filters onto as many rows as needed instead of scrolling
   them horizontally — a scrolling rail left the last filter (e.g. "deck") cut off
   at the right edge, "almost out of range" (#3). With the modal height now locked
   (#2), the extra row just sits at the top of the scroll area. */
.cgal-rail { display: flex; flex-wrap: wrap; gap: 6px; padding-bottom: 2px; }
.cgal-railbtn {
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; cursor: pointer;
  padding: 9px 15px; border-radius: 12px; font-size: 0.84rem; font-weight: 600;
  color: var(--text-dim, #8b91a1); background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.08));
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.cgal-railbtn svg { width: 16px; height: 16px; }
.cgal-railbtn:hover { color: var(--text, #e8eaf0); background: rgba(255, 255, 255, 0.08); }
.cgal-railbtn.active { color: var(--accent, #35e08e); background: rgba(var(--accent-rgb), 0.16); border-color: rgba(var(--accent-rgb), 0.4); }
.cgal-railbtn.lim.active { color: #bcb0ff; background: rgba(139, 123, 255, 0.2); border-color: rgba(139, 123, 255, 0.45); }
.cgal-railbtn.sup.active { color: #ffd089; background: rgba(255, 180, 84, 0.18); border-color: rgba(255, 180, 84, 0.42); }
.cgal-select { position: relative; flex: none; }
/* The two toolbar dropdowns are upgraded to the app's CustomSelect (the native
   OS popup read as cheap) — size its trigger to sit level with the search field. */
.cgal-select .cs-wrap { display: flex; }
.cgal-select .cs-trigger { padding: 11px 12px 11px 14px; border-radius: 12px; font-size: 0.82rem; min-width: 108px; }

/* ── Grid + product cards ── */
.cgal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 16px; }
/* One-entry sections lay the card out wide instead of stranding a 232px card at
   the left edge of a full-width shelf. Same shape as the website catalog: media
   left, details right, and the description gets the room to be read. */
.cgal-grid.is-solo { grid-template-columns: 1fr; }
.cgal-grid.is-solo > .cgal-card { flex-direction: row; align-items: stretch; }
.cgal-grid.is-solo > .cgal-card > .cgal-media { flex: 0 0 44%; aspect-ratio: auto; min-height: 232px; }
.cgal-grid.is-solo > .cgal-card > .cgal-body { justify-content: center; gap: 9px; padding: 22px 26px; }
.cgal-grid.is-solo .cgal-name { font-size: 1.22rem; letter-spacing: -0.01em; }
.cgal-grid.is-solo .cgal-version { font-size: 0.78rem; }
.cgal-grid.is-solo .cgal-author { font-size: 0.84rem; }
.cgal-grid.is-solo .cgal-desc { font-size: 0.9rem; line-height: 1.55; -webkit-line-clamp: 5; max-width: 62ch; }
/* The card's `margin-top: auto` pins the actions to the bottom of a tall tile;
   in the wide layout the whole block is centred instead, so it must go. */
.cgal-grid.is-solo .cgal-card-actions { margin-top: 4px; max-width: 420px; }
.cgal-card {
  position: relative; display: flex; flex-direction: column; min-width: 0;
  border-radius: 16px; overflow: hidden;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
  transition: transform 0.22s cubic-bezier(0.2, 0.8, 0.2, 1), border-color 0.2s ease, box-shadow 0.2s ease;
}
.cgal-card:hover { transform: translateY(-4px); border-color: rgba(var(--accent-rgb), 0.5); box-shadow: 0 14px 34px rgba(0, 0, 0, 0.42), 0 0 0 1px rgba(var(--accent-rgb), 0.18); }
.cgal-card.is-limited:hover { border-color: rgba(139, 123, 255, 0.6); box-shadow: 0 14px 34px rgba(0, 0, 0, 0.45), 0 0 26px rgba(139, 123, 255, 0.24); }
.cgal-card.is-sup:hover { border-color: rgba(255, 180, 84, 0.55); box-shadow: 0 14px 34px rgba(0, 0, 0, 0.45), 0 0 26px rgba(255, 180, 84, 0.18); }
.cgal-card.dim { opacity: 0.55; }
.cgal-card.dim:hover { transform: none; box-shadow: none; }

/* Media: screenshot › live bg preview › generated canvas — always filled. */
.cgal-media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: rgba(0, 0, 0, 0.4); }
.cgal-media canvas { width: 100%; height: 100%; display: block; }
.cgal-media canvas, .cgal-media > .cgal-shots, .cgal-media > .cgal-preview { transition: transform 0.35s ease; }
.cgal-card:hover .cgal-media canvas, .cgal-card:hover .cgal-shots, .cgal-card:hover .cgal-preview { transform: scale(1.05); }
.cgal-media-veil { position: absolute; inset: 0; z-index: 1; pointer-events: none; background: linear-gradient(180deg, rgba(6, 8, 10, 0.3) 0%, transparent 32%, transparent 60%, rgba(6, 8, 10, 0.52) 100%); }
.cgal-shots { display: flex; height: 100%; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.cgal-shots::-webkit-scrollbar { display: none; }
.cgal-shot { flex: 0 0 100%; scroll-snap-align: start; width: 100%; height: 100%; object-fit: cover; display: block; }
.cgal-shotdots { position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); z-index: 3; display: flex; gap: 5px; }
.cgal-shotdot { width: 5px; height: 5px; border-radius: 50%; background: rgba(255, 255, 255, 0.45); }
.cgal-shotdot.on { background: #fff; }
.cgal-preview { position: absolute; inset: 0; }
.cgal-preview-frame { width: 100%; height: 100%; border: 0; display: block; pointer-events: none; }
.cgal-tier {
  position: absolute; top: 10px; left: 10px; z-index: 3;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.02em;
  padding: 5px 10px 5px 8px; border-radius: 999px; color: #fff;
  background: rgba(8, 10, 14, 0.62); border: 1px solid rgba(255, 255, 255, 0.16); backdrop-filter: blur(8px);
}
.cgal-tier svg { width: 13px; height: 13px; }
.cgal-tier.t-limited { color: #cabfff; border-color: rgba(139, 123, 255, 0.55); background: linear-gradient(135deg, rgba(90, 70, 180, 0.5), rgba(8, 10, 14, 0.6)); }
.cgal-tier.t-sup { color: #ffd089; border-color: rgba(255, 180, 84, 0.55); }
/* "NEW" flag — entries published since the user last opened the Store (#5). Sits
   top-right, opposite the tier pill, in the same glass-pill language but tinted
   with the accent. Cleared on the next visit (storeLastVisit in community-gallery.js). */
.cgal-new {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase;
  padding: 4px 9px; border-radius: 999px; color: var(--accent, #35e08e);
  background: rgba(8, 10, 14, 0.62); border: 1px solid rgba(var(--accent-rgb, 53, 224, 142), 0.55);
  backdrop-filter: blur(8px);
}
/* "Novità" rail chip — accent-tinted so it reads as fresh among the kind filters (#5). */
.cgal-railbtn.is-new { color: var(--accent, #35e08e); }
.cgal-railbtn.is-new.active { background: rgba(var(--accent-rgb), 0.16); border-color: rgba(var(--accent-rgb), 0.4); }
/* "Available until {d}" — the scheduling deadline on supporter/limited cards,
   hero and detail view. Tier-coloured: gold for supporters, violet on limited. */
.cgal-until { font-size: 0.74rem; font-weight: 700; color: var(--warn, #ffb454); }
.cgal-card.is-limited .cgal-until, .cgal-hero.is-limited .cgal-until, .cgal-detail-info .t-limited ~ .cgal-until { color: #bcb0ff; }
.cgal-until-big { font-size: 0.84rem; }

/* Count riding the "Novità" rail chip — how many entries are new since the last
   visit (the same number the Settings gear and Store pill badges carry). */
.cgal-rail-cnt {
  margin-left: 6px;
  min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.62rem; font-weight: 800; line-height: 1; border-radius: 999px;
  color: #04240f; background: var(--accent, #35e08e);
}
/* "N new since your last visit" count dot on the Settings entry points to the Store
   (#5). The buttons are made position:relative so the dot sits at their corner; a
   fixed red keeps it readable on both the neutral pill and the accent hero CTA. */
.settings-store-pill, .settings-store-hero-cta { position: relative; overflow: visible; }
.cgal-store-dot {
  position: absolute; top: -6px; right: -6px; z-index: 2;
  min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.62rem; font-weight: 800; line-height: 1; border-radius: 999px;
  color: #fff; background: #e5484d; border: 1.5px solid var(--panel, #12151c);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}
/* Accent variant of the Store dot: shown only when there are no updates but there
   ARE new items since the last visit — discovery, not a call to action (#5). */
.cgal-store-dot.is-new { background: var(--accent, #35e08e); color: #04240f; border-color: var(--panel, #12151c); }
/* On the topbar Settings gear the count sits at the TOP-LEFT corner: the
   top-right is the app-update dot's spot (UpdateModal.css), and the two can be
   up at the same time — an update and new Store content are different news. */
.qbtn-settings .cgal-store-dot { top: 2px; left: 6px; right: auto; }
/* Red count of available updates on the Store's Installed tab — how many owned
   items have a newer version waiting. Sits inline after the tab label. */
.cgal-tab-badge {
  margin-left: 6px; display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; padding: 0 5px; box-sizing: border-box;
  font-size: 0.6rem; font-weight: 800; line-height: 1; border-radius: 999px;
  color: #fff; background: #e5484d; vertical-align: middle;
}
.cgal-swatches { position: absolute; bottom: 10px; right: 10px; z-index: 3; display: flex; gap: 4px; padding: 4px 6px; border-radius: 999px; background: rgba(8, 10, 14, 0.55); backdrop-filter: blur(6px); }
.cgal-swatches .preset-swatch-dot { width: 12px; height: 12px; border-radius: 50%; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16); }
.cgal-lock { position: absolute; inset: 0; z-index: 4; display: grid; place-items: center; background: linear-gradient(180deg, rgba(8, 10, 14, 0.15), rgba(8, 10, 14, 0.55)); }
.cgal-lock > span { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; font-size: 15px; background: rgba(8, 10, 14, 0.65); border: 1px solid rgba(255, 180, 84, 0.55); }

.cgal-body { display: flex; flex-direction: column; gap: 6px; padding: 13px 14px 14px; flex: 1; min-height: 0; }
.cgal-name { font-weight: 700; font-size: 0.98rem; color: var(--text, #e7e9ee); line-height: 1.25; overflow: hidden; text-overflow: ellipsis; }
.cgal-version { font-weight: 500; font-size: 0.72rem; color: var(--text-dim, #8b91a1); margin-left: 4px; }
.cgal-author { font-size: 0.78rem; color: var(--text-dim, #8b91a1); }
.cgal-author a { color: rgba(var(--accent-rgb), 0.95); text-decoration: none; }
.cgal-author a:hover { text-decoration: underline; }
.cgal-authorstar { color: var(--warn, #ffb454); }
.cgal-catlabel { color: var(--text-dim, #8b91a1); }
/* Star ratings: the async-filled card slot and the detail view's vote row. */
.cgal-stars { margin-left: 6px; color: var(--warn, #ffb454); font-weight: 600; white-space: nowrap; }
/* Install count: deliberately quieter than the rating. It is a rough popularity
   signal, not a quality one, and it should never out-shout the stars. */
.cgal-installs { margin-left: 6px; color: var(--text-dim, #8b91a1); font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.cgal-installs:empty { display: none; }
.cgal-rate { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 6px 0 2px; }
.cgal-rate-row { display: inline-flex; gap: 2px; }
.cgal-rate-star {
  font-size: 22px; line-height: 1; padding: 4px 3px; min-width: 30px; /* touch-friendly */
  background: none; border: 0; cursor: pointer; color: var(--text-dim, #8b91a1);
  transition: color 0.12s ease, transform 0.08s ease;
}
.cgal-rate-star:hover { transform: translateY(-1px); }
.cgal-rate-star.on { color: var(--warn, #ffb454); }
.cgal-rate-avg { font-size: 0.8rem; color: var(--text-dim, #8b91a1); }
.cgal-desc { font-size: 0.82rem; line-height: 1.45; color: var(--text-dim, #8b91a1); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.cgal-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.cgal-tag { font-size: 0.72rem; color: rgba(var(--accent-rgb), 0.8); }
/* "May use more resources" — the catalog's performance note. Amber pill on the
   card/hero byline and the detail meta row; the long sentence sits below in the
   detail view. Informational, never blocking. */
.cgal-perfchip {
  flex: none; display: inline-block; margin-left: 6px; padding: 2px 8px; border-radius: 999px;
  font-size: 0.64rem; font-weight: 700; letter-spacing: 0.02em;
  color: var(--warn, #ffb454); background: rgba(255, 180, 84, 0.1);
  border: 1px solid rgba(255, 180, 84, 0.32);
}
.cgal-detail-perfnote {
  margin: 2px 0 0; font-size: 0.8rem; line-height: 1.45; color: var(--warn, #ffb454); opacity: 0.9;
}

/* ── Buttons ── */
.cgal-btn {
  appearance: none; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 10px 16px; border-radius: 11px; font: inherit; font-size: 0.86rem; font-weight: 650; cursor: pointer;
  color: var(--text, #e7e9ee); background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.14)); text-decoration: none;
  transition: background 0.15s ease, filter 0.15s ease, box-shadow 0.15s ease;
}
.cgal-btn:hover { background: rgba(255, 255, 255, 0.12); }
.cgal-btn:disabled { opacity: 0.4; cursor: default; }
.cgal-btn.primary { color: var(--on-accent); background: var(--accent); border-color: transparent; font-weight: 700; box-shadow: 0 4px 14px rgba(var(--accent-rgb), 0.28); }
.cgal-btn.primary:hover:not(:disabled) { filter: brightness(1.08); box-shadow: 0 6px 20px rgba(var(--accent-rgb), 0.42); }
.cgal-unlock { color: var(--warn, #ffb454); border-color: rgba(255, 180, 84, 0.42); background: rgba(255, 180, 84, 0.1); }
.cgal-unlock:hover { background: rgba(255, 180, 84, 0.18); }
/* Settled "already installed" state — a non-interactive chip, not a button, so it
   reads as done and can't re-trigger an import. Wins over .primary/.cgal-unlock
   colours by coming later at equal specificity. */
.cgal-btn.cgal-installed {
  cursor: default; font-weight: 700; box-shadow: none; filter: none;
  color: var(--success, #45d483);
  background: rgba(69, 212, 131, 0.14);
  border-color: rgba(69, 212, 131, 0.4);
}
.cgal-btn.cgal-installed:hover { background: rgba(69, 212, 131, 0.14); filter: none; }
.cgal-limited-buttons { width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(138px, 1fr)); gap: 8px; }
.cgal-limited-buttons .cgal-ic { width: 16px; height: 16px; }
.cgal-claim { color: #110b27; border-color: transparent; background: #a99cff; box-shadow: 0 5px 18px rgba(139, 123, 255, 0.3); white-space: nowrap; }
.cgal-claim:hover { background: #bcb2ff; box-shadow: 0 7px 24px rgba(139, 123, 255, 0.42); }
.cgal-discord { color: #fff; border-color: rgba(255, 255, 255, 0.16); background: #5865f2; box-shadow: 0 5px 18px rgba(88, 101, 242, 0.25); white-space: nowrap; }
.cgal-discord:hover { background: #6975f5; box-shadow: 0 7px 24px rgba(88, 101, 242, 0.38); }
/* "I have a code" — deliberately the quiet one of the row: it matters only to
   the few who already claimed, and must not compete with the claim button. */
.cgal-havecode { color: var(--text-muted, #a7adbb); border-color: var(--glass-border, rgba(255, 255, 255, 0.14)); background: transparent; white-space: nowrap; }
.cgal-havecode:hover { color: var(--text, #e7e9ee); background: rgba(255, 255, 255, 0.08); }
.cgal-card-actions { display: flex; align-items: center; gap: 10px; margin-top: auto; padding-top: 10px; flex-wrap: wrap; }
.cgal-card-actions .cgal-btn { flex: 1; }
.cgal-limcount { flex: none; width: 100%; text-align: right; font-size: 0.74rem; color: var(--text-dim, #8b91a1); font-variant-numeric: tabular-nums; }
.cgal-needs { font-size: 0.72rem; color: var(--text-dim, #8b91a1); }
.cgal-soldout { flex: 1; text-align: center; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: #ff5a63; padding: 9px 12px; border-radius: 10px; border: 1px solid rgba(255, 90, 99, 0.42); background: rgba(255, 90, 99, 0.1); }

/* ── Cinematic hero spotlight ── */
.cgal-hero {
  position: relative; display: grid; grid-template-columns: 1.15fr 1fr; margin-bottom: 24px;
  border-radius: 18px; overflow: hidden; border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
  background: rgba(255, 255, 255, 0.03);
}
.cgal-hero.is-limited { border-color: rgba(139, 123, 255, 0.4); box-shadow: 0 0 0 1px rgba(139, 123, 255, 0.14), 0 18px 50px rgba(40, 20, 90, 0.34); }
.cgal-hero.is-sup { border-color: rgba(255, 180, 84, 0.35); }
.cgal-media-hero { aspect-ratio: auto; min-height: 300px; height: 100%; }
.cgal-media-hero .cgal-media-veil { background: linear-gradient(90deg, transparent 40%, rgba(6, 8, 10, 0.4) 100%), linear-gradient(180deg, transparent 60%, rgba(6, 8, 10, 0.4) 100%); }
/* Holo sheen sweeps via transform (compositor-only) — animating
   background-position recomputes style + repaints the hero every display frame
   for as long as the gallery is open (GitHub #99). The pseudo is 260% wide with
   the gradient at natural size and slides across; .cgal-media's overflow:hidden
   clips it. Same traversal as the old 130%→-130% background-position sweep. */
.cgal-hero.is-limited .cgal-media-hero::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 260%;
  z-index: 2; pointer-events: none; mix-blend-mode: screen;
  background: linear-gradient(115deg, transparent 30%, rgba(150, 130, 255, 0.28) 48%, rgba(120, 200, 255, 0.2) 54%, transparent 70%);
  animation: cgal-holo 5.5s linear infinite;
  will-change: transform;
}
@keyframes cgal-holo { from { transform: translateX(-80%); } to { transform: translateX(80%); } }
.cgal-hero-info { display: flex; flex-direction: column; gap: 10px; padding: 26px 28px; justify-content: center; min-width: 0; }
.cgal-hero-eyebrow { display: inline-flex; align-items: center; gap: 8px; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: rgba(var(--accent-rgb), 1); }
.cgal-hero.is-limited .cgal-hero-eyebrow { color: #bcb0ff; }
.cgal-hero.is-sup .cgal-hero-eyebrow { color: var(--warn, #ffb454); }
.cgal-hero-eyebrow svg { width: 16px; height: 16px; }
.cgal-hero-kind { margin-left: 4px; font-size: 0.66rem; letter-spacing: 0.06em; color: var(--text-dim, #8b91a1); padding: 2px 8px; border-radius: 999px; background: rgba(255, 255, 255, 0.06); }
.cgal-hero-title { margin: 0; font-size: 1.7rem; font-weight: 800; line-height: 1.12; letter-spacing: -0.02em; color: var(--text, #e7e9ee); }
.cgal-hero-by { font-size: 0.86rem; color: var(--text-dim, #8b91a1); }
.cgal-hero-by a { color: rgba(var(--accent-rgb), 0.95); text-decoration: none; }
.cgal-hero-desc { margin: 0; font-size: 0.92rem; line-height: 1.55; color: var(--text-dim, #8b91a1); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.cgal-hero-meter { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.cgal-hero-bar { height: 7px; border-radius: 999px; background: rgba(255, 255, 255, 0.1); overflow: hidden; }
.cgal-hero-barfill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, #8b7bff, #b9abff); }
.cgal-hero-left { font-size: 0.78rem; font-weight: 600; color: #bcb0ff; font-variant-numeric: tabular-nums; }
.cgal-hero-cta { display: flex; align-items: center; gap: 12px; margin-top: 8px; flex-wrap: wrap; }
.cgal-btn-hero { padding: 13px 26px; font-size: 0.94rem; }

/* ── Spotlight: the hero plus the admin's other featured entries ──
   Only rendered when the catalog features more than one entry; a single
   featured entry keeps the full-width hero above, untouched. The column is
   capped at three cards in JS, so this never grows past the hero's height. */
.cgal-spot { display: grid; grid-template-columns: minmax(0, 2.15fr) minmax(240px, 1fr); gap: 16px; align-items: stretch; margin-bottom: 24px; }
.cgal-spot > .cgal-hero { margin-bottom: 0; }
.cgal-spot-side { display: grid; grid-auto-rows: 1fr; gap: 16px; min-width: 0; }
.cgal-spotcard {
  display: grid; grid-template-columns: 128px minmax(0, 1fr); min-width: 0;
  border-radius: 16px; overflow: hidden; border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
  background: rgba(255, 255, 255, 0.03); transition: border-color 0.18s ease, transform 0.18s ease;
}
.cgal-spotcard:hover { transform: translateY(-2px); border-color: rgba(255, 255, 255, 0.22); }
.cgal-spotcard.is-limited { border-color: rgba(139, 123, 255, 0.34); }
.cgal-spotcard.is-limited:hover { border-color: rgba(139, 123, 255, 0.6); }
.cgal-spotcard.is-sup { border-color: rgba(255, 180, 84, 0.3); }
.cgal-spotcard.is-sup:hover { border-color: rgba(255, 180, 84, 0.55); }
.cgal-spotcard .cgal-media { aspect-ratio: auto; height: 100%; min-height: 96px; }
.cgal-spotcard-body { display: flex; flex-direction: column; justify-content: center; gap: 7px; padding: 13px 15px; min-width: 0; }
.cgal-spotcard-eyebrow { display: inline-flex; align-items: center; gap: 6px; font-size: 0.66rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-dim, #8b91a1); }
.cgal-spotcard-eyebrow svg { width: 13px; height: 13px; }
.cgal-spotcard.is-limited .cgal-spotcard-eyebrow { color: #bcb0ff; }
.cgal-spotcard.is-sup .cgal-spotcard-eyebrow { color: var(--warn, #ffb454); }
.cgal-spotcard-title { font-size: 0.98rem; font-weight: 700; line-height: 1.2; color: var(--text, #e7e9ee); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.cgal-spotcard-cta { gap: 8px; margin-top: 4px; padding-top: 0; }
.cgal-spotcard-cta .cgal-btn { flex: 1; padding: 8px 12px; font-size: 0.78rem; }
.cgal-spotcard-cta .cgal-limcount { text-align: left; }

/* Duo — exactly two featured entries. A lone side card stretched to the hero's
   full height read as broken (a 128px media sliver, crushed text), so both
   entries get the full hero treatment instead: upright, equal width, media on
   top. Scoped to the width where they actually sit side by side; below it the
   spotlight collapse in the 1080px query takes over and the heroes stack in
   their default horizontal shape. */
@media (min-width: 1081px) {
  .cgal-spot.is-duo { grid-template-columns: 1fr 1fr; }
  .cgal-spot.is-duo > .cgal-hero { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .cgal-spot.is-duo .cgal-media-hero { height: auto; min-height: 0; aspect-ratio: 21 / 9; }
  /* The side veil is shaped for media-left/info-right; upright only needs the bottom fade. */
  .cgal-spot.is-duo .cgal-media-hero .cgal-media-veil { background: linear-gradient(180deg, transparent 55%, rgba(6, 8, 10, 0.45) 100%); }
  .cgal-spot.is-duo .cgal-hero-info { padding: 18px 22px 22px; justify-content: flex-start; gap: 9px; }
  .cgal-spot.is-duo .cgal-hero-title { font-size: 1.3rem; }
  .cgal-spot.is-duo .cgal-hero-desc { -webkit-line-clamp: 2; }
  .cgal-spot.is-duo .cgal-btn-hero { padding: 11px 20px; font-size: 0.88rem; }
}

/* ── Section blocks + counts ── */
.cgal-kblock { margin-top: 28px; }
.cgal-kblock:first-child { margin-top: 0; }
.cgal-khead { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 0 2px 14px; }
.cgal-khead-l { display: flex; align-items: center; gap: 9px; }
.cgal-khead-ic { color: rgba(var(--accent-rgb), 1); font-size: 19px; }
.cgal-khead-title { font-size: 1.06rem; font-weight: 800; letter-spacing: -0.01em; color: var(--text, #e7e9ee); }
.cgal-khead-cnt { font-size: 0.72rem; font-weight: 700; color: var(--text-dim, #8b91a1); background: rgba(255, 255, 255, 0.06); padding: 2px 9px; border-radius: 999px; }
.cgal-seeall { display: inline-flex; align-items: center; gap: 4px; background: none; border: 0; cursor: pointer; font-size: 0.82rem; font-weight: 600; color: rgba(var(--accent-rgb), 1); }
.cgal-seeall:hover { text-decoration: underline; }

/* ── Exclusive shelves (Limited + Supporters), on par with each other ── */
.cgal-feat-block { position: relative; margin-top: 26px; padding: 18px 18px 4px; border-radius: 18px; border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1)); }
/* The tier shelves hold their WHOLE tier as a horizontal rail: fixed-width
   cards, native touch pan (finger swipe right-left on the Edge), snap to card
   edges, a quiet scrollbar for the mouse. Vertical page scroll is untouched —
   the browser splits pan axes on its own. */
.cgal-hrail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 232px;
  gap: 16px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  padding: 2px 2px 12px;
}
.cgal-hrail > .cgal-card { scroll-snap-align: start; min-width: 0; }
.cgal-hrail::-webkit-scrollbar { height: 8px; }
.cgal-hrail::-webkit-scrollbar-track { background: transparent; }
.cgal-hrail::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.16);
  border-radius: 4px;
  border: 2px solid transparent;
  background-clip: content-box;
}
:root[data-theme="light"] .cgal-hrail::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.2); background-clip: content-box; }
.cgal-feat-block .cgal-khead { margin-bottom: 4px; }
.cgal-feat-block.is-limited { border-color: rgba(139, 123, 255, 0.3); background: radial-gradient(130% 100% at 100% 0, rgba(139, 123, 255, 0.1), transparent 60%), rgba(139, 123, 255, 0.02); }
.cgal-feat-block.is-limited .cgal-khead-ic { color: #bcb0ff; }
.cgal-feat-block.is-limited .cgal-khead-cnt { color: #cabfff; background: rgba(139, 123, 255, 0.16); }
.cgal-feat-block.is-sup { border-color: rgba(255, 180, 84, 0.3); background: radial-gradient(130% 100% at 100% 0, rgba(255, 180, 84, 0.1), transparent 60%), rgba(255, 180, 84, 0.02); }
.cgal-feat-block.is-sup .cgal-khead-ic { color: var(--warn, #ffb454); }
.cgal-feat-block.is-sup .cgal-khead-cnt { color: #ffd089; background: rgba(255, 180, 84, 0.16); }
/* Archive: the deliberate opposite of the two tier shelves above. It gets the
   same footprint so it still reads as a shelf, but no accent tint and no glow —
   it is history, not stock, and it must not compete with a drop somebody can
   still claim. Its cards already carry .dim from renderCard. */
.cgal-feat-block.is-archive { border-color: var(--glass-border, rgba(255, 255, 255, 0.07)); background: rgba(255, 255, 255, 0.014); }
.cgal-feat-block.is-archive .cgal-khead-title,
.cgal-feat-block.is-archive .cgal-khead-ic { color: var(--text-dim, #8b91a1); }
.cgal-feat-block.is-archive .cgal-khead-cnt { color: var(--text-dim, #8b91a1); background: rgba(255, 255, 255, 0.06); }
.cgal-khead-actions { display: flex; align-items: center; gap: 14px; flex: none; }
.cgal-feat-lead { margin: 0 2px 14px; font-size: 0.84rem; line-height: 1.45; color: var(--text-dim, #8b91a1); }
.cgal-feat-join { flex: none; white-space: nowrap; }
.cgal-feat-block.is-sup .cgal-feat-join { color: #12100a; background: var(--warn, #ffb454); border-color: transparent; font-weight: 700; }
.cgal-feat-block.is-sup .cgal-feat-join:hover { filter: brightness(1.06); }
.cgal-feat-how { color: var(--warn, #ffb454) !important; }
@media (max-width: 680px) {
  .cgal-feat-block { padding: 14px 14px 2px; }
  /* A shelf header is a title on one side and up to three controls on the
     other, and none of them could shrink: on a 390px phone the row measured
     385px of actions next to the title, which made the whole Store 585px wide
     inside a 355px panel. Everything then sat at whatever the sideways scroll
     position happened to be. The controls take their own line here, and the
     supporter button takes the width it needs. */
  .cgal-khead { flex-wrap: wrap; row-gap: 8px; }
  .cgal-khead-l { flex: 1 1 auto; min-width: 0; }
  .cgal-khead-actions { flex: 1 1 100%; flex-wrap: wrap; min-width: 0; gap: 8px 12px; }
  .cgal-feat-join { flex: 1 1 auto; white-space: normal; }
}

/* ── "How it works" supporter perks panel (stacked over the Store) ── */
.cgal-info { width: min(480px, 100%); max-height: 90%; display: flex; flex-direction: column; overflow: hidden;
  border-radius: 20px; background: var(--glass-bg, #14181c); border: 1px solid rgba(255, 180, 84, 0.36);
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.6); animation: cgal-pop 0.22s cubic-bezier(0.2, 0.8, 0.2, 1); }
.cgal-info-mark { flex: none; width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center;
  color: var(--warn, #ffb454); background: rgba(255, 180, 84, 0.16); border: 1px solid rgba(255, 180, 84, 0.34); }
.cgal-info-mark svg { width: 18px; height: 18px; }
.cgal-info-body { overflow-y: auto; padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 14px; }
.cgal-info-lead { margin: 0; font-size: 0.92rem; line-height: 1.55; color: var(--text-soft, #c3c8d2); }
.cgal-info-perks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.cgal-info-perks li { display: flex; align-items: flex-start; gap: 10px; font-size: 0.9rem; line-height: 1.5; color: var(--text, #e7e9ee); }
.cgal-info-tick { flex: none; margin-top: 2px; color: var(--warn, #ffb454); }
.cgal-info-tick svg { width: 16px; height: 16px; }
.cgal-info-note {
  display: flex; flex-direction: column; gap: 8px;
  font-size: 0.82rem; line-height: 1.5; color: var(--text-dim, #8b91a1);
  padding: 12px 14px; border-radius: 12px;
  background: rgba(255, 180, 84, 0.08); border: 1px solid rgba(255, 180, 84, 0.24);
}
.cgal-info-mail {
  align-self: flex-start; font-family: ui-monospace, monospace; font-size: 0.82rem; font-weight: 600;
  color: var(--warn, #ffb454); text-decoration: none;
  padding: 6px 11px; border-radius: 8px; background: rgba(255, 180, 84, 0.14); border: 1px solid rgba(255, 180, 84, 0.34);
}
.cgal-info-mail:hover { background: rgba(255, 180, 84, 0.22); }
.cgal-info-cta { display: flex; flex-direction: column; gap: 10px; margin-top: 2px; }
.cgal-info-cta .cgal-btn { width: 100%; }
.cgal-info-bmc { color: #12100a; background: var(--warn, #ffb454); border-color: transparent; font-weight: 700; }
.cgal-info-bmc:hover { filter: brightness(1.06); background: var(--warn, #ffb454); }

/* ── Load-more, status, skeleton ── */
.cgal-loadmore { display: flex; justify-content: center; margin: 24px 0 6px; }
.cgal-loadmore-btn { padding: 11px 30px; }
.cgal-status { padding: 44px 6px; text-align: center; font-size: 0.9rem; color: var(--text-dim, #8b91a1); }
.cgal-stale { padding: 12px 6px 0; }
.cgal-skel { pointer-events: none; }
.cgal-skel:hover { transform: none; box-shadow: none; border-color: var(--glass-border, rgba(255, 255, 255, 0.1)); }
.cgal-skel-media { aspect-ratio: 16 / 10; }
/* Skeleton shimmer sweeps via transform (compositor-only) — animating
   background-position recomputes style + repaints every frame while the
   skeletons are up (GitHub #99). The 400%-wide pseudo carries the gradient at
   natural size and slides -75%→0, covering the element at all times: same look
   as the old 100%→0 background-position sweep. */
.cgal-skel-media, .cgal-skel-line, .cgal-skel-btn { position: relative; overflow: hidden; }
.cgal-skel-media::after, .cgal-skel-line::after, .cgal-skel-btn::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 400%; pointer-events: none;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0.04) 25%, rgba(255, 255, 255, 0.09) 37%, rgba(255, 255, 255, 0.04) 63%);
  animation: cgal-shimmer 1.4s ease infinite;
  will-change: transform;
}
.cgal-skel-line { height: 12px; border-radius: 6px; margin: 4px 0; }
.cgal-skel-line.w70 { width: 70%; }
.cgal-skel-line.w40 { width: 40%; }
.cgal-skel-line.w90 { width: 90%; }
.cgal-skel-btn { height: 38px; border-radius: 11px; margin-top: 12px; }
@keyframes cgal-shimmer { from { transform: translateX(-75%); } to { transform: translateX(0); } }

/* Below this the column would squeeze both halves: the featured cards drop under
   the hero as a row instead, still one block, still ahead of everything else. */
@media (max-width: 1080px) {
  .cgal-spot { grid-template-columns: 1fr; }
  .cgal-spot-side { grid-auto-rows: auto; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
}
@media (max-width: 680px) {
  .cgal-hero { grid-template-columns: 1fr; }
  .cgal-media-hero { min-height: 190px; aspect-ratio: 16 / 9; }
  .cgal-spotcard { grid-template-columns: 104px minmax(0, 1fr); }
  .cgal-hero-title { font-size: 1.4rem; }
  .cgal-grid { grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 12px; }
  .cgal-hrail { grid-auto-columns: 188px; gap: 12px; }
  /* Too narrow to sit side by side — back to the stacked card. */
  .cgal-grid.is-solo > .cgal-card { flex-direction: column; }
  .cgal-grid.is-solo > .cgal-card > .cgal-media { flex: none; aspect-ratio: 16 / 10; min-height: 0; }
  .cgal-grid.is-solo > .cgal-card > .cgal-body { padding: 13px 14px 14px; gap: 6px; }
  .cgal-grid.is-solo .cgal-name { font-size: 0.98rem; }
  .cgal-grid.is-solo .cgal-desc { font-size: 0.82rem; -webkit-line-clamp: 3; }
  .cgal-brand-sub, .cgal-trust { display: none; }
  .cgal-brand-title { font-size: 1.12rem; }
}
@media (prefers-reduced-motion: reduce) {
  .cgal-card, .cgal-media canvas, .cgal-shots, .cgal-preview { transition: none !important; }
  .cgal-card:hover .cgal-media canvas, .cgal-card:hover .cgal-shots, .cgal-card:hover .cgal-preview { transform: none; }
  .cgal-skel-media, .cgal-skel-line, .cgal-skel-btn, .cgal-hero.is-limited .cgal-media-hero::after { animation: none; }
}

/* ── Clickable cards/hero → detail view ── */
.cgal-clickable { cursor: pointer; }
.cgal-clickable:focus-visible { outline: 2px solid rgba(var(--accent-rgb), 0.7); outline-offset: 2px; }

/* ── Detail view: stacked overlay over the store grid ── */
.cgal-detail-scrim {
  position: absolute; inset: 0; z-index: 20;
  display: flex; align-items: center; justify-content: center; padding: 3vh 2.4vw;
  background: rgba(4, 6, 9, 0.62); backdrop-filter: blur(7px);
  animation: cgal-fade 0.18s ease;
}
@keyframes cgal-fade { from { opacity: 0; } to { opacity: 1; } }
.cgal-detail {
  width: min(940px, 100%); max-height: 92%;
  display: flex; flex-direction: column; overflow: hidden;
  border-radius: 20px; background: var(--glass-bg, #14181c);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.6);
  animation: cgal-pop 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
}
@keyframes cgal-pop { from { opacity: 0; transform: scale(0.97) translateY(8px); } to { opacity: 1; transform: none; } }
.cgal-detail.is-limited { border-color: rgba(139, 123, 255, 0.4); }
.cgal-detail.is-sup { border-color: rgba(255, 180, 84, 0.36); }
.cgal-detail-head {
  display: flex; align-items: center; gap: 12px; flex: none; padding: 12px 14px;
  border-bottom: 1px solid var(--glass-border, rgba(255, 255, 255, 0.08));
}
.cgal-detail-htitle { flex: 1; min-width: 0; font-size: 1.04rem; font-weight: 800; letter-spacing: -0.01em; color: var(--text, #e7e9ee); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cgal-detail-body { flex: 1; overflow-y: auto; display: grid; grid-template-columns: 1.25fr 1fr; gap: 22px; padding: 20px; align-items: start; }

/* Gallery */
.cgal-gal { display: flex; flex-direction: column; gap: 10px; min-width: 0; position: sticky; top: 0; }
.cgal-gal-stage {
  position: relative; aspect-ratio: 16 / 10; overflow: hidden; border-radius: 14px;
  background: rgba(0, 0, 0, 0.42); border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
}
.cgal-gal-track { display: flex; height: 100%; transition: transform 0.35s cubic-bezier(0.2, 0.8, 0.2, 1); }
.cgal-gal-slide { flex: 0 0 100%; height: 100%; }
.cgal-gal-slide img { width: 100%; height: 100%; object-fit: cover; display: block; cursor: zoom-in; }
.cgal-gal-frame { width: 100%; height: 100%; border: 0; display: block; }
.cgal-gal-stage > canvas { width: 100%; height: 100%; display: block; }
.cgal-gal-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  color: #fff; background: rgba(8, 10, 14, 0.6); border: 1px solid rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(6px); transition: background 0.15s ease;
}
.cgal-gal-arrow:hover { background: rgba(8, 10, 14, 0.85); }
.cgal-gal-arrow svg { width: 18px; height: 18px; }
.cgal-gal-prev { left: 10px; }
.cgal-gal-next { right: 10px; }
.cgal-gal-next svg { transform: rotate(180deg); }
.cgal-gal-zoom {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; cursor: pointer;
  color: #fff; background: rgba(8, 10, 14, 0.6); border: 1px solid rgba(255, 255, 255, 0.18); backdrop-filter: blur(6px);
}
.cgal-gal-zoom:hover { background: rgba(8, 10, 14, 0.85); }
.cgal-gal-zoom svg { width: 17px; height: 17px; }
.cgal-gal-count {
  position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); z-index: 3;
  font-size: 0.72rem; font-weight: 700; color: #fff; font-variant-numeric: tabular-nums;
  padding: 3px 10px; border-radius: 999px; background: rgba(8, 10, 14, 0.6); backdrop-filter: blur(6px);
}
.cgal-gal-thumbs { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
.cgal-gal-thumbs::-webkit-scrollbar { display: none; }
.cgal-gal-thumb {
  flex: 0 0 66px; height: 42px; padding: 0; overflow: hidden; cursor: pointer;
  border-radius: 8px; background: rgba(0, 0, 0, 0.4);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
  opacity: 0.6; transition: opacity 0.15s ease, border-color 0.15s ease;
}
.cgal-gal-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cgal-gal-thumb:hover { opacity: 0.85; }
.cgal-gal-thumb.on { opacity: 1; border-color: rgba(var(--accent-rgb), 0.7); }

/* Info column */
.cgal-detail-info { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.cgal-detail-tier {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.72rem; font-weight: 700; color: var(--text, #e7e9ee);
  padding: 5px 11px 5px 9px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.06); border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.16));
}
.cgal-detail-tier svg { width: 14px; height: 14px; }
.cgal-detail-tier.t-limited { color: #cabfff; border-color: rgba(139, 123, 255, 0.55); background: rgba(139, 123, 255, 0.14); }
.cgal-detail-tier.t-sup { color: #ffd089; border-color: rgba(255, 180, 84, 0.5); background: rgba(255, 180, 84, 0.12); }
.cgal-detail-name { margin: 0; font-size: 1.5rem; font-weight: 800; line-height: 1.15; letter-spacing: -0.02em; color: var(--text, #e7e9ee); }
.cgal-detail-by { font-size: 0.86rem; color: var(--text-dim, #8b91a1); }
.cgal-detail-by a { color: rgba(var(--accent-rgb), 0.95); text-decoration: none; }
.cgal-detail-by a:hover { text-decoration: underline; }
.cgal-detail-meta { display: flex; flex-wrap: wrap; gap: 6px; }
/* "What's new in v1.2.0" + the publisher's own line. */
.cgal-detail-changelog {
  display: flex; flex-direction: column; gap: 3px;
  margin-top: 10px; padding: 9px 12px; border-radius: 10px;
  background: rgba(var(--accent-rgb), 0.08);
  border: 1px solid rgba(var(--accent-rgb), 0.2);
}
.cgal-changelog-label {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--accent, #35e08e);
}
.cgal-changelog-text { font-size: 0.82rem; line-height: 1.45; color: var(--text, #e7e9ee); overflow-wrap: anywhere; }
.cgal-metachip { font-size: 0.72rem; font-weight: 600; color: var(--text-dim, #8b91a1); padding: 3px 10px; border-radius: 999px; background: rgba(255, 255, 255, 0.06); }
.cgal-detail-desc { margin: 0; font-size: 0.92rem; line-height: 1.6; color: var(--text-soft, #c3c8d2); }
.cgal-detail-swatches { display: flex; flex-direction: column; gap: 7px; }
.cgal-detail-sw { display: flex; align-items: center; gap: 9px; }
.cgal-detail-sw .preset-swatch-dot { width: 20px; height: 20px; }
.cgal-detail-sw-hex { font-family: ui-monospace, monospace; font-size: 0.8rem; letter-spacing: 0.02em; color: var(--text-dim, #8b91a1); text-transform: uppercase; }
.cgal-detail-cta { display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.cgal-detail-cta .cgal-btn { width: 100%; }
.cgal-detail-cta .cgal-hero-meter { margin: 0 0 2px; }
/* "Become a supporter" beside the unlock button (locked entries, in the detail
   view and the featured hero). Reuses the warm heart CTA (.cgal-info-bmc) but a
   step quieter, so the unlock stays the primary action. */
.cgal-support-cta { font-size: 0.84rem; opacity: 0.94; }
.cgal-support-cta:hover { opacity: 1; }
.cgal-support-cta .cgal-ic { width: 15px; height: 15px; }

/* Fullscreen zoom */
.cgal-zoom {
  position: fixed; inset: 0; z-index: 4000; display: flex; align-items: center; justify-content: center; padding: 4vmin;
  background: rgba(2, 4, 7, 0.9); backdrop-filter: blur(8px); animation: cgal-fade 0.16s ease;
}
.cgal-zoom-img { max-width: min(1200px, 94vw); max-height: 88vh; border-radius: 12px; box-shadow: 0 30px 90px rgba(0, 0, 0, 0.7); }
.cgal-zoom-arrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 52px; height: 52px; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  color: #fff; background: rgba(12, 16, 22, 0.72); border: 1px solid rgba(255, 255, 255, 0.2);
}
.cgal-zoom-arrow:hover { background: rgba(12, 16, 22, 0.95); }
.cgal-zoom-arrow svg { width: 22px; height: 22px; }
.cgal-zoom-prev { left: 3vmin; }
.cgal-zoom-next { right: 3vmin; }
.cgal-zoom-next svg { transform: rotate(180deg); }
.cgal-zoom.single .cgal-zoom-arrow { display: none; }
.cgal-zoom-x {
  position: absolute; top: 3vmin; right: 3vmin; z-index: 2;
  width: 44px; height: 44px; border-radius: 50%; display: grid; place-items: center; cursor: pointer;
  color: #fff; background: rgba(12, 16, 22, 0.72); border: 1px solid rgba(255, 255, 255, 0.2);
}
.cgal-zoom-x:hover { background: rgba(12, 16, 22, 0.95); }
.cgal-zoom-x svg { width: 18px; height: 18px; }

@media (max-width: 720px) {
  .cgal-detail-body { grid-template-columns: 1fr; gap: 16px; }
  .cgal-gal { position: static; }
  .cgal-detail-name { font-size: 1.3rem; }
}
@media (prefers-reduced-motion: reduce) {
  .cgal-detail-scrim, .cgal-detail, .cgal-zoom { animation: none; }
  .cgal-gal-track { transition: none; }
}

/* ── Import preview: theme colour swatches + animated-background mini-preview. ── */
.preset-theme-swatches { display: flex; flex-wrap: wrap; gap: 10px 16px; margin: 0 0 12px; }
/* Distinct class from the round `.preset-swatch` accent dot on quick-preset
   buttons (above) — this is a dot+label row; sharing the name inherited that
   fixed 22px circle and collapsed the labels on top of each other. */
.preset-theme-sw { display: inline-flex; align-items: center; gap: 7px; font-size: 0.8rem; color: var(--muted-text, #aeb3bd); }
.preset-swatch-dot {
  width: 18px; height: 18px; border-radius: 6px; flex: none;
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.18));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
}
.preset-swatch-label { color: var(--text, #e7e9ee); }
.preset-bg-preview {
  width: 100%; height: 140px; margin: 0 0 12px; border: 0; border-radius: 12px;
  background: #05070d; box-shadow: inset 0 0 0 1px var(--glass-border, rgba(255, 255, 255, 0.12));
  pointer-events: none;
}

/* ── Icon packs: the builder's added-icons list and the import thumbnail grid. ── */
.preset-iconpack-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 12px; }
.preset-iconpack-item { display: inline-flex; align-items: center; gap: 6px; }
.preset-iconpack-item img { width: 18px; height: 18px; object-fit: contain; flex: none; }
.preset-iconpack-del {
  flex: none; width: 18px; height: 18px; padding: 0; font-size: 13px; line-height: 1;
  color: var(--muted-text, #aeb3bd); background: transparent; border: 0; border-radius: 6px; cursor: pointer;
}
.preset-iconpack-del:hover { color: var(--danger, #ff6b6b); background: rgba(255, 255, 255, 0.06); }
.preset-iconpack-grid { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.preset-iconpack-thumb {
  width: 28px; height: 28px; object-fit: contain; flex: none; padding: 5px; box-sizing: content-box;
  background: rgba(255, 255, 255, 0.05); border-radius: 9px;
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12));
}

/* ── Code-locked theme sharing: the "protect" panel, the generated codes list,
   and the unlock field on import. ──────────────────────────────────────── */
.preset-lock-section { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1)); }
.preset-lock-toggle { width: 100%; }
.preset-lock-toggle.is-open { color: var(--accent, #35e08e); border-color: rgba(var(--accent-rgb, 53, 224, 142), 0.35); }
.preset-lock-form { margin-top: 12px; }
.preset-lock-count { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 0.85rem; color: var(--text, #e7e9ee); margin-bottom: 4px; }
.preset-lock-count-input {
  flex: none; width: 76px; box-sizing: border-box; text-align: center;
  padding: 7px 9px; font: inherit; font-size: 0.85rem;
  color: var(--text, #e7e9ee); background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12)); border-radius: 9px;
}
.preset-locked-chip { color: var(--warn, #ffb454); background: rgba(255, 180, 84, 0.14); border-color: rgba(255, 180, 84, 0.32); }
.preset-lock-codes-head { margin: 14px 0 8px; font-weight: 700; color: var(--text, #e7e9ee); }
.preset-lock-codes { display: flex; flex-direction: column; gap: 6px; max-height: 40vh; overflow-y: auto; }
.preset-lock-code-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 8px 6px 10px; border-radius: 9px;
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.1));
}
.preset-lock-code-idx { flex: none; width: 1.6em; text-align: right; font-size: 0.78rem; color: var(--text-dim, #8b91a1); }
.preset-lock-code-val { flex: 1 1 auto; min-width: 0; font-family: ui-monospace, monospace; font-size: 0.88rem; letter-spacing: 0.04em; color: var(--text, #e7e9ee); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.preset-lock-code-copy { flex: none; padding: 5px 11px; font-size: 0.78rem; }
.preset-lock-note { margin-top: 12px; font-size: 0.8rem; color: var(--warn, #ffb454); }
.preset-unlock-wrap { margin-top: 10px; }
.preset-unlock-label { display: flex; flex-direction: column; gap: 5px; font-size: 0.85rem; color: var(--text, #e7e9ee); }
.preset-unlock-field {
  width: 100%; box-sizing: border-box;
  padding: 9px 11px; font: inherit; font-size: 0.9rem; font-family: ui-monospace, monospace; letter-spacing: 0.04em;
  color: var(--text, #e7e9ee); background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.12)); border-radius: 10px;
}
.preset-unlock-field:focus { outline: none; border-color: rgba(var(--accent-rgb, 53, 224, 142), 0.5); }
.preset-unlock-note { margin-top: 7px; font-size: 0.76rem; line-height: 1.45; color: var(--text-dim, rgba(231, 233, 238, 0.55)); }

/* ── "Widgets & sharing" hub: intro + two explainer sub-cards ─────────────
   Groups the code-that-extends (community widgets) and the data-you-share
   (themes/pages/Deck) in one category, clearly told apart. */
.settings-wshub-body { padding: 10px; display: grid; gap: 10px; }

.settings-wshub-intro {
  margin: 0; padding: 10px 12px; border-radius: 11px;
  border: 1px solid rgba(255,255,255,0.07);
  background: rgba(255,255,255,0.03);
  color: var(--muted-text); font-size: 11.5px; font-weight: 700; line-height: 1.5;
}

.settings-subcard {
  border: 1px solid rgba(255,255,255,0.08); border-radius: 13px;
  background: rgba(255,255,255,0.028); padding: 12px;
  display: grid; gap: 11px;
}
.settings-subcard-head { display: flex; align-items: flex-start; gap: 11px; }
.settings-subcard-ico {
  flex: none; width: 34px; height: 34px; border-radius: 10px;
  display: grid; place-items: center; font-size: 17px; line-height: 1;
  border: 1px solid rgba(255,255,255,0.10); background: rgba(255,255,255,0.05);
}
.settings-subcard-ico--ext {
  background: rgba(var(--accent-rgb),0.14); border-color: rgba(var(--accent-rgb),0.34);
}
.settings-subcard-ico--create {
  background: rgba(255,177,84,0.14); border-color: rgba(255,177,84,0.4);
}
.settings-subcard-ico--share {
  background: rgba(86,138,242,0.16); border-color: rgba(86,138,242,0.42);
}
.settings-subcard-titles { display: grid; gap: 2px; min-width: 0; flex: 1; }
.settings-subcard-titles b { font-size: 13px; font-weight: 900; color: var(--text); }
.settings-subcard-badge {
  flex: none; align-self: center;
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px;
  color: rgba(var(--accent-rgb),1); background: rgba(var(--accent-rgb),0.14);
  border: 1px solid rgba(var(--accent-rgb),0.3);
}

/* Store — the featured entry point to the community catalog. Deliberately
   larger and accent-lit so it reads as the hero of this section, sitting above
   the quieter Create / Community-widget / Limited / Share subcards. */
.settings-store-hero {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 15px;
  padding: 16px 18px; border-radius: 16px;
  border: 1px solid rgba(var(--accent-rgb),0.34);
  background:
    linear-gradient(135deg, rgba(var(--accent-rgb),0.16), rgba(var(--accent-rgb),0.04) 62%),
    rgba(255,255,255,0.03);
}
.settings-store-hero-glow {
  position: absolute; top: -46%; right: -14%; width: 240px; height: 240px;
  border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(var(--accent-rgb),0.26), transparent 68%);
}
.settings-store-hero-ico {
  position: relative; flex: none; width: 52px; height: 52px; border-radius: 14px;
  display: grid; place-items: center; color: rgba(var(--accent-rgb),1);
  background: rgba(var(--accent-rgb),0.16); border: 1px solid rgba(var(--accent-rgb),0.4);
}
/* No `fill` here: this selector is more specific than .store-glyph, so setting
   one would win and fill the outline bag solid. */
.settings-store-hero-ico svg { width: 27px; height: 27px; }
.settings-store-hero-body { position: relative; display: grid; gap: 3px; min-width: 0; flex: 1; }
.settings-store-hero-eyebrow {
  font-size: 9.5px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(var(--accent-rgb),1);
}
.settings-store-hero-title { font-size: 18px; font-weight: 900; color: var(--text); line-height: 1.1; }
.settings-store-hero-cta { position: relative; flex: none; white-space: nowrap; }

@media (max-width: 560px) {
  .settings-store-hero { flex-wrap: wrap; }
  .settings-store-hero-cta { width: 100%; }
}

/* numbered "how it works" steps with accent counter chips */
.settings-howto-block { display: grid; gap: 6px; }
.settings-howto-label {
  font-size: 10px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted-text);
}
.settings-howto { list-style: none; margin: 0; padding: 0; counter-reset: howto; display: grid; gap: 6px; }
.settings-howto li {
  counter-increment: howto; position: relative; padding-left: 26px;
  font-size: 11.5px; font-weight: 700; line-height: 1.45; color: var(--text);
}
.settings-howto li::before {
  content: counter(howto); position: absolute; left: 0; top: 0;
  width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center;
  font-size: 10px; font-weight: 800;
  color: rgba(var(--accent-rgb),1); background: rgba(var(--accent-rgb),0.14);
  border: 1px solid rgba(var(--accent-rgb),0.32);
}
.settings-howto-text { margin: 0; line-height: 1.5; }

.settings-inline-link {
  display: inline-block; font-size: 11.5px; font-weight: 800;
  color: rgba(var(--accent-rgb),1); text-decoration: none;
}
.settings-inline-link:hover { text-decoration: underline; }
.settings-howto-links { display: flex; flex-wrap: wrap; gap: 4px 16px; }

/* security callout — subtle, with a left accent rule */
.settings-safenote {
  margin: 0; padding: 9px 11px 9px 12px; border-radius: 10px;
  border: 1px solid rgba(255,255,255,0.06);
  border-left: 2px solid rgba(var(--accent-rgb),0.5);
  background: rgba(var(--accent-rgb),0.045); line-height: 1.5;
}

/* "moved to Widgets & sharing" pointer (shown under Appearance) */
.settings-pointer-row {
  width: 100%; display: flex; align-items: center; gap: 11px;
  padding: 11px 13px; border: 0; background: none; cursor: pointer;
  text-align: left; color: var(--text); font: inherit;
}
.settings-pointer-row:hover { background: rgba(var(--accent-rgb),0.06); }
.settings-pointer-ico {
  flex: none; width: 30px; height: 30px; border-radius: 9px;
  display: grid; place-items: center; font-size: 15px;
  background: rgba(86,138,242,0.16); border: 1px solid rgba(86,138,242,0.42);
}
.settings-pointer-txt { display: grid; gap: 2px; flex: 1; min-width: 0; }
.settings-pointer-txt b { font-size: 12.5px; font-weight: 850; }
.settings-pointer-arrow { flex: none; color: var(--muted-text); font-size: 16px; font-weight: 700; }

/* ── Persistent AI memory viewer (Settings → Xenon AI) ─────────────────────── */
.settings-memory-manage {
  margin-top: 10px; display: grid; gap: 10px;
  padding: 12px; border-radius: 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.07);
}
.settings-memory-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; max-height: 220px; overflow-y: auto; }
.settings-memory-item {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 10px; border-radius: 9px;
  background: rgba(var(--accent-rgb),0.06);
  border: 1px solid rgba(var(--accent-rgb),0.14);
}
.settings-memory-text { flex: 1; min-width: 0; font-size: 12.5px; line-height: 1.35; word-break: break-word; }
.settings-memory-del {
  flex: none; width: 24px; height: 24px; border-radius: 7px;
  display: grid; place-items: center; cursor: pointer;
  font-size: 16px; line-height: 1; color: var(--muted-text);
  background: transparent; border: 1px solid transparent;
  transition: color .15s ease, background .15s ease, border-color .15s ease;
}
.settings-memory-del:hover { color: var(--color-danger); background: var(--danger-bg); border-color: rgba(var(--danger-rgb),0.35); }
.settings-memory-empty { margin: 0; font-size: 12px; color: var(--muted-text); line-height: 1.4; }
.settings-memory-actions { display: flex; justify-content: flex-end; }

/* ── Sostieni Xenon (support category) ─────────────────────────
   The one page allowed to be warm and loud: a donation hero and a Discord
   card, both with a single unmistakable call to action. */
.settings-support-group {
  background: transparent;
  border: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow: visible;
}
.support-hero {
  border-radius: 16px;
  padding: 22px 20px;
  text-align: center;
  background: linear-gradient(160deg, rgba(255,77,141,0.16), rgba(255,77,141,0.05) 60%, transparent);
  border: 1px solid rgba(255,77,141,0.28);
}
.support-hero-heart { width: 34px; height: 34px; margin: 0 auto 8px; color: #ff4d8d; }
.support-hero-heart svg { width: 100%; height: 100%; filter: drop-shadow(0 4px 14px rgba(255,77,141,0.45)); }
.support-hero-title { font-size: 18px; font-weight: 900; letter-spacing: 0.01em; }
.support-hero-lead {
  margin: 6px auto 14px;
  max-width: 520px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted-text);
}
.support-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 44px;
  padding: 10px 22px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 800;
  text-decoration: none;
  transition: transform .12s ease, background .15s ease;
}
.support-cta:active { transform: scale(0.97); }
.support-cta svg { width: 18px; height: 18px; }
.support-cta-coffee { background: #ff4d8d; color: #fff; box-shadow: 0 8px 24px rgba(255,77,141,0.35); }
.support-cta-coffee:hover { background: #ff5f99; }
.support-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  border-radius: 16px;
}
.support-card-discord { background: rgba(88,101,242,0.12); border: 1px solid rgba(88,101,242,0.3); }
.support-card-ico { width: 30px; height: 30px; flex: 0 0 auto; color: #7784f5; }
.support-card-ico svg { width: 100%; height: 100%; }
.support-card-body { flex: 1 1 auto; min-width: 0; }
.support-card-title { font-size: 14px; font-weight: 800; }
.support-card-lead { margin: 3px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--muted-text); }
.support-cta-discord { background: #5865F2; color: #fff; flex: 0 0 auto; padding: 10px 16px; font-size: 13px; }
.support-cta-discord:hover { background: #6b77f4; }
.support-links { display: flex; gap: 10px; flex-wrap: wrap; }
.support-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-radius: 10px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--muted-text);
  text-decoration: none;
  border: 1px solid rgba(255,255,255,0.1);
  background: rgba(255,255,255,0.04);
}
.support-link:hover { color: var(--text); background: rgba(255,255,255,0.08); }
.support-link svg { width: 15px; height: 15px; }
@media (max-width: 640px) {
  .support-card { flex-direction: column; text-align: center; }
}

/* ── 2026-07 reorg: breathing room ─────────────────────────────
   Slightly airier groups on regular displays. Scoped to taller viewports so
   the Xeneon Edge short-screen tuning (max-height:620 above) keeps winning. */
@media (min-height: 621px) {
  .settings-content { gap: 12px; }
  .settings-group-head { padding: 11px 16px 9px; font-size: 14px; }
  .settings-group-head .settings-hint { font-size: 11.5px; }
  .settings-grid { padding: 13px 16px 15px; gap: 9px; }
}

/* ── Static background picker (Settings → Sfondo) ───────────────
   Four preview tiles that render the actual static-background looks (they read
   --accent-rgb, so they tint with the user's accent). Selecting one supersedes
   the animated aurora group below, which dims via .is-superseded. */
.bgstatic-picker {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  padding: 10px 12px 12px;
}
.bgstatic-option {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-dim, #9aa6b6);
  font: inherit;
}
.bgstatic-prev {
  aspect-ratio: 16 / 11;
  border-radius: 9px;
  border: 2px solid rgba(255, 255, 255, 0.10);
  overflow: hidden;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.12s ease;
}
.bgstatic-option:hover .bgstatic-prev { transform: translateY(-1px); }
.bgstatic-option[aria-pressed="true"] .bgstatic-prev {
  border-color: rgb(var(--accent-rgb));
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.25);
}
.bgstatic-option[aria-pressed="true"] { color: var(--text); }
.bgstatic-option:focus-visible .bgstatic-prev {
  outline: 2px solid rgb(var(--accent-rgb));
  outline-offset: 2px;
}
.bgstatic-name {
  font-size: 11.5px;
  font-weight: 600;
  text-align: center;
}
/* Preview compositions — compact echoes of the real #bg-static layers. */
.bgstatic-prev.none {
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.02)),
    var(--panel, #12161d);
}
.bgstatic-prev.nebulosa {
  background:
    radial-gradient(120% 120% at 20% 8%, rgba(var(--accent-rgb), 0.75), transparent 60%),
    radial-gradient(100% 100% at 92% 96%, rgba(var(--accent-rgb), 0.34), transparent 62%),
    linear-gradient(180deg, #0b0e13, #070a0e);
}
.bgstatic-prev.prisma {
  background:
    radial-gradient(85% 85% at 8% 12%, rgba(var(--accent-rgb), 0.78), transparent 55%),
    radial-gradient(80% 80% at 92% 8%, rgba(132, 92, 255, 0.62), transparent 55%),
    radial-gradient(90% 90% at 82% 96%, rgba(40, 185, 235, 0.5), transparent 55%),
    linear-gradient(135deg, #0a0d13, #0c0910);
}
.bgstatic-prev.halo {
  background:
    radial-gradient(72% 82% at 70% 24%, rgba(var(--accent-rgb), 0.85), rgba(var(--accent-rgb), 0.14) 34%, transparent 66%),
    linear-gradient(180deg, #090b0f, #050608);
}

/* Aurora group is superseded while a static style is active. */
.settings-fx-group.is-superseded .settings-grid { opacity: 0.45; }
.settings-superseded-note { color: rgb(var(--accent-rgb)); }

/* (Community gallery toolbar styles moved into the premium storefront block above.) */

/* ── Catalog "new drop" nudge modal (js/catalog-drop.js) ─────────────────────
   A dismissible promo card for a fresh PAID tier (Supporters / Limited). Liquid
   glass, per-tier accent (gold = supporters, violet = limited), sized and
   touch-tuned for the Xeneon Edge. Themed via the same tokens as the Store. */
.xdrop-overlay {
  position: fixed; inset: 0; z-index: 9000;
  display: flex; align-items: center; justify-content: center; padding: 4vh 4vw;
  background: rgba(5, 7, 11, 0.62); backdrop-filter: blur(4px);
  animation: xdrop-fade 0.3s ease;
}
.xdrop-overlay.closing { animation: xdrop-fade 0.2s ease reverse; }
@keyframes xdrop-fade { from { opacity: 0; } to { opacity: 1; } }

.xdrop-card {
  --xd: 255, 180, 84;                 /* supporters gold (default) */
  --xd-ink: #241701;
  position: relative; width: min(430px, 96vw); max-height: 92vh; overflow: hidden;
  display: flex; flex-direction: column;
  border-radius: 22px;
  background:
    linear-gradient(180deg, rgba(var(--xd), 0.14), transparent 34%),
    var(--glass-bg, #14181c);
  border: 1px solid rgba(var(--xd), 0.4);
  box-shadow: 0 40px 90px -28px rgba(0, 0, 0, 0.78), 0 1px 0 rgba(255, 255, 255, 0.08) inset;
  animation: xdrop-pop 0.42s cubic-bezier(0.16, 1, 0.3, 1);
}
.xdrop-card.is-limited { --xd: 139, 123, 255; --xd-ink: #160a2b; }
@keyframes xdrop-pop { from { opacity: 0; transform: translateY(14px) scale(0.96); } to { opacity: 1; transform: none; } }
/* Accent halo along the top edge */
.xdrop-card::before {
  content: ""; position: absolute; left: 50%; top: -42%; width: 120%; height: 80%;
  transform: translateX(-50%);
  background: radial-gradient(60% 100% at 50% 0%, rgba(var(--xd), 0.5), transparent 70%);
  opacity: 0.5; pointer-events: none;
}

.xdrop-x {
  position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; cursor: pointer;
  color: var(--text, #e7e9ee); background: rgba(8, 10, 14, 0.5);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.14)); backdrop-filter: blur(6px);
  transition: background 0.15s ease;
}
.xdrop-x:hover { background: rgba(8, 10, 14, 0.8); }

.xdrop-media {
  position: relative; height: 156px; flex: none; overflow: hidden;
  border-bottom: 1px solid var(--glass-border, rgba(255, 255, 255, 0.09));
}
.xdrop-shot { width: 100%; height: 100%; object-fit: cover; display: block; }
.xdrop-media-veil { position: absolute; inset: 0; background: linear-gradient(180deg, transparent 52%, var(--glass-bg, #14181c)); pointer-events: none; }
.xdrop-pill {
  position: absolute; left: 14px; top: 13px; z-index: 2;
  display: inline-flex; align-items: center;
  padding: 6px 12px; border-radius: 999px;
  font-size: 0.68rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--xd-ink); background: rgb(var(--xd));
  box-shadow: 0 6px 18px -6px rgba(var(--xd), 0.8);
}

/* `min-height: 0` is what makes the `overflow-y` real. Without it this flex item
   refuses to shrink below its content, so on a short viewport the card (which is
   `overflow: hidden`) simply cut the body off instead of scrolling it. */
.xdrop-body { padding: 16px 20px 18px; display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.xdrop-kicker {
  display: inline-flex; align-items: center; gap: 7px; align-self: flex-start;
  font-size: 0.74rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  color: rgb(var(--xd)); margin-bottom: 6px;
}
.xdrop-kicker svg { width: 14px; height: 14px; }
.xdrop-title { margin: 0 0 6px; font-size: 1.4rem; line-height: 1.16; letter-spacing: -0.02em; font-weight: 800; color: var(--text, #e7e9ee); text-wrap: balance; }
.xdrop-sub { margin: 0; font-size: 0.92rem; line-height: 1.5; color: var(--text-soft, #c3c8d2); }

.xdrop-meter { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.xdrop-bar { height: 8px; border-radius: 999px; background: rgba(255, 255, 255, 0.1); overflow: hidden; }
.xdrop-barfill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, rgba(var(--xd), 0.7), rgb(var(--xd))); box-shadow: 0 0 14px rgba(var(--xd), 0.6); }
.xdrop-left { font-size: 0.78rem; font-weight: 600; color: rgba(var(--xd), 1); font-variant-numeric: tabular-nums; }

/* `flex: none` on both: they are the two things in the card that must keep their
   size. A flex item shrinks by default, so on a phone the list above them took
   the space and these two were squeezed toward zero height and PAINTED OVER it —
   the CTA sitting across a drop's name, the opt-out across another. */
.xdrop-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; flex: none; }
.xdrop-btn {
  appearance: none; border: 0; cursor: pointer; font-family: inherit;
  border-radius: 14px; font-weight: 700; letter-spacing: -0.01em;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  transition: transform 0.12s ease, filter 0.18s ease, box-shadow 0.2s ease, background 0.15s ease;
}
.xdrop-btn:active { transform: translateY(1px) scale(0.995); }
.xdrop-primary {
  height: 50px; font-size: 1rem; color: var(--xd-ink);
  background: linear-gradient(180deg, rgb(var(--xd)), rgba(var(--xd), 0.82));
  box-shadow: 0 12px 26px -10px rgba(var(--xd), 0.8), 0 1px 0 rgba(255, 255, 255, 0.35) inset;
}
.xdrop-primary:hover { filter: brightness(1.06); }
.xdrop-ghost {
  height: 44px; font-size: 0.9rem; font-weight: 600; color: var(--text, #e7e9ee);
  background: transparent; border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.16));
}
.xdrop-ghost:hover { background: rgba(255, 255, 255, 0.06); }

.xdrop-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  /* Wraps rather than squashing: the opt-out label is a full sentence in every
     language, and at 390px it and "Maybe later" do not share one line. */
  flex-wrap: wrap; row-gap: 6px;
  flex: none;
  margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--glass-border, rgba(255, 255, 255, 0.09));
}
.xdrop-dontshow { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; user-select: none; color: var(--text-dim, #8b91a1); font-size: 0.8rem; }
.xdrop-dontshow input { position: absolute; opacity: 0; width: 0; height: 0; }
.xdrop-box { width: 19px; height: 19px; flex: none; border-radius: 6px; border: 1.5px solid var(--glass-border, rgba(255, 255, 255, 0.28)); display: grid; place-items: center; transition: background 0.15s ease, border-color 0.15s ease; }
.xdrop-box svg { width: 12px; height: 12px; opacity: 0; color: var(--xd-ink); transition: opacity 0.15s ease; }
.xdrop-dontshow input:checked + .xdrop-box { background: rgb(var(--xd)); border-color: rgb(var(--xd)); }
.xdrop-dontshow input:checked + .xdrop-box svg { opacity: 1; }
.xdrop-dontshow input:focus-visible + .xdrop-box { outline: 2px solid rgb(var(--xd)); outline-offset: 2px; }
.xdrop-later { background: none; border: 0; cursor: pointer; font-family: inherit; padding: 6px; color: var(--text-dim, #8b91a1); font-size: 0.8rem; font-weight: 600; }
.xdrop-later:hover { color: var(--text-soft, #c3c8d2); }

/* ── Batch variant: several drops landed at once → ONE grouping card with a
   short tappable list (thumbnail, tier, name), never a modal per item. The
   card wears the theme accent (it holds mixed tiers); each ROW carries its
   own tier colour, gold or violet. */
.xdrop-card.is-batch { --xd: var(--accent-rgb, 53, 224, 142); --xd-ink: #04240f; width: min(470px, 96vw); }
/* The LIST is the scroller here, not the body: nine drops on a 390px screen are
   taller than the card, and the "Open the Store" CTA and the opt-out have to stay
   where the thumb expects them instead of being pushed off the bottom. */
.xdrop-card.is-batch .xdrop-body { overflow-y: hidden; }
.xdrop-batch {
  display: flex; flex-direction: column; gap: 10px; margin-top: 14px;
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  scrollbar-width: thin;
}
/* Each row keeps its own height. Left shrinkable, the 52px thumbnail (`flex: none`)
   outgrew its row and spilled over the row below it. */
.xdrop-row { flex: none; }
.xdrop-row {
  --xr: 255, 180, 84;                 /* supporters gold (default) */
  appearance: none; font-family: inherit; text-align: left; cursor: pointer;
  display: flex; align-items: center; gap: 12px; padding: 8px;
  border-radius: 14px; border: 1px solid rgba(var(--xr), 0.32);
  background: rgba(var(--xr), 0.06); color: var(--text, #e7e9ee);
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.12s ease;
}
.xdrop-row.is-limited { --xr: 139, 123, 255; }
.xdrop-row:hover { border-color: rgba(var(--xr), 0.6); background: rgba(var(--xr), 0.1); }
.xdrop-row:active { transform: scale(0.995); }
.xdrop-row .xdrop-thumb { width: 92px; height: 52px; flex: none; border-radius: 9px; border: 1px solid rgba(255, 255, 255, 0.08); border-bottom-width: 1px; }
.xdrop-row-mid { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.xdrop-row-tier { font-size: 0.62rem; font-weight: 800; letter-spacing: 0.09em; text-transform: uppercase; color: rgba(var(--xr), 1); }
.xdrop-row-name { font-size: 0.95rem; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xdrop-row-left { font-size: 0.74rem; color: var(--text-dim, #8b91a1); font-variant-numeric: tabular-nums; }

@media (max-width: 460px) {
  .xdrop-card { width: 100%; }
  .xdrop-title { font-size: 1.24rem; }
}
@media (prefers-reduced-motion: reduce) {
  .xdrop-overlay, .xdrop-card { animation: none; }
  .xdrop-btn { transition: none; }
}

/* ── Hub announcement (js/hub-messages.js) ───────────────────────────────────
   Sits next to the drop card because they are the same kind of surface, and
   deliberately reads quieter than it: this one is a note, not an offer. Neutral
   accent, no scarcity meter, and at most ONE piece of artwork in a fixed frame
   (see .hubmsg-media). If it ever starts looking like the card above, the
   channel has drifted into advertising. */
.hubmsg-overlay {
  position: fixed; inset: 0; z-index: 9000;
  display: flex; align-items: center; justify-content: center; padding: 4vh 4vw;
  background: rgba(5, 7, 11, 0.62); backdrop-filter: blur(4px);
  animation: xdrop-fade 0.3s ease;
}
.hubmsg-overlay.closing { animation: xdrop-fade 0.2s ease reverse; }

.hubmsg-card {
  position: relative; width: min(420px, 96vw); max-height: 92vh; overflow-y: auto;
  display: flex; flex-direction: column;
  padding: 26px 24px 18px;
  border-radius: 22px;
  background: var(--glass-bg, #14181c);
  border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.14));
  box-shadow: 0 40px 90px -28px rgba(0, 0, 0, 0.78), 0 1px 0 rgba(255, 255, 255, 0.08) inset;
  animation: xdrop-pop 0.42s cubic-bezier(0.16, 1, 0.3, 1);
}
.hubmsg-close {
  position: absolute; top: 12px; right: 12px; width: 32px; height: 32px;
  appearance: none; border: 0; cursor: pointer; font-family: inherit; font-size: 1.3rem; line-height: 1;
  border-radius: 50%; background: rgba(255, 255, 255, 0.07); color: var(--text-dim, #8b91a1);
}
.hubmsg-close:hover { background: rgba(255, 255, 255, 0.13); color: var(--text, #e7e9ee); }

/* Artwork. The rule above used to say a message carries none, and for a text-only
   channel that was right — the risk it named is real and has not gone away. What
   changed is that a release note describing a new widget, or a drop worth looking
   at, was being written in prose and read by nobody: the card had no way to SHOW
   anything. So one picture or clip is allowed, and the guard moved from "never"
   to "the frame is fixed": a set aspect box the author cannot grow, above the
   text, with no caption of its own. A card can illustrate what it says; it still
   cannot become a poster.

   Full-bleed to the card's top edge (hence .has-media dropping the top padding),
   because a framed image inset on all four sides reads as a broken attachment.
   The aspect-ratio is what stops the card from jumping when a file lands late —
   the box is the right size before anything decodes. */
.hubmsg-card.has-media { padding-top: 0; }
.hubmsg-media {
  position: relative; margin: 0 -24px 18px; aspect-ratio: 16 / 9; overflow: hidden;
  border-radius: 22px 22px 14px 14px;
  background: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid var(--glass-border, rgba(255, 255, 255, 0.09));
}
.hubmsg-media img, .hubmsg-media video {
  display: block; width: 100%; height: 100%; object-fit: cover;
}
/* With artwork behind it the close button sits on the picture, and its usual
   translucent-white fill disappears against a pale one. Opaque dark here, since
   this is the control that has to be findable on any image an author picks. */
.hubmsg-card.has-media .hubmsg-close {
  background: rgba(8, 10, 14, 0.62); color: #f2f4f8;
  backdrop-filter: blur(6px); box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}
.hubmsg-card.has-media .hubmsg-close:hover { background: rgba(8, 10, 14, 0.82); }

.hubmsg-kicker {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: rgba(var(--accent-rgb, 30, 215, 96), 1); margin-bottom: 8px;
}
.hubmsg-title { margin: 0; font-size: 1.2rem; font-weight: 700; letter-spacing: -0.015em; color: var(--text, #e7e9ee); }
.hubmsg-body { margin: 10px 0 0; font-size: 0.9rem; line-height: 1.5; color: var(--text-soft, #c3c8d2); }

.hubmsg-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 20px; }
/* Poll options. Stacked and full width so every answer is the same size — a
   wider button reads as the recommended one, which biases the result. */
.hubmsg-poll { display: flex; flex-direction: column; gap: 9px; margin-top: 20px; }
.hubmsg-poll .hubmsg-btn { width: 100%; height: 46px; font-size: 0.92rem; font-weight: 600; }
.hubmsg-btn {
  appearance: none; border: 0; cursor: pointer; font-family: inherit;
  border-radius: 14px; font-weight: 700; letter-spacing: -0.01em;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  transition: transform 0.12s ease, filter 0.18s ease, background 0.15s ease;
}
.hubmsg-btn:active { transform: translateY(1px) scale(0.995); }
.hubmsg-btn.primary {
  /* --on-accent, not the never-defined --accent-ink this used to name: that
     token resolves nowhere, so the fallback ink was pinned regardless of theme. */
  height: 48px; font-size: 0.96rem; color: var(--on-accent, #06210f);
  background: rgba(var(--accent-rgb, 30, 215, 96), 1);
}
.hubmsg-btn.primary:hover { filter: brightness(1.06); }
.hubmsg-btn.ghost {
  height: 42px; font-size: 0.88rem; font-weight: 600; color: var(--text, #e7e9ee);
  background: transparent; border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.16));
}
.hubmsg-btn.ghost:hover { background: rgba(255, 255, 255, 0.06); }

/* The opt-out is plain and always present — never a hidden setting. */
.hubmsg-optout {
  margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--glass-border, rgba(255, 255, 255, 0.09));
  background: none; border-left: 0; border-right: 0; border-bottom: 0; cursor: pointer; font-family: inherit;
  color: var(--text-dim, #8b91a1); font-size: 0.8rem; font-weight: 600; text-align: center;
}
.hubmsg-optout:hover { color: var(--text-soft, #c3c8d2); }

@media (max-width: 460px) { .hubmsg-card { width: 100%; } }
@media (prefers-reduced-motion: reduce) {
  .hubmsg-overlay, .hubmsg-card { animation: none; }
  .hubmsg-btn { transition: none; }
}

/* Ricerca e disco: vertical rhythm for rows dropped straight into the group
   (no .settings-grid here), the second head, and multiline folder inputs. */
.settings-searchdisk-group > .settings-row,
.settings-searchdisk-group > .settings-toggle-row,
.settings-searchdisk-group > .settings-hint,
.settings-searchdisk-group > .settings-note { margin-bottom: 12px; }
.settings-searchdisk-group > .settings-group-head { margin-bottom: 10px; }

/* (see above) the second head inside the shared group, and multiline
   folder inputs (one path per line). */
.settings-group-head-followup { margin-top: 16px; }
.settings-textarea {
  resize: vertical;
  min-height: 58px;
  font-family: inherit;
  line-height: 1.4;
}
