/* ============================================================================
   PsyShift — Element library
   ----------------------------------------------------------------------------
   The generic building blocks any site needs, styled to the same system as the
   product components: long-form prose, the full range of form controls, tables,
   media players, dialogs, alerts and disclosure widgets.

   components.css holds the things that only make sense inside PsyShift (festival
   cards, budget donuts). This file holds everything that would survive being
   lifted into a different product.
   ========================================================================== */

/* ═════════════════════════════════════════════════════════════════════════
   1. PROSE — long-form editorial content
   ═══════════════════════════════════════════════════════════════════════ */

.prose {
  max-width: 68ch;
  color: var(--c-text-soft);
  line-height: 1.72;
}

.prose > * + * { margin-top: var(--s-4); }

.prose h2, .prose h3, .prose h4 {
  color: var(--c-text);
  margin-top: var(--s-8);
  margin-bottom: var(--s-3);
}
.prose h2 { font-size: var(--t-h2); }
.prose h3 { font-size: var(--t-h3); }
.prose h4 { font-size: var(--t-body); font-weight: 600; }
.prose > h2:first-child, .prose > h3:first-child { margin-top: 0; }

.prose p { margin-top: var(--s-4); }

/* Opening paragraph gets a touch more presence. */
.prose > p:first-of-type { font-size: 1.05rem; color: var(--c-text); }

.prose a {
  color: var(--c-accent-bright);
  text-decoration: underline;
  text-decoration-color: var(--c-line-accent);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--dur-2) var(--ease), color var(--dur-2) var(--ease);
}
.prose a:hover { color: var(--c-text); text-decoration-color: currentColor; }

.prose strong { color: var(--c-text); font-weight: 600; }
.prose em { font-style: italic; }

.prose ul, .prose ol { padding-left: var(--s-5); }
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li { margin-top: var(--s-2); padding-left: var(--s-2); }
.prose li::marker { color: var(--c-accent); }
.prose ul ul, .prose ol ol, .prose ul ol, .prose ol ul { margin-top: var(--s-2); }

.prose blockquote {
  margin-inline: 0;
  padding: var(--s-1) 0 var(--s-1) var(--s-5);
  border-left: 2px solid var(--c-accent);
  color: var(--c-text);
  font-size: 1.05rem;
  font-style: italic;
}
.prose blockquote cite {
  display: block;
  margin-top: var(--s-3);
  font-size: var(--t-xs);
  font-style: normal;
  color: var(--c-text-faint);
}
.prose blockquote cite::before { content: "— "; }

.prose hr {
  height: 1px;
  margin-block: var(--s-8);
  border: none;
  background: linear-gradient(90deg, var(--c-line-strong), transparent);
}

.prose figure { margin: var(--s-6) 0; }
.prose figcaption {
  margin-top: var(--s-3);
  font-size: var(--t-xs);
  color: var(--c-text-faint);
}

/* Definition list */
.prose dl { display: grid; grid-template-columns: auto 1fr; gap: var(--s-2) var(--s-5); }
.prose dt { font-weight: 600; color: var(--c-text); }
.prose dd { margin: 0; }

/* ── Inline text elements ─────────────────────────────────────────────── */

code, .code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  padding: 0.15em 0.42em;
  color: var(--c-accent-bright);
  background: var(--c-accent-wash);
  border: 1px solid var(--c-line-accent);
  border-radius: var(--r-xs);
  white-space: nowrap;
}

pre {
  overflow-x: auto;
  padding: var(--s-4);
  background: var(--c-bg-deep);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  font-family: var(--font-mono);
  font-size: var(--t-xs);
  line-height: 1.7;
  color: var(--c-text-soft);
  tab-size: 2;
}
/* A code block inside <pre> must not inherit the inline pill treatment. */
pre code {
  padding: 0;
  color: inherit;
  background: none;
  border: none;
  white-space: pre;
  font-size: inherit;
}

kbd {
  display: inline-block;
  min-width: 1.6em;
  padding: 2px 6px;
  font-family: var(--font-mono);
  font-size: 0.8em;
  line-height: 1.4;
  text-align: center;
  color: var(--c-text-soft);
  background: var(--c-surface-2);
  border: 1px solid var(--c-line-strong);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
}

mark {
  padding: 0.1em 0.3em;
  color: var(--c-text);
  background: var(--c-warn-wash);
  border-radius: 3px;
}

del { color: var(--c-text-faint); text-decoration-color: var(--c-hot); }
ins { color: var(--c-second); text-decoration: none; background: var(--c-second-wash); padding: 0 .25em; border-radius: 3px; }

abbr[title] {
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  cursor: help;
}

small { font-size: var(--t-xs); color: var(--c-text-muted); }

sup, sub { font-size: 0.7em; }

/* Standalone link style, outside prose. */
.link {
  color: var(--c-accent-bright);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 3px;
  transition: text-decoration-color var(--dur-2) var(--ease);
}
.link:hover { text-decoration-color: currentColor; }

.link--quiet { color: var(--c-text-soft); }
.link--quiet:hover { color: var(--c-text); }

/* ═════════════════════════════════════════════════════════════════════════
   2. FORMS
   ═══════════════════════════════════════════════════════════════════════ */

.form { display: grid; gap: var(--s-5); }

fieldset {
  padding: var(--s-5);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
}
legend {
  padding-inline: var(--s-3);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--c-text-faint);
}

/* `.field` and `.field__label` are defined in components.css; these extend it. */
.field__label .req { color: var(--c-hot); margin-left: 2px; }
.field__label .optional {
  margin-left: var(--s-2);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--c-text-faint);
}

.field__hint {
  font-size: var(--t-2xs);
  line-height: 1.5;
  color: var(--c-text-faint);
}
.field__error,
.field__ok {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--t-2xs);
  font-weight: 500;
}
.field__error { color: var(--c-hot); }
.field__ok { color: var(--c-second); }

/* ── Text inputs ──────────────────────────────────────────────────────────
   `.input` and `.select` come from components.css. Everything below covers
   the native types those rules do not reach, plus states.                 */

textarea.input {
  height: auto;
  min-height: 108px;
  padding-block: var(--s-3);
  line-height: var(--lh-body);
  resize: vertical;
}

.input:disabled, .select:disabled, textarea.input:disabled {
  opacity: .5;
  cursor: not-allowed;
  background: var(--c-surface);
}
.input:read-only:not([type="range"]) { color: var(--c-text-muted); }

/* Validation states — driven by a class so they can be applied deliberately,
   plus :user-invalid so native validation styles itself after a real attempt. */

.input:user-invalid, textarea.input:user-invalid {
  border-color: rgba(255, 77, 143, .55);
  box-shadow: 0 0 0 4px var(--c-hot-wash);
}

/* Native pickers: force the browser's own icons to the dark palette. */
.input[type="date"], .input[type="time"], .input[type="datetime-local"],
.input[type="month"], .input[type="week"] { color-scheme: dark; }
.input::-webkit-calendar-picker-indicator {
  filter: invert(.7) sepia(.2) saturate(3) hue-rotate(200deg);
  cursor: pointer;
}

.input[type="color"] {
  padding: 4px;
  width: 62px;
  cursor: pointer;
}
.input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
.input[type="color"]::-webkit-color-swatch { border: none; border-radius: var(--r-xs); }
.input[type="color"]::-moz-color-swatch { border: none; border-radius: var(--r-xs); }

/* Icon sitting inside the field itself. */
.input-icon { position: relative; display: block; }
.input-icon > svg {
  position: absolute;
  left: var(--s-4);
  top: 50%;
  translate: 0 -50%;
  width: 18px; height: 18px;
  color: var(--c-text-faint);
  pointer-events: none;
}
.input-icon .input { padding-left: calc(var(--s-4) * 2 + 18px); }

/* ── Rich text editor (docs/features/rich-text-editor) ───────────────────
   A toolbar over an editable surface, drawn as one field: it replaces the
   <textarea> it enhances (Ui::editor(), editor.js). The surface is `.prose`,
   like the post it becomes, so what is written reads the way it will look. */
.editor {
  background: var(--c-surface-2);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  transition: border-color var(--dur-2) var(--ease), box-shadow var(--dur-2) var(--ease);
}
.editor:focus-within { border-color: var(--c-line-accent); box-shadow: 0 0 0 4px var(--c-accent-wash); }
.editor__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px;
  padding: 4px;
  border-bottom: 1px solid var(--c-line);
}
.editor__btn {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r-sm);
  color: var(--c-text-muted);
  transition: background var(--dur-1) var(--ease), color var(--dur-1) var(--ease);
}
.editor__btn svg { width: 18px; height: 18px; }
.editor__btn:hover { background: var(--c-surface-3); color: var(--c-text); }
.editor__btn[aria-pressed="true"] { background: var(--c-accent-wash); color: var(--c-accent-bright); }
.editor__btn:focus-visible { outline: 2px solid var(--c-accent); outline-offset: -2px; }
.editor__sep { width: 1px; height: 18px; margin-inline: 4px; background: var(--c-line); }
.editor__linkbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2);
  border-bottom: 1px solid var(--c-line);
}
.editor__url { flex: 1 1 14rem; min-width: 0; height: 36px; }
.editor__surface {
  position: relative;
  min-height: 132px;
  max-height: 60vh;
  overflow-y: auto;
  padding: var(--s-3) var(--s-4);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  color: var(--c-text-soft);
  overflow-wrap: anywhere;
  outline: none;
}
.editor__surface > :first-child { margin-top: 0; }
.editor__surface.is-empty::before {
  content: attr(data-placeholder);
  position: absolute;
  inset: var(--s-3) var(--s-4) auto;
  color: var(--c-text-faint);
  pointer-events: none;
}
/* A code mark wraps like the words around it, here and in a post. */
.editor__surface code { white-space: normal; }
.editor__surface blockquote > :first-child { margin-top: 0; }

/* ── Checkbox & radio (standalone; `.opt` is the list-row variant) ────── */
.choice {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--s-3);
  cursor: pointer;
  font-size: var(--t-sm);
  color: var(--c-text-soft);
}
.choice input { position: absolute; opacity: 0; pointer-events: none; }

.choice__mark {
  display: grid;
  place-items: center;
  width: 19px; height: 19px;
  margin-top: 1px;
  flex-shrink: 0;
  background: var(--c-surface-2);
  border: 1.5px solid var(--c-line-strong);
  border-radius: 5px;
  transition: background var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.choice__mark svg {
  width: 13px; height: 13px;
  color: #fff;
  opacity: 0;
  transform: scale(.4);
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}
.choice--radio .choice__mark { border-radius: 50%; }
/* The radio dot is drawn with a pseudo-element rather than an icon. */
.choice--radio .choice__mark::after {
  content: "";
  width: 9px; height: 9px;
  border-radius: 50%;
  background: #fff;
  opacity: 0;
  transform: scale(.4);
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out);
}

.choice input:checked + .choice__mark {
  background: var(--c-accent);
  border-color: var(--c-accent);
}
.choice input:checked + .choice__mark svg,
.choice input:checked + .choice__mark::after { opacity: 1; transform: scale(1); }

.choice input:indeterminate + .choice__mark { background: var(--c-accent); border-color: var(--c-accent); }
.choice input:indeterminate + .choice__mark::before {
  content: "";
  width: 10px; height: 2px;
  border-radius: 1px;
  background: #fff;
}

.choice input:focus-visible + .choice__mark {
  outline: 2px solid var(--c-accent-bright);
  outline-offset: 2px;
}
.choice input:disabled + .choice__mark { opacity: .4; }
.choice:has(input:disabled) { opacity: .55; cursor: not-allowed; }

.choice__text { display: flex; flex-direction: column; gap: 2px; }
.choice__text em {
  font-style: normal;
  font-size: var(--t-2xs);
  color: var(--c-text-faint);
}

/* ── Switch ───────────────────────────────────────────────────────────── */
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  cursor: pointer;
  font-size: var(--t-sm);
  color: var(--c-text-soft);
}
.switch input { position: absolute; opacity: 0; pointer-events: none; }
.switch__track {
  position: relative;
  width: 42px; height: 24px;
  flex-shrink: 0;
  background: var(--c-surface-3);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--r-full);
  transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}
.switch__track::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 18px; height: 18px;
  background: #fff;
  border-radius: 50%;
  box-shadow: var(--e-1);
  transition: translate var(--dur-2) var(--ease-out);
}
.switch input:checked + .switch__track {
  background: var(--c-accent);
  border-color: var(--c-accent);
}
.switch input:checked + .switch__track::after { translate: 18px 0; }
.switch input:focus-visible + .switch__track {
  outline: 2px solid var(--c-accent-bright);
  outline-offset: 2px;
}
.switch:has(input:disabled) { opacity: .5; cursor: not-allowed; }

/* ── File input / dropzone ────────────────────────────────────────────── */
.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-8) var(--s-5);
  text-align: center;
  background: var(--c-surface);
  border: 1.5px dashed var(--c-line-strong);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}
.dropzone:hover{
  border-color: var(--c-accent);
  background: var(--c-accent-wash);
}
.dropzone input[type="file"] { position: absolute; opacity: 0; width: 0; height: 0; }
.dropzone__icon {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  color: var(--c-accent-bright);
  background: var(--c-accent-wash);
  border-radius: var(--r-full);
}
.dropzone__icon svg { width: 20px; height: 20px; }
.dropzone strong { font-size: var(--t-sm); color: var(--c-text); }
.dropzone span { font-size: var(--t-2xs); color: var(--c-text-faint); }

/* ═════════════════════════════════════════════════════════════════════════
   3. TABLES
   ═══════════════════════════════════════════════════════════════════════ */

/* Tables never shrink gracefully; they scroll inside their own container. */
.table-wrap {
  overflow-x: auto;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-lg);
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-sm);
  white-space: nowrap;
}

.table caption {
  padding: var(--s-4) var(--s-5) 0;
  text-align: left;
  font-size: var(--t-2xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--c-text-faint);
}

.table th, .table td {
  padding: var(--s-3) var(--s-4);
  text-align: left;
  border-bottom: 1px solid var(--c-line);
}

.table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--c-text-faint);
  background: var(--c-surface-2);
  border-bottom-color: var(--c-line-strong);
}

.table tbody tr { transition: background var(--dur-1) var(--ease); }
.table tbody tr:hover { background: rgba(255, 255, 255, .03); }
.table tbody tr:last-child td { border-bottom: none; }

.table tfoot td {
  font-weight: 600;
  color: var(--c-text);
  background: var(--c-surface-2);
  border-bottom: none;
}

.table .num, .table [data-num] { text-align: right; font-variant-numeric: tabular-nums; }

/* ═════════════════════════════════════════════════════════════════════════
   4. MEDIA
   ═══════════════════════════════════════════════════════════════════════ */

/* Aspect-ratio box for anything that must hold its shape while loading. */
.ratio {
  position: relative;
  aspect-ratio: var(--ratio, 16 / 9);
  overflow: hidden;
  border-radius: var(--r-md);
  background: var(--c-surface-2);
}
.ratio > * { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.figure { margin: 0; }
.figure figcaption {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
  margin-top: var(--s-3);
  font-size: var(--t-xs);
  color: var(--c-text-faint);
}
.figure figcaption svg { width: 14px; height: 14px; margin-top: 2px; flex-shrink: 0; }

/* Responsive iframe / embed container. */
.embed {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  background: var(--c-bg-deep);
}
.embed > iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* Masonry-ish gallery. */
.gallery {
  display: grid;
  gap: var(--s-3);
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
}
.gallery > * {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--r-sm);
  transition: transform var(--dur-2) var(--ease-out);
}
.gallery > *:hover { transform: scale(1.03); z-index: 1; }

/* ═════════════════════════════════════════════════════════════════════════
   5. FEEDBACK — alerts, dialogs, tooltips, loaders
   ═══════════════════════════════════════════════════════════════════════ */

.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-4);
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-left: 3px solid var(--c-text-faint);
  border-radius: var(--r-md);
  font-size: var(--t-sm);
}
.alert__icon { flex-shrink: 0; margin-top: 1px; }
.alert__icon svg { width: 18px; height: 18px; }
.alert__body { flex: 1; min-width: 0; }
.alert__title { display: block; font-weight: 600; color: var(--c-text); margin-bottom: 2px; }
.alert p { color: var(--c-text-muted); }

.alert--info    { border-left-color: var(--c-accent); background: linear-gradient(90deg, var(--c-accent-wash), var(--c-surface) 55%); }
.alert--info .alert__icon { color: var(--c-accent-bright); }
.alert--success { border-left-color: var(--c-second); background: linear-gradient(90deg, var(--c-second-wash), var(--c-surface) 55%); }
.alert--success .alert__icon { color: var(--c-second); }
.alert--warning { border-left-color: var(--c-warn); background: linear-gradient(90deg, var(--c-warn-wash), var(--c-surface) 55%); }
.alert--warning .alert__icon { color: var(--c-warn); }
.alert--danger  { border-left-color: var(--c-hot); background: linear-gradient(90deg, var(--c-hot-wash), var(--c-surface) 55%); }
.alert--danger .alert__icon { color: var(--c-hot); }

/* Full-width page banner (cookie notice, maintenance…). */
.banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  background: var(--c-surface-glass);
  backdrop-filter: var(--glass-blur);
  -webkit-backdrop-filter: var(--glass-blur);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--r-lg);
  box-shadow: var(--e-3);
  font-size: var(--t-sm);
}
.banner__text { flex: 1 1 260px; min-width: 0; color: var(--c-text-muted); }
.banner__actions { display: flex; gap: var(--s-2); flex-wrap: wrap; }

/* ── Native <dialog> ──────────────────────────────────────────────────── */
.dialog {
  width: min(520px, calc(100vw - var(--s-8)));
  padding: 0;
  color: var(--c-text);
  background: var(--c-surface);
  border: 1px solid var(--c-line-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--e-4);
}
.dialog::backdrop {
  background: rgba(4, 5, 9, .7);
  backdrop-filter: blur(4px);
}
.dialog[open] { animation: dialog-in var(--dur-3) var(--ease-out); }
@keyframes dialog-in {
  from { opacity: 0; transform: translateY(12px) scale(.97); }
}

/* ── Tooltip ──────────────────────────────────────────────────────────── */
.tip { position: relative; display: inline-flex; }

@keyframes spin { to { rotate: 360deg; } }

/* Three-dot pulse, for inline "thinking" states. */
.dots { display: inline-flex; gap: 4px; align-items: center; }
.dots i {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--c-accent);
  animation: dots 1.1s var(--ease-in-out) infinite;
}
.dots i:nth-child(2) { animation-delay: .14s; }
.dots i:nth-child(3) { animation-delay: .28s; }
@keyframes dots {
  0%, 60%, 100% { opacity: .3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-4px); }
}

/* Determinate progress. `.bar` in components.css is the plain variant. */
.progress {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.progress .bar { flex: 1; }

/* Circular progress ring. */
.ring { display: block; width: var(--size, 56px); height: var(--size, 56px); }
.ring circle { fill: none; stroke-width: 5; }

/* ═════════════════════════════════════════════════════════════════════════
   6. NAVIGATION
   ═══════════════════════════════════════════════════════════════════════ */

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-xs);
  color: var(--c-text-faint);
}
.breadcrumb a { color: var(--c-text-muted); transition: color var(--dur-2) var(--ease); }
.breadcrumb a:hover { color: var(--c-text); }
.breadcrumb li { display: flex; align-items: center; gap: var(--s-2); }
.breadcrumb li + li::before {
  content: "";
  width: 5px; height: 5px;
  border-top: 1px solid currentColor;
  border-right: 1px solid currentColor;
  rotate: 45deg;
  opacity: .5;
}
.breadcrumb [aria-current="page"] { color: var(--c-text); font-weight: 500; }

/* ── Tabs ─────────────────────────────────────────────────────────────── */
.tabs {
  display: flex;
  gap: var(--s-1);
  overflow-x: auto;
  scrollbar-width: none;
  border-bottom: 1px solid var(--c-line);
}
.tabs::-webkit-scrollbar { display: none; }

.tab {
  position: relative;
  padding: var(--s-3) var(--s-4);
  flex-shrink: 0;
  font-size: var(--t-sm);
  font-weight: 500;
  color: var(--c-text-muted);
  white-space: nowrap;
  transition: color var(--dur-2) var(--ease);
}
.tab:hover { color: var(--c-text); }
.tab[aria-selected="true"] { color: var(--c-text); font-weight: 600; }
.tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  inset: auto 0 -1px;
  height: 2px;
  border-radius: var(--r-full);
  background: var(--c-accent);
  box-shadow: 0 0 12px var(--c-accent);
}
.tab__count {
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 600;
  color: var(--c-text-faint);
  background: var(--c-surface-2);
  border-radius: var(--r-full);
}

/* ── Pagination ───────────────────────────────────────────────────────── */
.pagination { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2); }
.page {
  display: grid;
  place-items: center;
  min-width: 36px; height: 36px;
  padding-inline: var(--s-2);
  font-size: var(--t-sm);
  font-variant-numeric: tabular-nums;
  color: var(--c-text-muted);
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-sm);
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease),
              background var(--dur-2) var(--ease);
}
.page:hover:not([aria-disabled="true"]) { color: var(--c-text); border-color: var(--c-line-strong); }
.page[aria-current="page"] {
  color: #fff;
  background: var(--c-accent);
  border-color: transparent;
  font-weight: 600;
}
.page[aria-disabled="true"] { opacity: .4; pointer-events: none; }
.page svg { width: 15px; height: 15px; }

/* ═════════════════════════════════════════════════════════════════════════
   7. DISCLOSURE
   ═══════════════════════════════════════════════════════════════════════ */

.accordion {
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  overflow: hidden;
}
.accordion + .accordion { margin-top: var(--s-2); }

.accordion > summary {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4);
  font-size: var(--t-sm);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  transition: background var(--dur-1) var(--ease);
}
.accordion > summary::-webkit-details-marker { display: none; }
.accordion > summary:hover { background: rgba(255, 255, 255, .035); }
.accordion > summary::after {
  content: "";
  width: 8px; height: 8px;
  margin-left: auto;
  flex-shrink: 0;
  border-right: 1.5px solid var(--c-text-faint);
  border-bottom: 1.5px solid var(--c-text-faint);
  rotate: 45deg;
  translate: 0 -2px;
  transition: rotate var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease);
}
.accordion[open] > summary::after { rotate: -135deg; translate: 0 2px; border-color: var(--c-accent-bright); }
.accordion[open] > summary { border-bottom: 1px solid var(--c-line); }

.accordion__body {
  padding: var(--s-4);
  font-size: var(--t-sm);
  color: var(--c-text-muted);
  line-height: var(--lh-body);
  animation: reveal var(--dur-3) var(--ease-out);
}

/* ═════════════════════════════════════════════════════════════════════════
   8. MISCELLANEOUS
   ═══════════════════════════════════════════════════════════════════════ */

/* Status pill with a leading state dot. */
.status { display: inline-flex; align-items: center; gap: 7px; font-size: var(--t-xs); }
.status::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: currentColor;
}

/* Vertical timeline. */
.timeline { position: relative; padding-left: var(--s-6); }
.timeline::before {
  content: "";
  position: absolute;
  left: 5px; top: 6px; bottom: 6px;
  width: 1px;
  background: linear-gradient(180deg, var(--c-accent), var(--c-line) 80%);
}

/* Divider with optional centred label. */
.divider {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  color: var(--c-text-faint);
  font-size: var(--t-2xs);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
}
.divider::before, .divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--c-line);
}

/* ── Third-party brand mark ───────────────────────────────────────────────
   A platform's glyph on its own colour (`--bm-bg` / `--bm-fg`), for sign-in
   buttons and connected-account lists. Rendered by `brandMark()` in
   auth/ui.js; lives here because the settings panel uses it too.          */
.bmark {
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  flex-shrink: 0;
  color: var(--bm-fg, var(--c-text));
  background: var(--bm-bg, var(--c-surface-3));
  border-radius: 8px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}
.bmark svg { width: 19px; height: 19px; }
.bmark--sm { width: 22px; height: 22px; border-radius: 6px; }
.bmark--sm svg { width: 15px; height: 15px; }
.bmark--lg { width: 40px; height: 40px; border-radius: 11px; }
.bmark--lg svg { width: 26px; height: 26px; }
.bmark--xl { width: 64px; height: 64px; border-radius: 18px; box-shadow: var(--e-3), inset 0 0 0 1px rgba(255, 255, 255, .1); }
.bmark--xl svg { width: 40px; height: 40px; }
.bmark--file { color: var(--c-text-muted); background: var(--c-surface-3); }
.bmark--psyshift {
  color: var(--c-accent-bright);
  background: linear-gradient(150deg, rgba(124, 92, 255, .3), rgba(46, 211, 183, .16)), var(--c-surface-2);
  box-shadow: var(--e-3), inset 0 0 0 1px var(--c-line-accent);
}

/* ═════════════════════════════════════════════════════════════════════════
   PRODUCTION ADDITIONS (server-rendered pages)
   ═══════════════════════════════════════════════════════════════════════ */

/* The consent banner (docs/features/analytics): the page banner above,
   docked at the foot of the viewport until the visitor answers. It clears
   the bottom navigation on phones and sits under sheets and dialogs. */
.consent {
  position: fixed;
  z-index: 85;
  left: var(--s-4);
  right: var(--s-4);
  bottom: calc(var(--s-4) + env(safe-area-inset-bottom));
  max-width: 760px;
  margin-inline: auto;
  animation: toast-in var(--dur-3) var(--ease-out) both;
}
.consent--above-nav { bottom: calc(var(--bottomnav-h) + var(--s-4) + env(safe-area-inset-bottom)); }
@media (min-width: 1024px) {
  .consent--above-nav { bottom: var(--s-6); left: calc(var(--sidebar-w) + var(--s-6)); }
}
.consent .banner { background: var(--c-surface-2); }
.banner__icon { display: inline-flex; color: var(--c-accent-bright); }
.banner__icon svg { width: 20px; height: 20px; }

/* ── Country flag ──────────────────────────────────────────────────────────
   16×11 (docs/flags), left of a place or a country name. Inline, it keeps its
   own gap; inside a flex row that already spaces its items, it takes none. */
.flag {
  display: inline-block;
  flex-shrink: 0;
  width: 16px;
  height: 11px;
  margin-inline-end: 6px;
  vertical-align: -1px;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(255,255,255,.14);
}
:is(.chip, .fcard__place, .fcard__line, .fhero__sub span, .trip__fact, .tbar, .calevent) > .flag { margin-inline-end: 0; }

/* ── Lightbox ─────────────────────────────────────────────────────────────
   A native <dialog> holding one image, as large as the screen allows, never
   cropped; round buttons to close it and step through a set. Clicking the dark
   around the image closes it, like Escape. */
.lightbox {
  width: 100vw; height: 100dvh;
  max-width: none; max-height: none;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--c-text);
}
.lightbox[open] { display: grid; place-items: center; animation: dialog-in var(--dur-3) var(--ease-out); }
.lightbox::backdrop { background: rgba(4, 5, 9, .88); backdrop-filter: blur(6px); }
.lightbox__img {
  max-width: calc(100vw - 2 * var(--s-6));
  max-height: calc(100dvh - 2 * var(--s-10));
  width: auto; height: auto;
  object-fit: contain;
  border-radius: var(--r-md);
  box-shadow: var(--e-4);
}
.lightbox__btn {
  position: fixed;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border-radius: var(--r-full);
  color: var(--c-text);
  background: rgba(20, 23, 36, .8);
  border: 1px solid var(--c-line-strong);
  transition: background var(--dur-1) var(--ease);
}
.lightbox__btn:hover { background: var(--c-surface-2); }
.lightbox__btn svg { width: 20px; height: 20px; }
.lightbox__close { top: var(--s-4); right: var(--s-4); }
.lightbox__prev, .lightbox__next { top: 50%; translate: 0 -50%; }
.lightbox__prev { left: var(--s-4); }
.lightbox__next { right: var(--s-4); }
.lightbox__count {
  position: fixed;
  bottom: var(--s-4);
  left: 50%;
  translate: -50% 0;
  font-size: var(--t-sm);
  color: var(--c-text-muted);
}

/* ── Message banners (production, 2026-09-30, docs/features/site-messages) ──
   The console's messages across the top of every page, edge to edge, above the
   sidebar and the top bar: plain blue, yellow or red, red first. An info or a
   warning one has a close button (a form: app.js closes it in place). The
   console's list shows the same element as a preview. */
.msgbars { position: relative; z-index: 70; }
.msgbar {
  --msg-bg: var(--c-msg-info);
  --msg-ink: var(--c-msg-info-ink);
  background: var(--msg-bg);
  color: var(--msg-ink);
}
.msgbar--warning { --msg-bg: var(--c-msg-warning); --msg-ink: var(--c-msg-warning-ink); }
.msgbar--danger  { --msg-bg: var(--c-msg-danger); --msg-ink: var(--c-msg-danger-ink); }
.msgbar + .msgbar { border-top: 1px solid rgba(0, 0, 0, .18); }
.msgbar__inner {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 44px;
  padding: var(--s-2) var(--s-4);
  padding-left: max(var(--s-4), env(safe-area-inset-left, 0px));
  padding-right: max(var(--s-2), env(safe-area-inset-right, 0px));
}
.msgbar__icon { display: inline-flex; flex-shrink: 0; }
.msgbar__icon svg { width: 18px; height: 18px; fill: currentColor; }
.msgbar__text {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1.4;
  overflow-wrap: anywhere;
}
.msgbar__link { color: inherit; text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.msgbar__link:hover { opacity: .85; }
.msgbar__form { display: contents; }
.msgbar__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: var(--r-full);
  background: transparent;
  color: inherit;
  cursor: pointer;
}
.msgbar__close svg { width: 18px; height: 18px; fill: currentColor; }
.msgbar__close:hover { background: rgba(0, 0, 0, .14); }
.msgbar__close:focus-visible, .msgbar__link:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.msgbar__close:disabled { cursor: default; opacity: .7; }
