/* ===========================================================================
   Yume component layer — every primitive, defined once.

   Loaded between tokens.css and style.css. That order is the contract:
   tokens hold the values, this file holds the primitives, and style.css holds
   layout and the screens. A page rule and a primitive rule with the same
   specificity are resolved by file order, so a screen can still override a
   primitive without !important and without touching this file.

   Before this existed the primitives were scattered through style.css in the
   page section that happened to need one first — .badge lived in the anime
   detail page, .icon-btn in the library, .empty-state in "misc" — and the
   next screen that needed the same thing wrote its own. That is where 1123
   class selectors, 36 badge variants and 11 button classes came from.

   Every component here answers for five states: base, hover, focus, disabled
   and loading. Not all five mean something for every component — a badge is
   not disableable — and where one does not apply it is absent rather than
   faked.

   Focus is deliberately not restated per component. tokens.css sets a global
   :focus-visible ring, and it already works; a component only speaks about
   focus when it needs a different one (an inset ring on a flush control, a
   ring that has to clear a coloured fill).
   =========================================================================== */

/* ---------------------------------------------------------------------------
   Button
   --------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  border: none;
  border-radius: var(--radius-full);
  font-weight: var(--weight-bold);
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-5);
  cursor: pointer;
  transition: transform var(--dur) var(--ease), filter var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
  white-space: nowrap;
  position: relative;
}
.btn:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn svg { width: 1rem; height: 1rem; }

.btn-primary { background: var(--primary); color: var(--primary-fg); }
.btn-theme { background: var(--accent); color: var(--accent-fg); }
.btn-theme:hover, .btn-primary:hover { box-shadow: 0 4px 18px color-mix(in srgb, var(--accent) 30%, transparent); }
.btn-secondary { background: var(--bg-raised); color: var(--fg); border: 1px solid var(--border-strong); }
.btn-ghost { background: transparent; color: var(--fg); border: 1px solid var(--border-strong); }
.btn-ghost:hover { background: var(--bg-raised); }
.btn-danger {
  background: color-mix(in oklab, var(--danger) 16%, transparent);
  color: var(--danger);
  border: 1px solid color-mix(in oklab, var(--danger) 45%, transparent);
}
.btn-danger:hover { background: color-mix(in oklab, var(--danger) 26%, transparent); }

.btn-sm { padding: var(--space-1) var(--space-4); font-size: var(--text-xs); }

/* Disabled and loading are the same refusal wearing two faces, so they share
   the dimming and the cursor. What differs is what the viewer should expect:
   disabled means not now, loading means wait. */
.btn[disabled], .btn[aria-disabled='true'] { opacity: .4; cursor: not-allowed; }
.btn[disabled]:hover, .btn[aria-disabled='true']:hover { filter: none; transform: none; box-shadow: none; }

.btn[data-loading] { color: transparent; pointer-events: none; }
.btn[data-loading]::after {
  content: '';
  position: absolute;
  width: 1em; height: 1em;
  border: 2px solid color-mix(in oklab, currentcolor 30%, transparent);
  border-top-color: currentcolor;
  border-radius: var(--radius-full);
  animation: spin .7s linear infinite;
  /* The spinner inherits the label's colour, which the rule above made
     transparent — so it is set back here from the variant's own text colour. */
  color: var(--fg);
}
.btn-primary[data-loading]::after { color: var(--primary-fg); }
.btn-theme[data-loading]::after { color: var(--accent-fg); }

/* ---------------------------------------------------------------------------
   IconButton — a square control whose whole label is a glyph.

   There were six of these (.icon-btn, .detail-icon-btn, .preview-icon-btn,
   .admin-menu-btn, .player-btn, .ep-num-btn) differing mostly in size, so
   size is a modifier here rather than a new class.
   --------------------------------------------------------------------------- */

.icon-btn {
  width: 1.9rem; height: 1.9rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-overlay);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease);
  flex-shrink: 0;
}
.icon-btn:hover { border-color: var(--accent); color: var(--accent); }
.icon-btn svg { width: .9rem; height: .9rem; }
.icon-btn-sm { width: 1.5rem; height: 1.5rem; }
.icon-btn-sm svg { width: .75rem; height: .75rem; }
.icon-btn-lg { width: 2.5rem; height: 2.5rem; border-radius: var(--radius-md); }
.icon-btn-lg svg { width: 1.15rem; height: 1.15rem; }
/* Over a video frame or artwork the control cannot borrow the theme: the
   surface behind it is a picture. */
.icon-btn-media {
  background: color-mix(in oklab, var(--scrim) 45%, transparent);
  color: var(--on-media);
  border-color: color-mix(in oklab, var(--on-media) 20%, transparent);
}
.icon-btn-media:hover { background: color-mix(in oklab, var(--scrim) 60%, transparent); color: var(--on-media); }
.icon-btn[disabled], .icon-btn[aria-disabled='true'] { opacity: .4; cursor: not-allowed; }
.icon-btn[disabled]:hover { border-color: var(--border); color: var(--fg); }

/* ---------------------------------------------------------------------------
   Surface — the generic panel.

   Named .surface rather than .card because .card is already this product's
   anime cover card, and renaming that would touch every screen for no gain.
   --------------------------------------------------------------------------- */

.surface {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}
.surface-lg { border-radius: var(--radius-lg); padding: var(--space-5); }
.surface-flush { padding: 0; overflow: clip; }
.surface-interactive { cursor: pointer; transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease); }
.surface-interactive:hover { border-color: var(--border-strong); background: color-mix(in oklab, var(--bg-raised) 70%, var(--bg)); }

/* ---------------------------------------------------------------------------
   Dialog — backdrop plus panel.
   --------------------------------------------------------------------------- */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: color-mix(in oklab, var(--bg-sunken) 65%, transparent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  z-index: 100;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 12vh;
}
.modal-backdrop.hidden { display: none; }

.dialog {
  width: min(34rem, calc(100vw - 2rem));
  background: var(--bg-overlay);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-3);
  overflow: clip;
}
.dialog-head {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
  font: var(--type-subtitle);
}
.dialog-body { padding: var(--space-4); }
.dialog-foot {
  display: flex; justify-content: flex-end; gap: var(--space-2);
  padding: var(--space-4);
  border-top: 1px solid var(--border);
}

/* ---------------------------------------------------------------------------
   Dropdown
   --------------------------------------------------------------------------- */

.dropdown { position: relative; display: inline-flex; }
.dropdown-menu {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  min-width: 10rem;
  background: var(--bg-overlay);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-2);
  padding: var(--space-1);
  z-index: 90;
}
.dropdown-menu[hidden] { display: none; }
.dropdown-menu-end { left: auto; right: 0; }
.dropdown-item {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  background: none; border: none;
  color: var(--fg);
  font: var(--type-caption);
  text-align: left;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.dropdown-item:hover { background: var(--accent-soft); color: var(--accent); }
.dropdown-item[disabled] { opacity: .4; cursor: not-allowed; }
.dropdown-item[disabled]:hover { background: none; color: var(--fg); }
.dropdown-sep { height: 1px; background: var(--border); margin: var(--space-1) 0; }

/* ---------------------------------------------------------------------------
   Input, Select, Textarea, Checkbox, Switch
   --------------------------------------------------------------------------- */

.input, .select, .textarea {
  background: var(--bg-raised);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-family: inherit;
  outline: none;
  min-width: 8rem;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.textarea { min-height: 6rem; resize: vertical; width: 100%; }
/* :focus rather than :focus-visible, because a text field earns a visible
   focus ring however it was reached — clicking into one and typing is the
   whole interaction. The outline is suppressed only because this ring
   replaces it. */
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.input::placeholder, .textarea::placeholder { color: var(--fg-faint); }
.input[disabled], .select[disabled], .textarea[disabled] {
  opacity: .5; cursor: not-allowed; background: var(--bg);
}
.input[aria-invalid='true'], .textarea[aria-invalid='true'] {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--danger) 18%, transparent);
}

.field { display: flex; flex-direction: column; gap: var(--space-1); }
.field-label { font: var(--type-metadata); color: var(--fg-muted); }
.field-hint { font: var(--type-metadata); color: var(--fg-faint); }
.field-error { font: var(--type-metadata); color: var(--danger); }

.checkbox {
  display: inline-flex; align-items: center; gap: var(--space-2);
  cursor: pointer;
  font: var(--type-caption);
}
.checkbox input {
  appearance: none;
  width: 1.05rem; height: 1.05rem;
  flex-shrink: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-raised);
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.checkbox input:checked { background: var(--accent); border-color: var(--accent); }
/* The tick is drawn rather than typed: a glyph would inherit the page font
   and sit differently in every fallback. */
.checkbox input:checked::after {
  content: '';
  display: block;
  width: .3rem; height: .55rem;
  margin: .05rem auto 0;
  border: solid var(--accent-fg);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.checkbox input[disabled] { opacity: .4; cursor: not-allowed; }
.checkbox:has(input[disabled]) { opacity: .6; cursor: not-allowed; }

.switch { display: inline-flex; align-items: center; gap: var(--space-2); cursor: pointer; font: var(--type-caption); }
/* 1.5rem tall, not 1.15rem. The audit caught this one in my own component
   layer: 34x18 is under the 24px floor, and a switch is the whole target. */
.switch input { appearance: none; width: 2.6rem; height: 1.5rem; flex-shrink: 0;
  background: var(--border-strong); border-radius: var(--radius-full); position: relative;
  cursor: pointer; transition: background var(--dur) var(--ease); }
.switch input::after {
  content: '';
  position: absolute; top: 2px; left: 2px;
  width: calc(1.5rem - 4px); height: calc(1.5rem - 4px);
  background: var(--on-media);
  border-radius: var(--radius-full);
  transition: transform var(--dur) var(--ease);
}
.switch input:checked { background: var(--accent); }
.switch input:checked::after { transform: translateX(calc(2.6rem - 1.5rem)); }
.switch input[disabled] { opacity: .4; cursor: not-allowed; }

/* ---------------------------------------------------------------------------
   Tabs
   --------------------------------------------------------------------------- */

.tabs {
  display: flex;
  gap: var(--space-1);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: none; border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  color: var(--fg-faint);
  font: var(--type-caption);
  font-weight: var(--weight-bold);
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.tab:hover { color: var(--fg); }
.tab[aria-selected='true'], .tab.active { color: var(--accent); border-bottom-color: var(--accent); }
.tab[disabled] { opacity: .4; cursor: not-allowed; }
.tab:focus-visible { outline-offset: -2px; }

/* ---------------------------------------------------------------------------
   Badge
   --------------------------------------------------------------------------- */

.badges { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0; }
.badge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  background: var(--bg-raised);
  border: 1px solid var(--border);
  color: var(--fg-muted);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  padding: var(--space-1) var(--space-3);
  white-space: nowrap;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
a.badge:hover { color: var(--accent); border-color: var(--accent); }
.badge.badge-theme { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
.badge.badge-outline { background: transparent; }
.badge-ok { color: var(--ok); border-color: color-mix(in oklab, var(--ok) 45%, transparent); background: color-mix(in oklab, var(--ok) 14%, transparent); }
.badge-danger { color: var(--danger); border-color: color-mix(in oklab, var(--danger) 45%, transparent); background: color-mix(in oklab, var(--danger) 14%, transparent); }
.badge-info { color: var(--info); border-color: color-mix(in oklab, var(--info) 45%, transparent); background: color-mix(in oklab, var(--info) 14%, transparent); }

/* ---------------------------------------------------------------------------
   Avatar
   --------------------------------------------------------------------------- */

.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; position: relative; overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--bg-raised);
  color: var(--fg-muted);
  font-weight: var(--weight-black);
  line-height: 1;
  user-select: none;
}
.avatar img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.avatar-xs { width: 1.25rem; height: 1.25rem; font-size: var(--text-xs); }
.avatar-sm { width: 1.9rem; height: 1.9rem; font-size: var(--text-sm); }
.avatar-md { width: 2.75rem; height: 2.75rem; font-size: var(--text-lg); }
.avatar-lg { width: 5rem; height: 5rem; font-size: var(--text-2xl); }
.avatar-xl {
  width: 7rem; height: 7rem; font-size: var(--text-3xl);
  /* Only the big one sits over a banner, so only it needs to lift off it. */
  border: 3px solid var(--bg);
  box-shadow: var(--shadow-2);
}

/* ---------------------------------------------------------------------------
   Toast
   --------------------------------------------------------------------------- */

.toasts {
  position: fixed;
  bottom: var(--space-4);
  right: var(--space-4);
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.toast {
  background: var(--bg-overlay);
  border: 1px solid var(--border-strong);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  box-shadow: var(--shadow-2);
  animation: toast-in var(--dur) var(--ease);
  max-width: 22rem;
}
.toast.error { border-left-color: var(--danger); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------------------------------------------------------------------------
   Tooltip

   The sidebar carried the only tooltips on the site and did it with the
   title attribute, which cannot be styled, cannot be positioned and waits
   about a second before appearing.
   --------------------------------------------------------------------------- */

.tooltip { position: relative; }
.tooltip::after {
  content: attr(data-tip);
  position: absolute;
  left: 50%;
  bottom: calc(100% + var(--space-2));
  transform: translateX(-50%);
  background: var(--bg-overlay);
  color: var(--fg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-1) var(--space-2);
  font: var(--type-metadata);
  white-space: nowrap;
  box-shadow: var(--shadow-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease);
  z-index: 120;
}
.tooltip:hover::after, .tooltip:focus-visible::after { opacity: 1; }
.tooltip-right::after { left: calc(100% + var(--space-2)); bottom: auto; top: 50%; transform: translateY(-50%); }

/* ---------------------------------------------------------------------------
   Skeleton

   .skeleton is the shimmer itself. The shapes below exist because a loading
   state that is one grey box tells the viewer nothing about what is coming:
   a skeleton earns its place only by having the silhouette of the content it
   stands in for.
   --------------------------------------------------------------------------- */

.skeleton { position: relative; overflow: clip; background: var(--bg-raised); }
.skeleton::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--fg) 6%, transparent), transparent);
  animation: shimmer 1.4s infinite;
}
@keyframes shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

.skel-text { height: 1em; border-radius: var(--radius-sm); margin: .2em 0; }
.skel-text-sm { height: .85em; }
.skel-title { height: 1.4em; border-radius: var(--radius-sm); max-width: 60%; margin: .2em 0 .5em; }
.skel-line-short { max-width: 40%; }
.skel-line-mid { max-width: 70%; }
.skel-block { border-radius: var(--radius-md); }
.skel-avatar { border-radius: var(--radius-full); width: 1.9rem; height: 1.9rem; flex-shrink: 0; }
.skel-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--border);
}
.skel-row-body { flex-grow: 1; min-width: 0; }

@media (prefers-reduced-motion: reduce) {
  .skeleton::after { animation: none; }
}

/* ---------------------------------------------------------------------------
   Spinner
   --------------------------------------------------------------------------- */

.spinner {
  width: 2rem; height: 2rem;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: var(--radius-full);
  animation: spin .8s linear infinite;
  margin: var(--space-6) auto;
}
.spinner-sm { width: 1.1rem; height: 1.1rem; border-width: 2px; margin: 0; }

/* ---------------------------------------------------------------------------
   Pagination
   --------------------------------------------------------------------------- */

.pagination { display: flex; align-items: center; justify-content: center; gap: var(--space-2); padding: var(--space-5) 0; flex-wrap: wrap; }
.pagination-page {
  min-width: 2rem;
  padding: var(--space-1) var(--space-2);
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--fg-muted);
  font: var(--type-metadata);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.pagination-page:hover { border-color: var(--accent); color: var(--accent); }
.pagination-page[aria-current='page'] { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
.pagination-page[disabled] { opacity: .4; cursor: not-allowed; }
.pagination-page[disabled]:hover { border-color: var(--border); color: var(--fg-muted); }
.pagination-gap { color: var(--fg-faint); padding: 0 var(--space-1); }

/* ---------------------------------------------------------------------------
   Table

   Below the stacking width the table stops being a table: each row becomes a
   card and each cell carries its own label, taken from data-label. A table
   that keeps its shape on a phone has to be scrolled sideways to be read,
   which is the defect this avoids rather than a style choice.
   --------------------------------------------------------------------------- */

.table { width: 100%; border-collapse: collapse; font: var(--type-caption); }
.table th {
  text-align: left;
  font: var(--type-metadata);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--fg-faint);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.table td { padding: var(--space-3); border-bottom: 1px solid var(--border); vertical-align: top; }
.table tbody tr { transition: background var(--dur) var(--ease); }
.table tbody tr:hover { background: color-mix(in oklab, var(--bg-raised) 60%, transparent); }
.table-num { text-align: right; font-variant-numeric: tabular-nums; }

@media (max-width: 720px) {
  .table-stack, .table-stack thead, .table-stack tbody, .table-stack tr, .table-stack th, .table-stack td { display: block; }
  .table-stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .table-stack tr {
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    padding: var(--space-2);
    margin-bottom: var(--space-3);
  }
  .table-stack td { border: none; padding: var(--space-1) var(--space-2); display: flex; gap: var(--space-3); justify-content: space-between; }
  .table-stack td::before {
    content: attr(data-label);
    font: var(--type-metadata);
    color: var(--fg-faint);
    text-transform: uppercase;
    letter-spacing: .04em;
    flex-shrink: 0;
  }
  .table-stack .table-num { text-align: left; }
}

/* ---------------------------------------------------------------------------
   EmptyState / ErrorState
   --------------------------------------------------------------------------- */

.empty-state {
  text-align: center;
  color: var(--fg-faint);
  padding: var(--space-7) var(--space-4);
  font-weight: var(--weight-bold);
  background: color-mix(in oklab, var(--bg-raised) 55%, transparent);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  max-width: 40rem;
  margin: var(--space-4) auto;
}
.empty-state::before {
  content: '◌';
  display: block;
  font-size: var(--text-2xl);
  margin-bottom: var(--space-2);
  color: var(--border-strong);
}
.empty-state-action { margin-top: var(--space-4); }

.error-state {
  text-align: center;
  color: var(--danger);
  background: color-mix(in oklab, var(--danger) 12%, transparent);
  border: 1px solid color-mix(in oklab, var(--danger) 40%, transparent);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin: var(--space-4) var(--space-6);
  font-weight: var(--weight-bold);
}
.error-state-detail { font: var(--type-metadata); color: var(--fg-muted); margin-top: var(--space-2); font-weight: var(--weight-normal); }
.error-state-action { margin-top: var(--space-4); }


/* ---------------------------------------------------------------------------
   Landing page

   The one screen a visitor sees before they have an account, so it is the one
   place the type is allowed to be enormous. Everything else on the site is a
   dense interface; this is a poster.
   --------------------------------------------------------------------------- */

.landing { max-width: 62rem; margin: 0 auto; padding: 0 var(--space-4); }

/* ---- fejléc ----
   Átlátszó, amíg a lap tetején vagyunk, mert az első képernyőn a cím a
   főszereplő és semmi nem takarhatja. Görgetés közben tömörödik be, hogy a
   fölé csúszó tartalom ne olvadjon össze vele. */
.lp-header {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.lp-header-solid {
  background: color-mix(in oklab, var(--bg) 88%, transparent);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-bottom-color: var(--border);
}

/* A márka tolja jobbra a többit. Testvér-szelektorral nem megy: a
   link-sor telefonon `display:none`, de testvér marad, így a rá épülő
   szabály akkor is érvényes, amikor a sor ott sincs — ettől ült a
   profil-ikon a logó mellett. */
.lp-brand { display: flex; align-items: center; gap: var(--space-2); text-decoration: none; color: var(--fg); margin-inline-end: auto; }
.lp-brand-mark {
  display: grid; place-items: center;
  width: 1.75rem; height: 1.75rem;
  border-radius: var(--radius-md);
  background: var(--accent);
  color: var(--accent-fg);
  font-weight: var(--weight-black);
  text-transform: uppercase;
}
.lp-brand-name { font-weight: var(--weight-extrabold); letter-spacing: -.01em; }

/* A középső link-sor eltűnik telefonon: a fejléc ott a márka és a fiók, más
   semmi. A célok a lapon belül úgyis ott vannak. */
.lp-header-nav { display: none; gap: var(--space-5); }
/* 24px floor. These were 21px — my own, added two commits ago, and the audit
   caught them the same way it caught the footer's. */
.lp-header-nav a {
  color: var(--fg-muted); text-decoration: none;
  font: var(--type-caption); font-weight: var(--weight-bold);
  display: inline-flex; align-items: center; min-height: 24px;
}
.lp-header-nav a:hover { color: var(--fg); }
@media (min-width: 720px) { .lp-header-nav { display: flex; } }

/* Egyetlen gomb jobb felül. Belépve a kezdőbetű, kilépve egy ikon — ugyanaz a
   doboz, így a fejléc nem ugrik meg belépéskor. */
.lp-account {
  display: grid; place-items: center;
  width: 2.25rem; height: 2.25rem;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  border: 1px solid var(--border-strong);
  background: var(--bg-raised);
  color: var(--fg);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.lp-account:hover { border-color: var(--accent); background: var(--accent-soft); }
.lp-account-letter { font-weight: var(--weight-black); font-size: var(--text-sm); }

/* ---- belépő ablak ---- */
.auth-modal .dialog { width: min(24rem, calc(100vw - 2rem)); }
.auth-body { display: flex; flex-direction: column; gap: var(--space-4); }
.auth-fields { display: flex; flex-direction: column; gap: var(--space-3); }
.auth-fields .input { width: 100%; }

.lp-hero {
  position: relative;
  min-height: min(78vh, 42rem);
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--space-8) 0;
  isolation: isolate;
}

/* The site's own name, outlined, barely there. Texture rather than content —
   it is aria-hidden in the markup for the same reason. */
.lp-watermark {
  position: absolute;
  inset-inline-start: -0.06em;
  top: 50%;
  transform: translateY(-50%);
  z-index: -1;
  font-size: clamp(6rem, 30vw, 20rem);
  font-weight: var(--weight-black);
  letter-spacing: -0.04em;
  line-height: 1;
  color: transparent;
  /* 7% olvasható maradt az alcím mögött, és versenyzett vele. A vízjel
     textúra, nem tartalom: annyira legyen ott, hogy hiányozzon, ha kiveszed. */
  -webkit-text-stroke: 1px color-mix(in oklab, var(--fg) 4%, transparent);
  user-select: none;
  white-space: nowrap;
}

.lp-title {
  font-size: clamp(2.5rem, 11vw, 5.5rem);
  font-weight: var(--weight-extrabold);
  line-height: var(--leading-tight);
  letter-spacing: -0.03em;
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
/* The gradient sits on the opening words only — the rest stays solid, so the
   effect reads as emphasis rather than as a coloured heading. */
.lp-title-lead {
  background: linear-gradient(100deg, var(--fg), color-mix(in oklab, var(--fg) 45%, var(--bg)));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.lp-sub {
  font: var(--type-subtitle);
  color: var(--fg-muted);
  max-width: 34rem;
  margin: 0 0 var(--space-6);
}

.lp-cta { display: flex; gap: var(--space-3); flex-wrap: wrap; }
.lp-cta .btn { padding: var(--space-3) var(--space-6); font-size: var(--text-base); }

.lp-section { padding: var(--space-8) 0; border-top: 1px solid var(--border); }

.lp-eyebrow {
  font: var(--type-metadata);
  text-transform: uppercase;
  letter-spacing: .2em;
  color: var(--fg-faint);
  margin: 0 0 var(--space-3);
}

.lp-display {
  font-size: clamp(1.8rem, 6vw, 3.2rem);
  font-weight: var(--weight-extrabold);
  line-height: var(--leading-tight);
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
.lp-display-lead {
  background: linear-gradient(100deg, var(--fg), color-mix(in oklab, var(--fg) 45%, var(--bg)));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.lp-lead { font: var(--type-body); color: var(--fg-muted); max-width: 38rem; margin: 0 0 var(--space-7); }

/* One feature per thumb-scroll on a phone, two columns once there is room. */
.lp-features { display: grid; gap: var(--space-7); }
@media (min-width: 720px) { .lp-features { grid-template-columns: 1fr 1fr; column-gap: var(--space-6); } }

.lp-feature { display: flex; gap: var(--space-4); align-items: flex-start; }
.lp-feature-icon {
  display: flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem; flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--accent);
}
.lp-feature-title { font: var(--type-subtitle); margin: 0 0 var(--space-1); }
.lp-feature-body { font: var(--type-caption); color: var(--fg-muted); margin: 0; }

.lp-close { scroll-margin-top: var(--space-5); }

@media (prefers-reduced-motion: no-preference) {
  .landing { scroll-behavior: smooth; }
}


/* ---------------------------------------------------------------------------
   Announcement modal

   The dialog primitive with one change: it is centred rather than dropped from
   the top, because this is the only modal a viewer did not ask for and landing
   it in the middle of the screen is what says "read me" without shouting.
   --------------------------------------------------------------------------- */

.ann-modal { align-items: center; padding-top: 0; }
.ann-modal .dialog { width: min(30rem, calc(100vw - 2rem)); }
.ann-body { display: flex; flex-direction: column; gap: var(--space-3); }
.ann-body p { margin: 0; font: var(--type-body); color: var(--fg-muted); }
.ann-body p:first-child { color: var(--fg); }


/* ---------------------------------------------------------------------------
   Fekvő bannerkártya és sor

   Nem a portré kártya szélesebb változata. Azért létezik, hogy egy sor
   *másképp* nézzen ki, mint a fölötte lévő: nyolc egyforma sor egyetlen falnak
   olvas, és a nyolcadiknál már senki nem néz oda. A műfaj-sorok kapják, a
   portré sorok közé ékelve.
   --------------------------------------------------------------------------- */

.hscroll-banner { gap: var(--space-3); }

.bcard {
  position: relative;
  display: block;
  flex: 0 0 auto;
  /* Egy kártya majdnem egy képernyő telefonon, hogy feature-csíknak olvasson
     és ne listaelemnek. A következő fele kilátszik: ez mondja, hogy görgethető. */
  width: min(85vw, 30rem);
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: clip;
  background: var(--bg-raised);
  text-decoration: none;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.bcard:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); }
.bcard-art { position: absolute; inset: 0; }
.bcard-art img { width: 100%; height: 100%; object-fit: cover; }

/* A cím a képre kerül, sötétítésen. Alá írni azt jelentené, hogy a kártya
   magassága a címtől függ, és egy hosszú anime-cím szétdobná a sort. */
.bcard-scrim {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-5) var(--space-4) var(--space-3);
  background: linear-gradient(to top, color-mix(in oklab, var(--scrim) 88%, transparent), transparent);
}
.bcard-title {
  font: var(--type-subtitle);
  color: var(--on-media);
  text-shadow: 0 1px 8px color-mix(in oklab, var(--scrim) 70%, transparent);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.bcard-meta {
  font: var(--type-metadata);
  color: color-mix(in oklab, var(--on-media) 78%, transparent);
}

@media (min-width: 720px) {
  .bcard { width: 24rem; }
}
