/* Copyright © 2026 Baka Attila Tamás. Minden jog fenntartva / All rights reserved. Lásd / see: LICENSE */
/* ============================================================
   Kanban — minimal, clean, desktop-first
   User colors carry the identity; the chrome stays quiet.
   ============================================================ */

/* Geist (Vercel, SIL OFL 1.1 — see THIRD-PARTY-NOTICES.md), self-hosted:
   one variable file for every weight. swap: the text shows at once in the
   fallback face and changes over when the file has arrived. */
@font-face {
  font-family: 'Geist';
  src: url('vendor/geist/Geist-Variable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Style A (v131): the tokens of the approved design, in the app's own
   palette (accent, deadline colours, filter band). */
:root {
  --bg:        #eef0f4;
  --surface:   #ffffff;
  --ink:       #22293a;
  --ink-2:     #3d4558;   /* body text a step below the ink: descriptions, comments, tags */
  --muted:     #616b82;   /* darkened slightly: clears AA on every light surface */
  --line:      #dbe0ea;
  --line-strong: #b9c1d0; /* dashed outlines: + Felelős, the + buttons */
  --accent:    #33529e;
  --accent-hi: #4266c2;
  --accent-text: #33529e; /* the accent as text (links, project names, Szűrők törlése) */
  --accent-soft: #e6ebf6; /* an active toggle's background (the filter button) */
  --danger:    #c2382e;
  --danger-solid: #c2382e;/* the bell's count: white on it */
  --stripe-none: #c3cad8; /* a card's stripe with no deadline coming up: quiet, still visible */
  --ok:        #1f7a3d;   /* green: a finished checklist (the done column's stripe is --dl-done since v150) */
  /* The deadline stripes (v150): their own palette, apart from --danger and
     friends, which still colour errors, buttons and the bell. */
  --dl-late:   #c92f30;   /* overdue or due today: a strong signal red */
  --dl-soon:   #d8c384;   /* one to three days away: straw yellow */
  --dl-done:   #5ba0a2;   /* in the done column: blue-green */
  /* The coloured priority chips follow them (v150): Sürgős the red, Magas the yellow. */
  --urgent-bg: #ffe4e0;
  --urgent-ink: #b71920;  /* 5.5 on --urgent-bg */
  --high:      #7e5d1d;   /* Magas: 5.2 on --prio3-bg */
  --low:       #636c7d;   /* darkened: 2.33 -> 4.7 on the chip background */
  --hover:     #f2f4f9;   /* menu / row hover */
  --soft:      #eef1f6;   /* tag pills, low-priority chip */
  --count-bg:  #e2e6ed;   /* a column's card count: set off from the board (#eef0f4) */
  --count-ink: #4b5468;   /* 6:1 on it */
  --hl-bg:     #ffe58a;   /* a search match marked on a card (v153) */
  --hl-ink:    #1d2330;
  --soft2:     #f4f6fa;   /* chips, observer toggles */
  --panel:     #f8f9fc;   /* attachment tiles */
  --filter-bar: #e9ecf1;  /* the row of selected filters under the header (v126; kept for the AA of Szűrők törlése) */
  --desc-bg:   #f6f7fa;   /* description block */
  --input-bg:  #ffffff;
  --on-accent: #ffffff;   /* text on accent / coloured backgrounds */
  --warn-bg:   #fdf3e3;
  --warn-line: #ecd9b0;
  --danger-soft: #fbeeed;
  --danger-chip: #c2382e;  /* red text on --danger-soft (a disabled user's badge; the urgent chip has its own since v150) */
  --prio3-bg:  #f8eed2;
  --scroll:    #c3cbd9;
  --scroll-hi: #a7b1c4;
  --scroll-board: #b3bccd;
  --ghost-hover: rgba(30, 38, 60, .06);
  --overlay:   rgba(28, 34, 52, .45);
  --radius:    8px;
  /* Optical centring for round chips (.pav, .tags-badge). Replaced at load
     with a value measured from the font actually in use — see kb-core.js. */
  --ink-nudge: 0px;
  --shadow:    0 1px 2px rgba(30, 38, 60, .08), 0 1px 6px rgba(30, 38, 60, .05);
  --shadow-up: 0 4px 16px rgba(30, 38, 60, .16);     /* a card under the pointer, menus */
  --shadow-modal: 0 12px 40px rgba(30, 38, 60, .22); /* dialogs */
  --font:      'Geist', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* The type roles (v167): headings, and the "computer" details — dates,
     counts, initials, card numbers, tags. One face here; a look
     (themes.php) may give each its own. See "type roles" near the end. */
  --font-display: var(--font);
  --font-mono:    var(--font);
  /* Tag and project colours (v167): swatch N's chip, light. TAG_SWATCHES in
     themes.php holds these same pairs; every text is at least 6:1 on its chip. */
  --sw1-bg: #feddda; --sw1-fg: #901e21;  --sw2-bg: #fedfcc; --sw2-fg: #7b3d01;  --sw3-bg: #fde3ad; --sw3-fg: #664b00;
  --sw4-bg: #dfeeb6; --sw4-fg: #495700;  --sw5-bg: #c3f5cc; --sw5-fg: #016129;  --sw6-bg: #aff7e8; --sw6-fg: #005d51;
  --sw7-bg: #bcf1fe; --sw7-fg: #005a6a;  --sw8-bg: #d7e8fe; --sw8-fg: #024e9a;  --sw9-bg: #e3e3ff; --sw9-fg: #4b3d9d;
  --sw10-bg: #f8dbfe; --sw10-fg: #722c81;  --sw11-bg: #ffdbea; --sw11-fg: #871f5b;  --sw12-bg: #e2e6ee; --sw12-fg: #48505d;
}

/* Dark theme. Applied to <html data-theme="dark"> by an inline script in
   index.php before first paint, so switching never flashes the light UI. */
html[data-theme="dark"] {
  --bg:        #171a21;
  --surface:   #21252e;
  --ink:       #e4e8f0;
  --ink-2:     #c6cddb;
  --muted:     #98a2b6;
  --line:      #343b49;
  --line-strong: #4f5869;
  --accent:    #6f8fd6;
  --accent-hi: #86a2e0;
  --accent-text: #86a2e0;
  --accent-soft: rgba(111, 143, 214, .18);
  --danger:    #e0776a;
  --danger-solid: #b84b3c;
  --stripe-none: #4a5263;
  --ok:        #5cc98a;
  --dl-late:   #f3625a;
  --dl-soon:   #f1dda0;
  --dl-done:   #77b8ba;
  --urgent-bg: #502420;
  --urgent-ink: #fb877e;  /* 5.5 on --urgent-bg */
  --high:      #d6c38b;   /* 7.3 on --prio3-bg */
  --low:       #95a1b8;   /* 3.7 -> 4.9 on the dark chip */

  --hover:     #2a2f3a;
  --soft:      #2c3240;
  --count-bg:  #2c3240;
  --count-ink: #98a2b6;
  --hl-bg:     #6b5a12;
  --hl-ink:    #fff6d6;
  --soft2:     #2a2f3a;
  --panel:     #262b35;
  --filter-bar: #282d38;  /* lighter than the header (v130), set off from it and from the board under it */
  --desc-bg:   #262b35;
  --input-bg:  #1c2027;
  /* The accent is deliberately light so links read on a dark background, so
     button labels sit on it in near-black (5.8) rather than white (3.2). */
  --on-accent: #101319;
  --warn-bg:   #3a3222;
  --warn-line: #574a2f;
  --danger-soft: rgba(224, 119, 106, .16);
  --danger-chip: #ea8a7e;  /* the design's red reads only 4.0 on its soft red; this one 4.9 */
  --prio3-bg:  #39321e;
  --scroll:    #3f4757;
  --scroll-hi: #4d566a;
  --scroll-board: #475061;
  --ghost-hover: rgba(255, 255, 255, .07);
  --overlay:   rgba(5, 7, 12, .6);

  --shadow:    0 1px 2px rgba(0, 0, 0, .35);
  --shadow-up: 0 4px 16px rgba(0, 0, 0, .45);
  --shadow-modal: 0 12px 40px rgba(0, 0, 0, .55);
  /* The swatches (v167), dark: deep chips, light text (7:1 or more). */
  --sw1-bg: #592624; --sw1-fg: #fec4be;  --sw2-bg: #552c0a; --sw2-fg: #fec7a2;  --sw3-bg: #483401; --sw3-fg: #f3d086;
  --sw4-bg: #333d07; --sw4-fg: #cbde93;  --sw5-bg: #154222; --sw5-fg: #a4e7b2;  --sw6-bg: #014239; --sw6-fg: #84ead7;
  --sw7-bg: #023f4b; --sw7-fg: #80e5fd;  --sw8-bg: #1b395e; --sw8-fg: #b8d7fe;  --sw9-bg: #34315d; --sw9-fg: #cfcfff;
  --sw10-bg: #492a50; --sw10-fg: #f2bffd;  --sw11-bg: #54263d; --sw11-fg: #ffbfdc;  --sw12-bg: #333840; --sw12-fg: #c9d5e9;
  color-scheme: dark;                 /* native inputs and scrollbars follow */
}

* { box-sizing: border-box; }
[v-cloak] { display: none; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.45 var(--font);
}
#app { height: 100%; display: flex; flex-direction: column; }

button { font: inherit; cursor: pointer; }
input, select, textarea { font: inherit; color: var(--ink); }

/* ---------- generic controls ---------- */

.btn {
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  border-radius: 8px;
  padding: 7px 12px;
  font-weight: 500;
  transition: border-color .12s, background .12s, box-shadow .12s;
}
.btn:hover { border-color: var(--line-strong); background: var(--hover); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.primary:hover { background: var(--accent-hi); }
.btn.danger { color: var(--danger); border-color: var(--danger); background: var(--input-bg); }
.btn.danger:hover { background: var(--danger-soft); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--muted); font-weight: 400; }
.btn.ghost:hover { color: var(--ink); background: var(--ghost-hover); }
.btn:disabled { opacity: .5; cursor: default; }
/* Greyed but working (v156): the calendar button with lanes on, the lane
   button in the calendar view. */
.icon-btn.dim { opacity: .45; }
/* The calendar button in the calendar view (v158): pressed, inert. */
.toolbar .view-btn.on { background: var(--soft); color: var(--accent); cursor: default; }
.icon-btn.dim:hover, .icon-btn.dim:focus-visible { opacity: .8; }

input[type=text], input[type=email], input[type=password], input[type=date],
input[type=search], select, textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 7px 10px;
  background: var(--input-bg);
}
input:focus, select:focus, textarea:focus, .btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}
textarea { resize: vertical; min-height: 72px; }
label { display: block; font-size: 12px; color: var(--muted); margin: 10px 0 4px; }

/* ---------- toolbar ---------- */

.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  /* 11 + 36px buttons + 11 = the design's 58px header */
  padding: 11px 24px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.toolbar .brand {
  font-weight: 600;
  font-size: 16px;
  letter-spacing: -.01em;
  margin-right: 4px;
  white-space: nowrap;
}
/* The mark in front of the name: the app's own icon (the favicon and the
   installed app's icon, v135), the same in both themes (decoration only; on a
   phone it makes room for the buttons). */
.toolbar .brand::before {
  content: ""; display: inline-block; vertical-align: middle;
  width: 28px; height: 28px; margin: -4px 10px 0 0;
  background: url("icons/icon-192.png") center / 28px 28px no-repeat;
}
.toolbar .brand-name, .login h1 .brand-name { color: var(--accent-text); margin-right: .22em; }   /* the gap before "Kanban" (a space would show even without a board name); the sign-in form shows the name too (v136) */

input[type=checkbox], input[type=radio] { accent-color: var(--accent); }

/* Filter controls (v123): on every screen the filter button opens a panel
   with the search box and the four filter buttons. On a wide screen it drops
   down under the button, like the bell's; on a phone it spans the screen
   under the header (phone rules, bottom of this file). */
.filter-wrap { position: relative; flex: 0 0 auto; }
/* Icon only (v131): the count is a small accent badge on the button's
   corner, and while filters are active the button takes the accent's soft
   background. (Its label carries the count for screen readers.) */
.toolbar .filter-btn { position: relative; }
.filter-btn .tags-badge {
  position: absolute; top: -3px; right: -3px; margin: 0; pointer-events: none;
  min-width: 16px; height: 16px; padding-left: 4px; padding-right: 4px;
  padding-top: max(0px, calc(var(--ink-nudge) * 2 * 10 / 11));
  padding-bottom: max(0px, calc(var(--ink-nudge) * -2 * 10 / 11));
  font-size: 10px;
}
.filters { display: none; }
.filters.open {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 40;
  width: 440px; max-width: calc(100vw - 16px); padding: 10px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow-up);
}
.filters .search { flex: 1 1 100%; max-width: none; }
/* The search box in the header (v194): after the board's name, 40px from it
   (the toolbar's 12px gap + 28px), 280px wide, as tall as the buttons. Only
   where it fits (fitHeaderSearch in app-views.js, which uses the same sizes).
   Rounded like the user's button beside it (v195); a look with its own
   corners for fields (2077, 1985, Glass) keeps them (its field rule outweighs
   this one). */
/* Its text 1.25px higher (v196): what it shows is lower case with accents
   above and descenders below, and in Geist that ink sat 1–1.5px below the
   middle (measured at screen scales 1–2; 1.25 is the best fit for all of
   them). A look whose face sits right sets --search-lift: 0px. */
.toolbar .header-search {
  flex: 0 0 280px; width: 280px; height: 36px; margin-left: 28px; border-radius: 18px;
  padding: calc(7px - var(--search-lift, 1.25px)) 14px calc(7px + var(--search-lift, 1.25px));
}
/* The search's hint text in the look's muted ink, both boxes: the browser's
   own grey reads under 4.5:1 on every dark field (v195). */
.search::placeholder { color: var(--muted); opacity: 1; }
/* Chrome's and Safari's ✕ that empties the box: in the look's muted ink too,
   instead of the browser's blue (v195). Firefox has none. */
.search::-webkit-search-cancel-button {
  -webkit-appearance: none; appearance: none; width: 14px; height: 14px; margin-left: 6px; cursor: pointer;
  background: var(--muted);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M3 3l8 8M11 3l-8 8' stroke='%23000' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E") center / 14px 14px no-repeat;
}
.search::-webkit-search-cancel-button:hover { background: var(--ink); }
/* The chips: on a wide screen in the row under the header, not in the panel. */
.filters .filter-in-panel { display: none; }
.toolbar .spacer { flex: 1; }
/* The icon buttons stand 2px apart, as one group (wide screens; the phone
   row keeps its even gaps). */
@media (min-width: 641px) {
  .toolbar .view-btn + .lanes-btn,
  .toolbar .lanes-btn + .theme-btn, .toolbar .theme-btn + .bell-wrap { margin-left: -10px; }
}
/* Just above phone width the header's one row is tight: in Chrome, at 700px
   with a short board name and one person online, the name button went to a
   second row (v142, found by the Chrome run of layout-test.py). Smaller gaps
   there keep it on one. */
@media (min-width: 641px) and (max-width: 760px) {
  .toolbar { gap: 8px; }
  /* the icon buttons' 2px grouping (above), from the smaller gap */
  .toolbar .view-btn + .lanes-btn,
  .toolbar .lanes-btn + .theme-btn, .toolbar .theme-btn + .bell-wrap { margin-left: -6px; }
}

/* "Who is here": one monogram circle per person, at the start of the
   header's right-hand buttons (before the filter button). Your own circle is drawn exactly like everyone else's —
   the tooltip and the colour already say which one you are. Text colour comes
   from monoInk() per user, because white lettering on a light user colour is
   unreadable. */
.presence { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.pav {
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  /* Flex centres the LINE BOX, not the letters, so a monogram sits high by
     an amount that depends on the font — measured at load and applied here.
     box-sizing: border-box (set globally) keeps the circle exactly 26px, and
     padding on one side moves the centring line half that far, so the pair
     below shifts the letters down OR up as the measurement requires. */
  padding-top: max(0px, calc(var(--ink-nudge) * 2));
  padding-bottom: max(0px, calc(var(--ink-nudge) * -2));
  font-size: 11px; font-weight: 600;
  flex: 0 0 auto; cursor: pointer; user-select: none;   /* a click filters by this person */
  transition: opacity .2s;
}
/* Reached with Tab only: a mouse click leaves the circle looking as it did. */
.pav:focus { outline: none; }
.pav:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; position: relative; z-index: 1; }
/* An avatar in place of the initials: the same circle, the picture filling
   it (the letters' nudge does not apply to a picture). */
.pav-img { padding: 0; display: block; object-fit: cover; background: var(--soft); }
/* More than five people: the circles overlap a little to save room, each
   with a ring in the header's colour so they stay apart; the one under the
   pointer comes to the front. */
.presence.crowd { gap: 0; }
.presence.crowd .pav { box-shadow: 0 0 0 2px var(--surface); position: relative; }
/* 4px under the next circle, plus that circle's 2px ring: as far as it can
   go without cutting into the initials. */
.presence.crowd .pav + .pav { margin-left: -4px; }
.presence.crowd .pav:hover { z-index: 1; }
/* Avatar beállítása: the picture at its stored size, as the circle it becomes. */
.avatar-stage { display: flex; align-items: center; gap: 16px; margin: 10px 0 4px; }
.avatar-preview { width: 100px; height: 100px; border-radius: 50%; flex: 0 0 auto; object-fit: cover; background: var(--soft); }
.avatar-mono { display: flex; align-items: center; justify-content: center; font-size: 38px; font-weight: 600; }
.avatar-side { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; min-width: 0; }
.avatar-state { font-size: 13px; color: var(--muted); }
.avatar-pick { cursor: pointer; margin: 0; font-weight: 400; color: var(--ink); font-size: 14px; }
.avatar-pick:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Their tab is in the background — still here, not looking. */
.pav.idle { opacity: .38; }

.tag-chip {
  border: 1px solid var(--line);
  background: var(--soft2);
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 12px;
  color: var(--muted);
}
/* The selected filters (v131): white pills on the band.
   A coloured tag or project keeps its own colours (set inline). */
.selected-tags .tag-chip.on {
  height: 26px; padding: 0 9px 0 10px; border: 0; border-radius: 13px;
  background: var(--surface); color: var(--ink); box-shadow: var(--shadow);
  font-size: 12.5px; line-height: 26px;
}
.selected-tags .tag-chip.on:hover { box-shadow: var(--shadow-up); }
.selected-tags .person-chip.on { padding-left: 4px; gap: 6px; }


.user-menu { position: relative; }
/* A pill (v131): the circle, then the name. */
.user-btn {
  display: flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 12px 0 4px; border-radius: 18px;
  font-size: 13px; font-weight: 400;
}
.user-btn .uav, .user-btn .uav.s {
  width: 26px; height: 26px; font-size: 10px;
  padding-top: max(0px, calc(var(--ink-nudge) * 2 * 10 / 11));
  padding-bottom: max(0px, calc(var(--ink-nudge) * -2 * 10 / 11));
}
.user-btn .uav.uav-img { padding: 0; }   /* .uav.s and the line above would squeeze the picture */
/* A person's circle next to their name (user-av in app.js): their avatar, or
   their initials on their colour. 22px on cards, calendar rows, the card
   view's assignee and the editor's picker; .s = 18px in lists and pills.
   The initials get the same optical nudge as .pav, scaled to their size
   (the nudge is measured for 11px letters). */
.uav {
  width: 22px; height: 22px; border-radius: 50%; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 600; letter-spacing: -.01em; user-select: none;
  padding-top: max(0px, calc(var(--ink-nudge) * 2 * 9.5 / 11));
  padding-bottom: max(0px, calc(var(--ink-nudge) * -2 * 9.5 / 11));
}
.uav.s {
  width: 18px; height: 18px; font-size: 8px;
  padding-top: max(0px, calc(var(--ink-nudge) * 2 * 8 / 11));
  padding-bottom: max(0px, calc(var(--ink-nudge) * -2 * 8 / 11));
}
.uav::before { content: attr(data-i); }
/* .uav.uav-img, not .uav-img: .uav.s's nudge padding would otherwise
   squeeze the small pictures. */
.uav.uav-img { padding: 0; display: block; object-fit: cover; background: var(--soft); }
/* Nobody: an empty dashed circle. */
.uav.none { border: 1.5px dashed var(--muted); background: transparent; }
.menu {
  position: absolute; right: 0; top: calc(100% + 6px);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow-up);
  min-width: 180px; z-index: 40; overflow: hidden; padding: 4px;
}
.menu button { display: block; width: 100%; text-align: left; padding: 8px 12px; border: 0; border-radius: 6px; background: none; color: var(--ink); font-size: 13.5px; }
.menu button:hover { background: var(--hover); }
/* ---------- the bell (in-app notifications) ----------
   A pop-up under its button, like the user menu. The badge sits on the
   button's corner instead of beside the icon, so the button — and with it
   the header — is the same width with and without unread items. */
.bell-wrap { position: relative; }
.bell-btn { position: relative; }
/* The unread count (v131): a small red number on the icon's corner. */
.toolbar .bell-badge {
  position: absolute; top: 3px; right: 3px; margin: 0; pointer-events: none;
  min-width: 15px; height: 15px; padding-left: 3px; padding-right: 3px;
  padding-top: max(0px, calc(var(--ink-nudge) * 2 * 9.5 / 11));
  padding-bottom: max(0px, calc(var(--ink-nudge) * -2 * 9.5 / 11));
  background: var(--danger-solid); color: #fff; font-size: 9.5px;
}
.bell-panel {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 40;
  display: flex; flex-direction: column;
  width: 380px; max-width: calc(100vw - 16px); max-height: min(560px, calc(100vh - 90px));
  max-height: min(560px, calc(100dvh - 90px));   /* a phone's address bar counts in vh, not in dvh */
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow-up); overflow: hidden;
}
.bell-head { display: flex; align-items: center; gap: 8px; padding: 12px 14px 10px 16px; border-bottom: 1px solid var(--line); flex: 0 0 auto; }
.bell-head strong { font-weight: 600; }
/* "Csak olvasatlan", on a row of its own under the title */
.bell-filter { display: flex; align-items: center; gap: 6px; margin: 0; padding: 7px 14px; border-bottom: 1px solid var(--line); font-size: 13px; font-weight: 400; color: var(--ink); cursor: pointer; flex: 0 0 auto; }
.bell-filter input { width: auto; margin: 0; flex: 0 0 auto; }
.bell-list { overflow-y: auto; overscroll-behavior: contain; flex: 1 1 auto; min-height: 0; }
.bell-item {
  display: flex; gap: 10px; width: 100%; text-align: left; padding: 10px 14px;
  border: 0; border-bottom: 1px solid var(--line); border-radius: 0; background: none; color: var(--ink);
}
.bell-item:hover { background: var(--hover); }
.bell-item.unread { background: var(--soft2); }
.bell-item.unread:hover { background: var(--soft); }
.bell-item.unread { cursor: pointer; }               /* a click on an unread row marks it read */
/* The dot in front is a switch: filled = unread (click: read), a ring = read
   (click: unread again). The button is 20px so it can be hit; the dot drawn
   in it stays the 8px it was. */
.bell-dot { flex: 0 0 20px; width: 20px; height: 20px; margin: 0 -6px 0 -6px; padding: 0; border: 0; border-radius: 50%; background: none; position: relative; cursor: pointer; }
.bell-dot::before { content: ""; position: absolute; left: 6px; top: 6px; width: 8px; height: 8px; border-radius: 50%; box-sizing: border-box; border: 1.5px solid var(--muted); }
.bell-item.unread .bell-dot::before { background: var(--accent); border-color: var(--accent); }
.bell-dot:hover { background: var(--ghost-hover); }
/* The title is the link to the card. */
.bell-card { color: var(--accent-text); text-decoration: none; cursor: pointer; }
.bell-card:hover, .bell-card:focus-visible { text-decoration: underline; }
.bell-body { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.bell-line, .bell-card { overflow-wrap: anywhere; }
.bell-item.unread .bell-card { font-weight: 600; }
/* A title can be 255 characters: two lines of it name the card well enough. */
.bell-card { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
/* Up to four lines of the change or the comment; the card has the rest. */
.bell-detail {
  white-space: pre-wrap; overflow-wrap: anywhere; color: var(--muted); font-size: 13px;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; overflow: hidden;
}
.bell-time { color: var(--muted); font-size: 12px; }
.bell-list .bell-empty { padding: 18px 14px; }
.bell-more { display: block; width: 100%; padding: 10px 14px; border: 0; border-radius: 0; background: none; color: var(--ink); font-weight: 600; }
.bell-more:hover { background: var(--hover); }
.bell-foot { flex: 0 0 auto; padding: 7px 14px; border-top: 1px solid var(--line); color: var(--muted); font-size: 12px; }

/* Értesítési beállítások: one tick box per line. */
.notify-list { display: flex; flex-direction: column; gap: 10px; margin: 4px 0 6px; }
.notify-list label { display: flex; align-items: center; gap: 8px; margin: 0; font-weight: 400; cursor: pointer; font-size: 14px; color: var(--ink); }
.notify-list input { width: auto; margin: 0; flex: 0 0 auto; }
/* Admin-only entries: a shield in front. Every entry of an admin's menu is
   indented by the same amount, so the labels line up. */
.menu.has-admin button { position: relative; padding-left: 36px; white-space: nowrap; }   /* nowrap: the indent must not push a label onto two lines */
.menu-admin-icon { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); display: inline-flex; color: var(--muted); }

/* ---------- orphan banner ---------- */

.banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--warn-bg); border-bottom: 1px solid var(--warn-line);
  padding: 8px 16px; font-size: 13px;
}
.banner select { width: auto; }

/* ---------- board ---------- */

/* Panning the board with the mouse (v163, kb-board.js): the hand closed
   while it moves, and no text selected on the way. */
.board-panning, .board-panning * { cursor: grabbing !important; user-select: none !important; -webkit-user-select: none !important; }
.board {
  flex: 1;
  display: flex;
  gap: 18px;
  padding: 18px 24px 20px;
  overflow-x: auto;
  align-items: flex-start;
  scroll-snap-type: x proximity;
  /* Column snapping must leave the board's own padding in view: without
     this, a column's snap point is the very edge of the scroll area, so
     whenever the board can scroll sideways the browser pulls it 16px in and
     the left padding disappears. Same value as the padding (10px on phones). */
  scroll-padding-inline: 24px;
}
.col {
  flex: 0 0 282px;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  scroll-snap-align: start;
}
/* The column's name, its count in a small pill, then + (v131). */
.col-head {
  display: flex; align-items: center; gap: 8px;
  min-height: 36px; padding: 0 2px 8px 2px; box-sizing: border-box;
  flex: 0 0 auto;   /* a column whose cards overflow must not squeeze it (it would sit out of line) */
}
.col-head h2 {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--ink);
}
.col-head .count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px; margin-right: auto;
  background: var(--count-bg); color: var(--count-ink); font-size: 11.5px; font-variant-numeric: tabular-nums;
}
.col-head .add {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 28px; height: 28px; margin-left: 2px; padding: 0; border-radius: 6px;
  font-size: 19px; font-weight: 400; line-height: 1;
}
.col-head .hidden-toggle { border-radius: 6px; }

.col-body {
  flex: 1; min-height: 0; overflow-y: auto; padding-bottom: 6px;
  display: flex; flex-direction: column;
}

.lane-label {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 500; color: var(--muted);
  margin: 16px 2px 6px;
}
/* The label does not wrap, and a flex item refuses to shrink below its own
   content width without this — so a very long tag would widen the column
   rather than ellipsising. (.card .tag-line wraps, so it needs nothing.) */
.lane-label .tag { min-width: 0; }
/* A person's name (v168): one line, cut with … (a look's wide face would wrap it). */
.lane-label .lane-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* [glass] The person's circle before it (v189): only the Glass look shows it (glass.css). */
.lane-label .lane-av { display: none; }
/* A search match on a card (v153): the title, the project, a tag. The ink is
   set too, so the mark stays readable on a tag an admin has coloured. */
mark.hl { background: var(--hl-bg); color: var(--hl-ink); border-radius: 3px; padding: 0 1px; margin: 0 -1px; }
/* The lane's card count in this column (v153): the column count's pill, a size smaller. */
.lane-label .lane-count {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--count-bg); color: var(--count-ink); font-size: 11px; font-weight: 500; font-variant-numeric: tabular-nums;
}
/* Only the first lane still showing skips the gap. A class rather than
   :first-child: a lane hidden by the people or tag filter is still the first
   child. (Scoped to the block either way: every label is the first child of
   its own block.) */
.lane-block.lead .lane-label { margin-top: 0; }

.cards {
  min-height: 14px; display: flex; flex-direction: column; gap: 8px; padding: 2px 2px 4px;
  flex: 1 0 auto;          /* fill the column so the whole body accepts drops */
}
.cards.lane {
  min-height: 44px; border: 1px dashed transparent; border-radius: var(--radius);
  flex: 1 0 auto;
}
.cards.lane:empty { border-color: var(--line); }

/* ---------- card ---------- */

.card {
  position: relative;
  display: flex; flex-direction: column; gap: 6px;
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 10px 12px 11px 13px;
  cursor: grab;
  border-left: 4px solid var(--card-color, #8e99ad);
  transition: box-shadow .15s;
}
.card:hover { box-shadow: var(--shadow-up); }
/* Reached with Tab (Enter or Space opens it): a ring. A mouse click, which
   also focuses the card, leaves it as it was. Offset 0: the list's 2px
   padding is all the room there is before the column clips it. */
.card:focus { outline: none; }
.card:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
.card.sortable-ghost { opacity: .35; }
.card.sortable-drag { transform: rotate(1.5deg); cursor: grabbing; }

/* The card (v131): who, title, project, then the badges and the tags, 6px
   apart (the card is a flex column). */
.card .who-line {
  display: flex; align-items: center; gap: 7px; min-height: 22px;
  font-size: 12px; color: var(--muted);
}
.card .title { font-size: 14px; font-weight: 500; line-height: 1.35; word-break: break-word; }
.card .title a { color: var(--accent-text); }
.card .tag-line {
  display: flex; flex-wrap: wrap; gap: 5px;
  font-size: 11.5px; color: var(--muted);
}
.card .meta {
  display: flex; align-items: center; gap: 6px 12px; flex-wrap: wrap;
  font-size: 12px; color: var(--muted);
}
/* The badges: an icon (14px, the app's 2px stroke) and a number. */
.badge-ico { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.badge-ico svg { flex: 0 0 auto; }
/* The priority chip: a rounded pill on a soft background. */
.prio {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px; border-radius: 10px;
  font-weight: 500; font-size: 12px; white-space: nowrap;
}
.prio.p4 { background: var(--urgent-bg); color: var(--urgent-ink); }
.prio.p3 { background: var(--prio3-bg); color: var(--high); }
.prio.p1 { background: var(--soft); color: var(--low); }
/* Normal (p2) intentionally has no chip — quiet by default */

.deadline { display: inline-flex; align-items: center; gap: 4px; font-variant-numeric: tabular-nums; }
/* The date on a card and in the calendar is plain text (v148): the card's
   stripe carries the deadline's colour, and the same colour again as bold
   text looked raw. The card view's and the editor's deadline pill are plain
   too since v149, when those dialogs got the stripe. */

.tag {
  /* nowrap is deliberate — a chip reads badly broken across lines. Real tags
     are short (the longest in use is 14 chars), but nothing caps a single
     tag's length, so an absurd one truncates rather than stretching the card;
     the full text stays in the title attribute.

     Deliberately inline-BLOCK, not inline-flex. text-overflow does not apply
     to a flex container, so the ellipsis would never appear; and `overflow:
     hidden` on an inline-level box moves its baseline to the bottom margin
     edge, which would drop the chip out of line with the text beside it in
     the swimlane label. inline-block keeps the normal text baseline and makes
     the ellipsis work. */
  display: inline-block; white-space: nowrap; vertical-align: middle;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  padding: 0 8px; border-radius: 10px;
  background: var(--soft); color: var(--ink-2);
  font-size: 11.5px; line-height: 20px;
}
/* The search found the card through one of its comments. */
.card .cmt.hit { color: var(--accent-text); font-weight: 600; }
.who { display: inline-flex; align-items: center; gap: 6px; }
.card .title a { -webkit-user-drag: none; user-drag: none; }

/* Ticket link: pinned to the card's top-right corner. .card is already
   position:relative, and centred on the first row (the 22px circle's line).
   The .ticketed modifier keeps that row clear of it. */
.card .ticket-link {
  position: absolute; top: 14px; right: 12px;
  display: inline-flex; line-height: 0;
  color: var(--muted);
  -webkit-user-drag: none; user-drag: none;
}
.card .ticket-link:hover { color: var(--accent); }
.card.ticketed .who-line, .card.ticketed .title { padding-right: 20px; }
.card .ticket-link svg { width: 14px; height: 14px; }


/* ---------- modals ---------- */

.overlay {
  position: fixed; inset: 0; z-index: 50;
  background: var(--overlay);
  display: flex; align-items: flex-start; justify-content: center;
  /* No top padding here: a pinned title row (see .modal > .detail-head)
     stops at the scroll area's padding, which would leave a strip of the
     dialog showing above it. The gap above the dialog is its own margin. */
  padding: 0 16px 16px;
  overflow-y: auto;
  /* When the browser scrolls a field into view (tabbing to it, say), keep it
     clear of the pinned title row (100px since v126: the URL line under the
     title makes the row about 80px tall). */
  scroll-padding-top: 100px;
}
.overlay > .modal { margin-top: 6vh; }
.modal {
  background: var(--surface);
  border-radius: 12px;
  box-shadow: var(--shadow-modal);
  width: 100%; max-width: 560px;
  padding: 20px 22px;
  /* Backstop: nothing inside a dialog may paint outside it, whatever new
     text surface gets added later. The rules above are still worth having —
     this one only catches what they miss. */
  overflow-wrap: anywhere;
}
.modal.narrow { max-width: 380px; }
/* Card detail, card editor and the admin's project list: 50% wider than the standard 560px. */
.modal.wide { max-width: 840px; }
.modal h3 { margin: 0 0 6px; font-size: 16px; font-weight: 600; letter-spacing: -.005em; }
.modal .row { display: flex; gap: 12px; }
.modal .row > div { flex: 1; }
.modal .actions { display: flex; gap: 8px; margin-top: 18px; }
.modal .actions .spacer { flex: 1; }

/* Same shrink trap as .comment-form: without min-width:0 a long unbroken
   title refuses to shrink and pushes the buttons narrow enough to wrap their
   own labels. The title is the part that should give way, not the controls. */
.detail-head { display: flex; align-items: flex-start; gap: 8px; }
.detail-head h3 { flex: 1; min-width: 0; overflow-wrap: anywhere; line-height: 1.35; }
.detail-head .btn { flex: 0 0 auto; white-space: nowrap; }
/* The head's icon buttons (link, pencil, ✕): 32px squares in muted ink. */
.detail-head > .btn.ghost {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0; border: 0; border-radius: 8px; font-size: 15px;
}
/* A dialog's title row (title, Szerkesztés, ✕) stays pinned while the dialog
   scrolls: a phone has no Escape key, and on a long dialog the dark area to
   click (dialogs close on a click outside since v119) can be out of reach,
   so the ✕ must always be in reach. The dialog scrolls inside
   its backdrop (.overlay) and doesn't clip, so sticky works; the negative
   margins let the row's background cover the dialog's padding edge to edge. */
.modal > .detail-head {
  position: sticky; top: 0; z-index: 3;
  margin: -20px -22px 16px; padding: 20px 20px 14px 22px;
  background: var(--surface); border-radius: 12px 12px 0 0;
  border-bottom: 1px solid var(--line);
}
/* The card view (v131): the body is indented to the title, past the link
   icon (22 + 32 + 8 = 62px), and by as much on the right (v135); on a phone
   it is not. */
.modal.card-view { padding-left: 62px; padding-right: 62px; }
.modal.card-view > .detail-head { margin-left: -62px; margin-right: -62px; }
/* The open card's deadline stripe (v149), as on the board: the card view and
   the editor carry the card's 4px left border in its colour (the editor's
   follows the deadline and column being edited). The 4px come off the left
   padding, so nothing inside moves. */
.modal.card-view, .modal.card-edit { border-left: 4px solid var(--card-color, var(--stripe-none)); }
.modal.card-view { padding-left: 58px; }
.modal.card-view > .detail-head { margin-left: -58px; padding-left: 18px; }
.modal.card-edit { padding-left: 18px; }
.modal.card-edit > .detail-head { margin-left: -18px; padding-left: 18px; }
.card-view .detail-head h3 { font-size: 19px; letter-spacing: -.01em; margin-bottom: 0; }
.modal.card-edit .actions { margin-top: 20px; }

/* ---------- Névjegy ---------- */
.about-head { text-align: center; padding: 4px 0 14px; }
.about-icon { display: block; margin: 0 auto 8px; border-radius: 16px; }
.about-name { font-size: 18px; font-weight: 650; }
.about-board { color: var(--muted); font-size: 13px; }
.about-version { color: var(--muted); font-size: 13px; margin-top: 2px; }
.about-section { border-top: 1px solid var(--line); padding: 12px 0; font-size: 13px; line-height: 1.5; }
.about-copy { font-weight: 600; }
.about-contact { margin-top: 6px; }
.about-label { color: var(--muted); font-size: 12px; margin-bottom: 4px; }
.about-components { width: 100%; border-collapse: collapse; margin-bottom: 6px; }
.about-components td { padding: 2px 0; }
.about-components td:last-child { text-align: right; color: var(--muted); }
.about a { color: var(--accent); }

/* The card's info (v111): a grid of labelled fields, two per row; one per
   row on a phone. Observers and tags take a whole row. Column, priority,
   assignee and project are outlined pills so they read as status, not as
   tags. */
/* No line of its own under the fields (v123): the description's shaded box,
   or the next section's line, closes them off. */
.detail-info { margin: 0 0 18px; font-size: 13px; }
.detail-info .info-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px 28px; }
.detail-info .info-field { display: grid; grid-template-columns: 92px minmax(0, 1fr); align-items: center; gap: 10px; min-width: 0; min-height: 26px; }
.detail-info .info-wide { grid-column: 1 / -1; }
.detail-info .info-label { color: var(--muted); font-size: 12px; }
.detail-info .info-value { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; }
.detail-info .info-tags .tag { max-width: 100%; }
/* The title block: the title, and under it the URL with the same inset
   (v126: inside the pinned title row), shortened with … when long. */
.detail-title { flex: 1; min-width: 0; }
.detail-url { display: flex; min-width: 0; margin: 3px 0 0; font-size: 13px; font-weight: 400; }
.detail-url a { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; min-width: 0; color: var(--accent-text); text-decoration: none; }
.detail-url a:hover { color: var(--accent-hi); text-decoration: underline; }
.detail-url .url-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.detail-url svg { flex: 0 0 auto; }
/* Létrehozta: the creator's name and, under it, when (no circle since v126). */
.detail-info .info-created .created-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.detail-info .info-created .created-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.detail-info .info-created .created-at { color: var(--muted); font-size: 11.5px; }
/* The fields' values (v131): round 26px pills with a ▾. */
.detail-info .info-pill {
  display: inline-flex; align-items: center; height: 26px;
  border: 1px solid var(--line); border-radius: 13px; padding: 0 10px;
  font-size: 12.5px; color: var(--ink); line-height: 1.2; background: var(--surface);
}
.detail-info .info-none { color: var(--muted); }
/* Column, priority, assignee and project open a picker: buttons that keep their look,
   with a small ▾ so it's clear they can be clicked (phones have no hover). */
.detail-info .pick-trigger { font: inherit; font-size: 12.5px; cursor: pointer; background: var(--surface); display: inline-flex; align-items: center; gap: 5px; }
.detail-info .pick-trigger:hover, .detail-info .pick-trigger:focus-visible { background: var(--hover); border-color: var(--line-strong); }
.detail-info .pick-caret { font-size: 10px; color: var(--muted); margin-left: -1px; }
/* The priority pill wears the board's chip colours. */
.detail-info .pick-trigger.pp4 { background: var(--urgent-bg); color: var(--urgent-ink); font-weight: 500; }
.detail-info .pick-trigger.pp3 { background: var(--prio3-bg); color: var(--high); font-weight: 500; }
.detail-info .pick-trigger.pp1 { background: var(--soft); color: var(--low); }
.detail-info .pick-trigger.pp4 .pick-caret, .detail-info .pick-trigger.pp3 .pick-caret, .detail-info .pick-trigger.pp1 .pick-caret { color: inherit; }
.detail-info .pick-trigger.pp4:hover, .detail-info .pick-trigger.pp3:hover, .detail-info .pick-trigger.pp1:hover { filter: brightness(.97); }
/* The assignee's 22px circle fills the pill's rounded end instead of making
   the pill taller than the other three. */
.detail-info .pick-assignee, .detail-info .epick-assignee { padding-left: 2px; gap: 6px; }
.detail-info .pick-assignee .uav, .detail-info .epick-assignee .uav { margin: 0; }
.detail-pick {
  position: fixed; z-index: 60; min-width: 160px; max-height: 60vh; overflow-y: auto;
  max-width: calc(100vw - 16px);   /* never wider than a phone's screen (app.js keeps it on it) */
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--shadow-up);
  display: flex; flex-direction: column; padding: 4px;
}
.detail-pick button {
  display: flex; align-items: center; gap: 8px; text-align: left; font: inherit; font-size: 13px;
  background: none; border: 0; border-radius: 6px; padding: 7px 10px; cursor: pointer; color: var(--ink);
}
.detail-pick button:not(.btn):hover, .detail-pick button:not(.btn):focus-visible { background: var(--hover); }
/* :not(.btn): the deadline panel's Mentés / Kész is a .btn.primary, whose
   accent background the rule above would replace with the hover grey —
   leaving its light label on a light ground, invisible exactly when the
   keyboard reaches it. The .btn rules give those their own hover and focus. */
.detail-pick button.on { font-weight: 600; }
.detail-pick .pick-check { margin-left: auto; color: var(--accent); }
/* The deadline pill's panel: a date field and its two buttons, not a list. */
.detail-pick.deadline-pick { padding: 10px; overflow: visible; }
.deadline-pick input { display: block; width: 100%; margin: 0 0 8px; }
.deadline-pick-btns { display: flex; gap: 6px; }
.detail-pick .deadline-pick-btns button { display: inline-flex; width: auto; padding: 3px 8px; font-size: 11px; border: 1px solid var(--line); border-radius: 6px; }
.detail-pick .deadline-pick-btns button.primary { border-color: var(--accent); }
/* A place files can be dropped on, while a file is dragged over it. */
.drop-on, textarea.drop-on:focus { outline: 2px dashed var(--accent); outline-offset: 1px; }   /* :focus too — a focused box has an outline rule of its own, which would win */
.fmt-btn.fmt-attach { display: inline-flex; align-items: center; justify-content: center; }
/* A file (not a picture) attached to a comment: a link with its name. */
.cmt-file-link { overflow-wrap: anywhere; }
/* The card view's pencil: the same size as the ✕ beside it (v131: borderless 32px squares). */
.icon-edit { display: inline-flex; align-items: center; justify-content: center; }
/* The link icon in front of the card's title: the same size as the pencil and ✕;
   a little closer to the title than the row's 10px gap. */
.icon-link { display: inline-flex; align-items: center; justify-content: center; }
/* .btn in front: .btn.ghost:hover would otherwise turn the ✓ back to plain ink
   while the pointer is still on it. */
.btn.icon-link.copied, .btn.icon-link.copied:hover { color: var(--accent); }
/* The title's first line is centred on the link icon: the icon button is 32px
   tall, a title line 1.35em, so the title starts half the difference lower. Further lines of a
   long title simply follow below. */
.detail-head h3 { padding-top: calc((32px - 1.35em) / 2); }

/* Text for screen readers only (labels the tooltips show on hover). */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.detail-desc {
  white-space: pre-wrap; background: var(--desc-bg); border-radius: 8px; padding: 12px 14px; margin-bottom: 18px;
  font-size: 14px; line-height: 1.6; color: var(--ink-2);
}

.comments { padding-top: 12px; }
/* Hozzászólások / Napló (v153): two tabs on a line across the dialog, the
   one shown underlined in the accent colour; the comments' order button at
   the right end of the line, while the comments are shown. */
.detail-tabs-row { display: flex; align-items: flex-end; gap: 8px; margin-top: 18px; border-bottom: 1px solid var(--line); }
.detail-tabs { display: flex; gap: 4px; }
.detail-tab { display: inline-flex; align-items: center; gap: 6px; padding: 8px 10px 7px; margin-bottom: -1px;
  border: 0; border-bottom: 2px solid transparent; background: none; color: var(--muted); font: inherit;
  font-size: 13px; font-weight: 600; cursor: pointer; border-radius: 6px 6px 0 0; }
.detail-tab:hover { color: var(--ink); background: var(--ghost-hover); }
.detail-tab.on { color: var(--ink); border-bottom-color: var(--accent); }
.detail-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.detail-tab .tab-count { min-width: 18px; padding: 0 5px; border-radius: 9px; background: var(--count-bg); color: var(--count-ink);
  font-size: 11.5px; font-weight: 500; line-height: 18px; text-align: center; font-variant-numeric: tabular-nums; }
.detail-tabs-row .cmt-order { margin: 0 0 4px auto; }
/* A comment, chat style (v126): the author's circle, then the name (bold),
   the time (muted) and, at the right, edit and delete as faint icons; the
   text is indented under the name. A thin line between comments. */
.comment { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0; border-top: 1px solid var(--line); }
.comment-list .comment:first-of-type { border-top: 0; padding-top: 6px; }
.comment-list .comment:last-of-type { padding-bottom: 0; }
.comment .cmt-av { flex: 0 0 auto; }
.comment .cmt-main { flex: 1 1 auto; min-width: 0; }
.comment .head { font-size: 12px; color: var(--muted); display: flex; gap: 8px; align-items: center; min-height: 22px; }
.comment .head .who { color: var(--ink); font-weight: 600; font-size: 13px; }
.comment .cmt-actions { margin-left: auto; display: inline-flex; gap: 2px; opacity: .75; transition: opacity .15s; }
.comment:hover .cmt-actions, .comment .cmt-actions:focus-within { opacity: 1; }
@media (hover: none) { .comment .cmt-actions { opacity: .8; } }   /* no hover on a touch screen */
.comment .head .btn.cmt-icon { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0; border-radius: 6px; }
/* A URL has no spaces, so pre-wrap alone cannot break it: the token runs
   straight out of the dialog and paints over the board behind it. "anywhere"
   rather than break-all because a comment is prose — break-all splits words
   mid-syllable even when the line had room, "anywhere" only breaks a token
   that would otherwise overflow. */
.comment .body { white-space: pre-wrap; margin-top: 2px; overflow-wrap: anywhere; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.comment .body a { color: var(--accent-text); overflow-wrap: anywhere; }
/* Küldés sits under the box, at its right (v131; it was beside it).
   min-width: 0 lets the textarea shrink with a narrow dialog. */
.comment-form { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; align-items: stretch; }
.comment-form > .btn { align-self: flex-end; height: 32px; padding: 0 14px; font-size: 13px; }
.comment-form textarea { border-radius: 8px; padding: 9px 11px; }
.comment-form textarea { min-height: 40px; min-width: 0; }
/* The new-comment box: two lines' worth by default (v126). */
.comment-form #fmt-new { min-height: 80px; }
/* Holds a comment box and its @-suggestion list. In the new-comment row it is
   the flex item the textarea used to be. */
.mention-wrap { position: relative; flex: 1 1 auto; min-width: 0; }
.mention-wrap textarea { display: block; width: 100%; }
.mention-pop {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 45;
  min-width: 220px; max-width: 100%; max-height: 220px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow-up); padding: 4px;
}
.mention-pop.up { top: auto; bottom: calc(100% + 4px); }   /* no room below: open above */
/* The description's box (v154): the @ list opens under it, or above it. */
.desc-box { position: relative; }
/* ---------- formatting: toolbar and formatted text ---------- */
.fmt-bar { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; margin-bottom: 4px; }
.fmt-btn {
  min-width: 28px; height: 26px; padding: 0 7px; border: 1px solid transparent; border-radius: 5px;
  background: none; color: var(--muted); font-size: 13px; line-height: 1; cursor: pointer;
}
.fmt-btn:hover, .fmt-btn:focus-visible { background: var(--hover); color: var(--ink); border-color: var(--line); }
.fmt-btn.fmt-bold { font-weight: 700; }
.fmt-btn.fmt-italic { font-style: italic; font-family: Georgia, serif; }
.fmt-btn.fmt-strike { text-decoration: line-through; }
.fmt-btn.fmt-code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
.fmt-bar .spacer { flex: 1 1 auto; }
.fmt-btn.fmt-preview.on { background: var(--soft); color: var(--ink); border-color: var(--line); }
/* The card editor's description: 281px — an ordinary text box is 72px; v113
   made this one three times that (216px), v114 made it 130% of that again —
   since this is where most of a card's text is written. It can still be
   dragged taller. The preview takes the same height, so
   switching between the two does not make the dialog jump. */
#fmt-desc { min-height: 281px; }
.fmt-preview-box { min-height: 281px; margin-bottom: 10px; }
.fmt-preview-box:empty::before { content: attr(data-empty); color: var(--muted); }

/* Formatted descriptions and comments. These containers keep their line
   breaks (pre-wrap), and the formatter emits no newlines inside its own
   blocks, so lists and quotes don't pick up blank lines. */
.rich ul, .rich ol { margin: 2px 0; padding-left: 22px; }
.rich li { margin: 1px 0; }
.rich blockquote { margin: 4px 0; padding: 1px 0 1px 10px; border-left: 3px solid var(--line); color: var(--muted); }
.rich code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .9em;
  background: var(--soft); border-radius: 4px; padding: 0 4px;
}
.rich del { color: var(--muted); }
.rich .md-h { margin: 8px 0 2px; font-weight: 650; line-height: 1.3; }
.rich .md-blank { height: 1.4em; }
.rich h4.md-h { font-size: 16px; }
.rich h5.md-h { font-size: 15px; }
.rich h6.md-h { font-size: 14px; }

.mention-pop .opt {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 10px; border-radius: 6px; cursor: pointer; font-size: 13px;
}
.mention-pop .opt.active, .mention-pop .opt:hover { background: var(--hover); }
/* "@Name" in a posted comment; a mention of you stands out. */
.mention { color: var(--accent-text); font-weight: 500; }
.mention.me { background: var(--accent); color: var(--on-accent); border-radius: 4px; padding: 0 3px; }
.comment-form .btn { flex: 0 0 auto; white-space: nowrap; }

.log-list { padding-top: 10px; font-size: 12px; }
.log-row { display: flex; gap: 8px; padding: 3px 0; color: var(--muted); }
.log-row .when { flex: 0 0 128px; font-variant-numeric: tabular-nums; }
.log-row .what { color: var(--ink); }
/* Field diffs carry raw values — a Ticket URL change puts a full URL here. */
.log-row .diff { color: var(--muted); overflow-wrap: anywhere; min-width: 0; }

/* ---------- login ---------- */

.login-wrap { flex: 1; display: flex; align-items: center; justify-content: center; padding: 20px; }
.login {
  background: var(--surface); border-radius: 14px; box-shadow: var(--shadow-modal);
  width: 100%; max-width: 360px; padding: 28px 28px 24px;
}
.login h1 { display: flex; align-items: center; gap: 10px; margin: 0 0 6px; font-size: 20px; font-weight: 600; letter-spacing: -.01em; }
/* The header's mark (the app's icon), in front of the sign-in form's name. */
.login h1::before {
  content: ""; flex: 0 0 auto; width: 28px; height: 28px;
  background: url("icons/icon-192.png") center / 28px 28px no-repeat;
}
.login .sub { color: var(--muted); font-size: 13px; margin-bottom: 12px; }
.login .btn { width: 100%; margin-top: 16px; }
.login .remember { display: flex; align-items: center; gap: 7px; margin-top: 12px; font-size: 13px; color: var(--muted); }
.login .remember input { width: auto; }
/* Elfelejtett jelszó? / Vissza a bejelentkezéshez: a link under the button. */
.login .login-link { display: block; margin: 14px auto 0; padding: 0; border: 0; background: none; color: var(--accent-text); font: inherit; font-size: 13px; text-decoration: underline; cursor: pointer; }
.login .reset-note { margin: 10px 0 4px; line-height: 1.5; overflow-wrap: anywhere; }

/* ---------- toasts ---------- */

/* width: max-content — centred with left: 50%, the box would otherwise be
   at most half the screen wide, and on a phone a message with a button
   (Visszavonás) broke onto two lines. Each .toast caps its own width. */
.toasts { position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%); z-index: 90; display: flex; flex-direction: column; gap: 8px; width: max-content; max-width: 92vw; }
.toast {
  background: var(--ink); color: var(--surface); border-radius: 10px;
  padding: 10px 16px; font-size: 13.5px; box-shadow: var(--shadow-modal);
  /* Server messages can quote a value back — the tag-length error lists the
     tags. Toasts sit outside any dialog, so they need their own rule. */
  max-width: min(92vw, 520px); overflow-wrap: anywhere;
}
.toast.err { background: var(--danger); }
/* A message with a button in it (Visszavonás). */
.toast-action { margin-left: 14px; padding: 0; border: 0; background: none; color: inherit; font: inherit; font-weight: 700; text-decoration: underline; }
/* Billentyűparancsok */
.shortcut-table { border-collapse: collapse; margin: 4px 0 8px; }
.shortcut-table th { text-align: left; padding: 5px 16px 5px 0; white-space: nowrap; font-weight: 400; vertical-align: top; }
.shortcut-table td { padding: 5px 0; }
.shortcut-table kbd { font: inherit; font-size: 12px; padding: 1px 6px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; background: var(--soft2); }

.err-msg { color: var(--danger); font-size: 13px; margin-top: 8px; }

/* ---------- calendar view ----------
   The cards that have a deadline, as a list by date. Takes the board's place
   and scrolls by itself, so the header stays put. */
.agenda { flex: 1; min-height: 0; overflow-y: auto; padding: 18px 24px 24px; }
/* A table since v171: one header row, then a panel per group whose rows are
   divided by lines. Header and rows share the grid, so the columns line up
   across the panels. 20px on the left = the row's 4px stripe + 16px. */
.agenda-head, .agenda-group { max-width: 1100px; margin: 0 auto; }
.agenda-group { margin-bottom: 20px; }
.agenda-head, .agenda-row {
  display: grid; grid-template-columns: 136px minmax(0, 1fr) 180px 160px; column-gap: 18px; align-items: center;
}
.agenda-head {
  padding: 0 16px 8px 20px; font-size: 11px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--muted);
}
/* Like a column's head: the name, its count in a small pill. */
.agenda-group h2 {
  display: flex; align-items: center; gap: 8px; margin: 0 2px 8px; min-height: 24px;
  font-size: 13px; font-weight: 600; letter-spacing: .01em; color: var(--ink);
}
.agenda-group h2 .count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px;
  background: var(--soft); color: var(--muted); font-size: 11.5px; font-weight: 400; font-variant-numeric: tabular-nums;
}
.agenda-panel { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
.agenda-row {
  border-left: 4px solid var(--card-color, var(--stripe-none));
  padding: 11px 16px; cursor: pointer; transition: background .15s;
}
.agenda-row + .agenda-row { border-top: 1px solid var(--line); }
.agenda-row:hover { background: var(--hover); }
.agenda-row:focus-visible { background: var(--hover); outline: 2px solid var(--accent); outline-offset: -2px; }
/* The date: in words on top (red once due), the date itself below. */
.agenda-row .agenda-when { flex-direction: column; align-items: flex-start; gap: 1px; line-height: 1.3; white-space: nowrap; }
.agenda-rel { font-size: 13px; font-weight: 600; color: var(--ink); }
.agenda-when.over .agenda-rel { color: var(--danger); }
.agenda-when.fin .agenda-rel { font-weight: 400; color: var(--muted); }
.agenda-date { font-size: 12px; color: var(--muted); }
.agenda-main { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.agenda-title { font-weight: 500; overflow-wrap: anywhere; }
.agenda-sub { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: 12px; }
.agenda-project { color: var(--accent-text); margin-right: 4px; }
.agenda-who { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 13px; color: var(--ink-2); }
.agenda-who > span:last-child, .agenda-column { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agenda-who.none { color: var(--muted); }
.agenda-column { font-size: 13px; color: var(--muted); }
@media (min-width: 641px) and (max-width: 900px) {
  .agenda-head, .agenda-row { grid-template-columns: 128px minmax(0, 1fr) 130px 110px; column-gap: 14px; }
}
.agenda .empty-note { max-width: 1100px; margin: 30px auto; text-align: center; }
.empty-note { color: var(--muted); font-size: 13px; padding: 6px 2px; }

/* ---------- mobile ---------- */

@media (max-width: 640px) {
  .detail-info .info-grid { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .detail-info .info-field { grid-template-columns: 84px minmax(0, 1fr); }
}
/* Címkék kezelése: the search box above the list */
.admin-tags-search { margin: 4px 0 8px; }
/* Saved views in the filter panel (v156) */
.views-box { flex: 1 1 100%; min-width: 0; margin-top: 6px; padding-top: 8px; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 4px; }
.views-head { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.views-head .views-default { margin-left: auto; }
.view-row { display: flex; align-items: center; gap: 2px; min-width: 0; border-radius: 6px; padding: 1px 2px; }
.view-row.on { background: var(--soft); }
.view-row .view-name { flex: 1 1 auto; min-width: 0; text-align: left; border: 0; background: none; color: var(--ink); font: inherit; font-size: 13.5px;
  padding: 4px 6px; border-radius: 5px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.view-row .view-name:hover { background: var(--ghost-hover); }
.view-row.on .view-name { font-weight: 600; }
.view-row .view-star.on { color: var(--accent); }
.view-row .view-link { display: inline-flex; align-items: center; justify-content: center; }
.view-row .view-rename { flex: 1 1 auto; min-width: 0; }
.view-new { display: flex; gap: 6px; align-items: center; margin-top: 2px; }
.view-new input { flex: 1 1 auto; min-width: 0; }
/* Értesítési beállítások: pop-ups on this device (v155) */
.push-box { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.push-box .admin-hint { margin: 4px 0 8px; }
.push-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.push-row .push-state { flex: 1 1 200px; font-size: 13px; color: var(--muted); }
.push-row .push-state.ps-on { color: var(--ink); font-weight: 600; }
/* Törölt kártyák: the same, above the list (v152) */
.trash-search { margin: 4px 0 8px; }
@media (max-width: 640px) {
  .board { scroll-snap-type: x mandatory; padding: 10px; gap: 10px; scroll-padding-inline: 10px; }
  .col { flex: 0 0 86vw; }
  .modal .row { flex-direction: column; gap: 0; }
  .log-row { flex-wrap: wrap; }

  /* One header row: name, filter button, calendar, lanes, theme, bell,
     your colour (the + floats at the bottom right since v159; in the row
     until v158).
     Everything that filters lives in the panel the filter button opens. */
  .toolbar { position: relative; flex-wrap: nowrap; gap: 6px; padding: 8px 10px; }
  .toolbar .brand { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
  .toolbar .brand::before { display: none; }   /* the mark: no room on one row */
  .presence { display: none; }        /* no room on one row */
  .user-btn .user-name { display: none; }
  .user-btn { padding: 0 4px; }                 /* the circle alone, in its pill */
  /* The card view's body is not indented past the link icon here. */
  .modal.card-view { padding-left: 18px; padding-right: 22px; }   /* 18 + the 4px stripe */
  .modal.card-view > .detail-head { margin-left: -18px; margin-right: -22px; }
  /* The bell's panel spans the screen under the header (the toolbar is the
     positioned ancestor here), wherever its button sits in the row. */
  .bell-wrap { position: static; }
  .bell-panel { left: 8px; right: 8px; top: calc(100% + 4px); width: auto; max-width: none; }

  .filter-wrap { position: static; }        /* the panel spans the toolbar, not the button */
  .filters.open {
    left: 0; right: 0; top: 100%; z-index: 35; width: auto; max-width: none;
    border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  }
  /* The selected filters live in the panel here, not in a row of their own. */
  .toolbar .filter-bar { display: none; }   /* .toolbar: .selected-tags, later in the file, sets display too */
  .filters .filter-in-panel { display: flex; }
  /* Calendar view: no header row; a row stacks: the date and the column on
     the first line, then the card, then who has it. */
  .agenda { padding: 10px 10px 20px; }
  .agenda-head { display: none; }
  .agenda-row { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 10px; padding: 10px 12px; }
  /* the date goes under the words when a long column name leaves no room */
  .agenda-row .agenda-when { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 8px; min-width: 0; }
  .agenda-column { grid-column: 2; grid-row: 1; align-self: start; max-width: 40vw; font-size: 12px; }
  .agenda-main, .agenda-who { grid-column: 1 / -1; }
  .agenda-who { font-size: 12px; }
  /* Chips wrap onto as many lines as they need, never a sideways scroller. */
  .filters .selected-tags { flex: 1 1 100%; max-width: none; flex-wrap: wrap; overflow: visible; }
  .filters .selected-tags .tag-chip { border: 1px solid var(--line); }   /* white chips on the white panel (v131) */

}

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

/* ---------- quick assign & observers ---------- */

.assign-wrap { position: relative; display: inline-flex; }
/* + Felelős: a dashed pill as tall as the circle it stands in for. */
.assign-btn {
  display: inline-flex; align-items: center; height: 22px;
  border: 1px dashed var(--line-strong); background: none; color: var(--muted);
  border-radius: 11px; padding: 0 9px; font-size: 11.5px; cursor: pointer;
}
.assign-btn:hover { color: var(--ink); border-color: var(--muted); }
.assign-pop {
  position: fixed; z-index: 60;   /* fixed: .col-body scrolls and would clip it */
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: var(--shadow-up); padding: 4px;
  display: flex; flex-direction: column; min-width: 150px;
  /* A long list of people scrolls inside it rather than running off the
     screen; and it is never wider than a phone's screen. */
  max-height: 60vh; overflow-y: auto; max-width: calc(100vw - 16px);
}
.assign-pop button {
  display: flex; align-items: center; gap: 7px;
  border: 0; border-radius: 6px; background: none; padding: 7px 10px; text-align: left; font-size: 13px; color: var(--ink);
}
.assign-pop button:hover { background: var(--hover); }

/* The editor's fields (v126): the card view's grid under the description,
   a little air above it; Én is a pill beside the assignee's. */
.edit-info { margin: 14px 0 6px; }
.edit-pick .pick-add { color: var(--accent); border-top: 1px solid var(--line); border-radius: 0 0 5px 5px; }

.obs-row { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
/* An observer: a pill with their circle, name and × (editor and card view alike). */
.obs-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 24px;
  border: 1px solid var(--line); background: transparent; color: var(--ink);
  border-radius: 12px; padding: 0 2px 0 2px; font-size: 12px; line-height: 18px;
}
.obs-x {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 18px; height: 18px; border: 0; background: none; color: var(--muted); cursor: pointer; font: inherit;
  font-size: 13px; line-height: 1; padding: 0; border-radius: 9px;
}
.obs-x:hover, .obs-x:focus-visible { color: var(--ink); background: var(--hover); }
/* + : a round button as tall as a pill */
.obs-add {
  width: 24px; height: 24px; border-radius: 12px; padding: 0; flex: 0 0 auto;
  border: 1px dashed var(--line-strong); background: none; color: var(--muted); cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;   /* the + is drawn (v137): a text + sits off-centre by a font-dependent amount */
}
.obs-add:hover, .obs-add:focus-visible, .obs-add[aria-expanded="true"] { color: var(--accent-text); border-color: var(--accent); }
/* The observers picker: the search box stays put, the names scroll. */
.obs-pick { overflow: hidden; max-height: 60vh; }
.obs-pick .obs-search { margin: 2px 2px 4px; width: auto; }
.obs-pick .obs-opts { display: flex; flex-direction: column; overflow-y: auto; min-height: 0; flex: 1 1 auto; }
.obs-pick .empty-note { padding: 7px 10px; }
/* The card view's tags: the tag's own chip with a × inside it. */
/* A very long tag shortens its text with …; the × always stays visible. */
.tag.tag-x-chip { display: inline-flex; align-items: center; gap: 2px; height: 24px; line-height: 24px; padding: 0 3px 0 10px; border-radius: 12px; font-size: 12px; min-width: 0; }
.tag-x-chip .tag-x-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag-x-chip .obs-x { color: inherit; opacity: .7; font-size: 13px; flex-shrink: 0; }
.tag-x-chip .obs-x:hover, .tag-x-chip .obs-x:focus-visible { opacity: 1; background: var(--ghost-hover); }
.card-tag-pick .tag { pointer-events: none; }
.card-tag-pick .tag-new { color: var(--accent); font-weight: 600; }

/* ---------- tag overflow panel ---------- */

.tags-btn { white-space: nowrap; }
/* Same story as .pav: the digit is centred by its line box and so rides high.
   A real round chip with the measured correction rather than an inline-block
   whose height came from the leading. */
.tags-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px;
  /* An inline-flex box whose items are not baseline-aligned synthesises its
     own baseline, and browsers disagree about how — some use the bottom
     border edge, which would drop the chip against the label. Aligning to the
     middle is deterministic, and keeps the 18px chip inside the button's
     existing 20.3px line box so the button does not grow. */
  vertical-align: middle;
  margin-left: 6px;
  padding-left: 5px; padding-right: 5px;
  padding-top: max(0px, calc(var(--ink-nudge) * 2));
  padding-bottom: max(0px, calc(var(--ink-nudge) * -2));
  /* Same weight as the monogram so one measurement serves both chips. */
  background: var(--accent); color: var(--on-accent); border-radius: 999px;
  font-size: 11px; font-weight: 600;
}
/* The selected filters: a row of their own at the bottom of the header,
   there only while something is selected. order + a full-width basis put it
   after everything else in the (wrapping) toolbar, on its own line; the
   chips wrap onto more lines if they must. (On a phone the strip is inside
   the filter panel instead — see the phone rules.) */
.selected-tags {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  flex: 0 0 100%; order: 99; min-width: 0;
}
/* On a wide screen the row is a grey band across the whole header, under its
   first line (v126). */
.toolbar .filter-bar { margin: 0 -24px -11px; padding: 8px 24px; flex-basis: calc(100% + 48px); gap: 8px;
  background: var(--filter-bar); border-top: 1px solid var(--line); }
.chip-group { display: contents; }
.filter-clear { margin-left: 4px; }
.selected-tags .btn.filter-clear { height: 26px; padding: 0 8px; color: var(--accent-text); font-size: 12.5px; font-weight: 500; }
.selected-tags .btn.filter-clear:hover { background: transparent; color: var(--accent-text); text-decoration: underline; }   /* no grey behind it: the dark theme's would cost AA */
.selected-tags .tag-chip, .selected-tags .btn { flex: 0 0 auto; }
/* …but a chip with a very long name may shrink to the row's width, its name
   shortened with … while the × stays (the name is .chip-text, index.php). */
.selected-tags .tag-chip { flex-shrink: 1; min-width: 0; max-width: 100%; display: inline-flex; align-items: center; gap: 5px; }
.selected-tags .chip-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag-panel-list { max-height: 46vh; overflow-y: auto; margin-top: 6px; }
.tag-panel-list label {
  display: flex; align-items: center; gap: 8px;
  margin: 0; padding: 5px 6px; border-radius: 5px;
  font-size: 13px; color: var(--ink); cursor: pointer;
}
.tag-panel-list label:hover { background: var(--hover); }
.tag-panel-list input { width: auto; }
.tag-panel-list .tag-count { margin-left: auto; color: var(--muted); font-size: 11px; }
.btn.tiny { padding: 3px 8px; font-size: 11px; border-radius: 6px; }

/* ---------- swimlane alignment ---------- */

.lane-block { display: flex; flex-direction: column; flex: 0 0 auto; }

/* ---------- aged-out cards in the last column ---------- */

.card.aged { opacity: .5; }
.card.aged:hover { opacity: .85; }
/* The quick-assign list belongs to the card, so the fade would make it
   see-through too: while it is open, the card is shown in full. */
.card.aged.assigning { opacity: 1; }
.hidden-toggle { white-space: nowrap; }

/* ---------- detail: created info + links ---------- */

.detail-desc a { color: var(--accent-text); word-break: break-all; }
.detail-desc a:hover { text-decoration: none; }

/* ---------- toolbar icon buttons ---------- */

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 6px 8px; color: var(--muted);
}
.icon-btn:hover { color: var(--ink); }
/* The header's icon buttons (v131): 36px squares with no outline, the icon
   in muted ink; the pointer gives them a faint background. */
.toolbar .icon-btn {
  width: 36px; height: 36px; padding: 0; flex: 0 0 auto;
  border: 0; border-radius: 8px; background: transparent;
}
.toolbar .icon-btn:hover { background: var(--ghost-hover); }
.toolbar .filter-btn.on { background: var(--accent-soft); color: var(--accent-text); }
/* A button that is "on" keeps its accent under the pointer: the plain hover
   colour above would otherwise make it look switched off while pointed at. */
.filter-btn.on:hover { color: var(--accent-text); }
/* So does the pressed calendar button (v160): the hover above came later and won. */
.toolbar .view-btn.on:hover { background: var(--soft); color: var(--accent); }

/* ---------- attachments ---------- */

.attachments { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 14px; }
.att-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; min-height: 24px; }
.att-head strong { font-size: 13px; font-weight: 600; }
.att-add { margin: 0 0 0 auto; cursor: pointer; position: relative; }   /* relative: holds its sr-only file field */
/* The file field inside is invisible but reached with Tab: the button shows
   where the focus is, as the avatar picker does. */
.att-add:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.att-list { display: flex; flex-wrap: wrap; gap: 10px; }
.att {
  display: flex; align-items: center; gap: 6px;
  border: 1px solid var(--line); border-radius: 8px; padding: 5px 8px;
  font-size: 12px; background: var(--panel);
}
.att a { color: var(--accent-text); text-decoration: none; }
.att-thumb {
  display: block; max-width: 120px; max-height: 90px;
  border-radius: 4px; object-fit: cover;
}
.att-meta { color: var(--muted); }
.att-file { white-space: nowrap; max-width: 220px; overflow: hidden; text-overflow: ellipsis; }

/* ---------- comments: inline images, edited / deleted states ---------- */

.cmt-img {
  display: block; max-width: 100%; max-height: 320px;
  margin: 6px 0; border: 1px solid var(--line); border-radius: 6px;
}

/* Order swap. The thread is its own flex context so .comments keeps its plain
   block layout: only the form moves, and it moves by `order` rather than by
   being duplicated, so the textarea is never remounted mid-typing.

   Spacing between the form and the list is the container's gap plus the
   form's own 8px on the list's side (v126). Flex items don't collapse
   margins, so the list adds none of its own: the last comment drops its
   bottom padding, and the room is the same in both orders (to within the
   first comment's 2px top padding). */
.comment-thread { display: flex; flex-direction: column; gap: 10px; }
.comment-thread .comment-form { margin-top: 0; }
/* More room between the new-comment box and the comments (v126); with the
   box last (oldest first) the room goes above it instead. */
.comment-thread:not(.input-last) .comment-form { margin-bottom: 8px; }
.comment-thread.input-last .comment-form { margin-top: 8px; }
.comment-thread.input-last .comment-form { order: 1; }


.comment .head .edited { color: var(--muted); font-style: italic; }
.deleted-note { color: var(--muted); font-style: italic; }
.comment textarea { margin-top: 4px; }
.comment .actions { margin-top: 6px; }


/* ---------- tags: clickable on cards, colourable in the picker ---------- */

/* A project chip (lane labels, the filter dialog, the admin's list; on cards
   the project is a text link instead): a tag-like chip told apart by its
   square corners and heavier lettering. */
.tag.project { border-radius: 4px; font-weight: 600; }
/* The card view's project pill looks exactly like the column, priority and
   assignee pills; a very long name shortens instead of widening the line. */
.detail-info .pick-project, .detail-info .epick-project { max-width: 100%; }
.detail-info .pick-project .pick-label, .detail-info .epick-project .pick-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* On a card the project is plain text under the title — no chip, no icon —
   that works as a link: a click filters by the project. A long name
   shortens (…) on its one line. */
/* width: 0 + min-width: 100%: the line takes the card's width but adds
   nothing to the card's own minimum width — otherwise a long one-line name
   would widen the card, and with it the whole column (a column is a flex
   item, which never shrinks below its content). */
.card .project-line { margin-top: -2px; line-height: 0; width: 0; min-width: 100%; }
.project-link {
  display: inline-block; vertical-align: top;
  font: inherit; font-size: 12px; line-height: 1.4; color: var(--accent-text);
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer; text-align: left;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.project-link:hover, .project-link:focus-visible, .project-link.on { text-decoration: underline; }
.project-link.on { font-weight: 600; }
.detail-pick button { max-width: min(360px, 92vw); }
/* An admin's new project, under the editor's grid. */
.project-new { margin-top: 10px; }
/* The filter's rows: a long name shortens (…) instead of pushing the count out. */
.project-row label { min-width: 0; }
/* The link icon after a project's name in the filter: small, and it must
   neither shrink nor take the row's height up. */
.project-link-copy { flex: 0 0 auto; padding: 3px 6px; margin: 0; color: var(--muted); }
.project-link-copy:hover, .project-link-copy:focus-visible, .btn.project-link-copy.copied, .btn.project-link-copy.copied:hover { color: var(--accent); }
.project-row .tag-count { flex: 0 0 auto; }   /* the count keeps its width (two digits must not wrap) */
/* The divisions a project belongs to: a line of tick boxes under its row. */
.admin-project-divisions { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 14px; margin-top: 6px; font-size: 13px; }
.admin-project-divisions .admin-hint { margin: 0; }
.admin-project-divisions label { display: inline-flex; align-items: center; gap: 5px; margin: 0; font-weight: 400; cursor: pointer; }
.admin-project-divisions input { width: auto; margin: 0; }
/* Division filter rows: a plain name where tags and projects have a chip. */
.division-name { display: inline-block; vertical-align: middle; max-width: 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-division-row .admin-count { min-width: 150px; }
/* A fixed column for the chip preview, so the name fields line up. */
.admin-project-chip { flex: 0 0 170px; min-width: 0; }
.tag.clickable {
  border: 0; font-family: inherit; cursor: pointer;   /* shape comes from .tag */
}
.tag.clickable:hover { filter: brightness(0.9); }
/* Darkening a dark chip barely shows: in the dark theme it lightens instead. */
html[data-theme="dark"] .tag.clickable:hover { filter: brightness(1.3); }
.tag.clickable.on { outline: 1.5px solid var(--accent); outline-offset: 1px; }

.tag-row { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border-radius: 5px; }
.tag-row:hover { background: var(--hover); }
.tag-row label { display: flex; align-items: center; gap: 8px; flex: 1; margin: 0; cursor: pointer; }
.tag-row .tag { font-size: 12px; padding: 3px 11px; }
/* A tag's or project's colour (v167): the button shows it; the row under the
   name offers the look's swatches, "Aa" on each, the plain chip first. */
.swatch-btn { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.swatch-btn[aria-expanded="true"] { border-color: var(--accent); }
.swatch-dot { display: inline-block; width: 14px; height: 14px; border-radius: 4px; background: var(--soft); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12); }
.swatch-dot.none { background: transparent; box-shadow: none; border: 1.5px dashed var(--line-strong); }
.swatch-row { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 4px; }
.swatch-opt {
  min-width: 34px; height: 26px; padding: 0 6px; border: 0; border-radius: 10px; cursor: pointer;
  background: var(--soft); color: var(--ink-2); font: inherit; font-size: 12px; font-weight: 600;
}
.swatch-opt.project { border-radius: 4px; }
.swatch-opt.on { outline: 2px solid var(--accent); outline-offset: 2px; }
.swatch-opt:hover { filter: brightness(.95); }
html[data-theme="dark"] .swatch-opt:hover { filter: brightness(1.2); }
.swatch-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- scrollbars ---------- */

/* Firefox */
* { scrollbar-width: thin; scrollbar-color: var(--scroll) transparent; }

/* WebKit / Blink */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--scroll); border-radius: 6px;
  border: 2px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--scroll-hi); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* The board's horizontal bar sits under the columns, so give it a little more
   presence than the in-column ones. */
.board::-webkit-scrollbar { height: 12px; }
.board::-webkit-scrollbar-thumb { background: var(--scroll-board); background-clip: content-box; }

/* ---------- board unavailable (offline / server unreachable) ---------- */

.board-offline {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 12px;
  color: var(--muted); text-align: center; padding: 40px 16px;
}
.board-offline p { margin: 0; }

/* ---------- people filter ---------- */

.person-chip { display: inline-flex; align-items: center; gap: 5px; }
/* (v131: the chips are white, so the circles need no ring, and Nincs
   felelős keeps its own muted dashed circle.) */

/* ---------- checklist ---------- */

/* Board badges run on from the left, 12px apart (v131). */
.card .chk-badge { white-space: nowrap; }
.card .chk-badge.full { color: var(--ok); font-weight: 600; }

/* No line above it (v131): the description's box, or the fields, close
   off what comes before. */
.checklist { margin-top: 18px; }
.chk-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; min-height: 24px; }
.chk-head strong { font-size: 13px; font-weight: 600; }
.chk-count { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.chk-bar {
  flex: 1; max-width: 200px; height: 5px; border-radius: 3px;
  background: var(--soft); overflow: hidden;
  display: flex;    /* a segment per item (v167), side by side: one bar here */
}
.chk-bar i { display: block; flex: 1 1 0; height: 100%; transition: background-color .18s ease; }
.chk-bar i.on { background: var(--ok); }

.chk-list { display: flex; flex-direction: column; }
.chk-item {
  display: flex; align-items: center; gap: 8px; min-height: 30px;
  padding: 2px 2px; border-radius: 6px; font-size: 13.5px;
}
.chk-item .item-check { width: 16px; height: 16px; accent-color: var(--accent); }
.chk-item:hover { background: var(--hover); }
.chk-item.done .item-label { color: var(--muted); text-decoration: line-through; }
.chk-item.pending { opacity: .6; }
.chk-item.failed { background: var(--danger-soft); }

/* Drag is handle-only: tapping the checkbox or the label on a touch screen
   must do what it looks like it does. */
.item-drag {
  cursor: grab; color: var(--muted); opacity: .45;
  font-size: 13px; line-height: 1; padding: 0 2px; user-select: none;
}
.item-drag:hover { opacity: .9; }
/* The existing ghost/drag rules are scoped to .card, so checklist rows would
   otherwise drag with no visual feedback at all. */
.chk-item.sortable-ghost { opacity: .35; }
.chk-item.sortable-drag { background: var(--surface); box-shadow: var(--shadow); cursor: grabbing; }
.item-drag.ghosted { visibility: hidden; cursor: default; }

.item-check { flex: none; margin: 0; cursor: pointer; }
.item-label { flex: 1; cursor: text; word-break: break-word; }
.item-edit { flex: 1; font-size: 13px; padding: 3px 6px; }
.item-state { font-size: 11px; color: var(--muted); white-space: nowrap; }
.item-state.err { color: var(--danger); }

/* Buttons stay out of the way until the row is hovered, so a long list reads
   as a list rather than a wall of icons. Always visible on touch, where there
   is no hover to reveal them. */
.chk-item .btn.ghost.tiny { opacity: 0; padding: 1px 5px; font-size: 11px; }
/* v154: one height for the item's small buttons, the child-card one's drawn
   icon (at the size of the ✎ and ✕ beside it) included. */
.chk-item .btn.ghost.tiny { display: inline-flex; align-items: center; justify-content: center; height: 20px; }
.chk-item .item-card .link-ico { width: 12px; height: 12px; }
.chk-item:hover .btn.ghost.tiny,
.chk-item .btn.ghost.tiny:focus-visible,
.chk-item.failed .btn.ghost.tiny { opacity: 1; }
/* Mentés / Mégse while renaming: the caret is in the field, so the mouse is
   very likely nowhere near the row. These must never be hover-gated. */
.chk-item .item-edit ~ .btn.ghost.tiny { opacity: 1; }
@media (hover: none) {
  /* Touch screens: iPhones and iPads report a tap as a click only on things
     they consider clickable, and a plain dark area is not one — a tap outside
     a dialog would never arrive. A pointer cursor (never seen on a touch
     screen) is what makes it count; the dialog itself keeps the usual one. */
  .overlay { cursor: pointer; -webkit-tap-highlight-color: transparent; }   /* …without the grey flash those devices put on a tapped "clickable" thing — here it would cover the whole screen */
  .overlay > .modal { cursor: auto; }
  .chk-item .btn.ghost.tiny { opacity: 1; }
}

.chk-add { display: flex; align-items: center; gap: 6px; margin-top: 4px; }
.chk-plus { color: var(--muted); font-size: 14px; width: 15px; text-align: center; }
.chk-add input { flex: 1; font-size: 13px; padding: 5px 8px; }
.chk-hint { font-size: 11px; color: var(--muted); margin: 4px 0 0 21px; }

/* ---------- swimlane mode: one scroller for the whole board ----------
   With lanes on, each column scrolling separately slides the rows out of
   alignment — the exact thing lanes are for. So the board itself takes over
   vertical scrolling and the columns simply grow. Flat mode keeps its
   per-column scrolling, where nothing needs to line up. */

/* A grid, not the board's usual flex row. Headers are sticky, and a sticky
   element only stays put inside its own parent — the column. A one-row flex
   container stretches its columns to the board's VISIBLE height, so the
   cards overflowed the column box and the headers scrolled away once you
   passed the first screenful. A grid row is as tall as its tallest column
   and every column is stretched to it, so each column box runs to the very
   bottom and its header stays pinned the whole way down. */
.board.lanes {
  overflow-y: auto;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 282px;   /* = .col's flex-basis in flat mode */
  align-items: stretch;
}
.board.lanes .col { max-height: none; }
@media (max-width: 640px) {
  .board.lanes { grid-auto-columns: 86vw; }   /* = the phone .col width */

  /* iPhone Safari zooms the page into any field whose text is under 16px and
     leaves it zoomed. After the checklist fields' own size on purpose: it
     would otherwise lose to it. */
  input, select, textarea, .item-edit, .chk-add input { font-size: 16px; }

  /* Narrower buttons keep the formatting toolbar's eight buttons (with the
     paperclip, v117) on one line. */
  .fmt-bar { gap: 1px; }
  .fmt-btn { min-width: 23px; padding: 0 3px; }
}
.board.lanes .col-body { overflow-y: visible; flex: 0 0 auto; }

/* Headers stay put while the cards scroll under them. The box-shadow paints
   the board's own top padding, so nothing peeks above the header. */
.board.lanes .col-head {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  box-shadow: 0 -18px 0 var(--bg);
}

/* ---------- admin: columns, users, deleted cards ---------- */

.admin-hint { font-size: 12px; color: var(--muted); margin: 0 0 10px; }
.admin-list { display: flex; flex-direction: column; gap: 2px; max-height: 56vh; overflow-y: auto; }

.admin-col-row { padding: 4px 6px; border-radius: 5px; }
.admin-col-row:hover { background: var(--hover); }
.admin-col-main { display: flex; align-items: center; gap: 8px; }
.admin-col-main input[type=text] { flex: 1; min-width: 0; }
.admin-col-moves { display: inline-flex; flex: 0 0 auto; }
.admin-col-moves .btn { padding: 3px 6px; }
.admin-done {
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto;
  margin: 0; font-size: 12px; color: var(--muted); white-space: nowrap; cursor: pointer;
}
.admin-done input { width: auto; margin: 0; }
.admin-count { flex: 0 0 auto; font-size: 11px; color: var(--muted); min-width: 56px; text-align: right; }
.admin-col-delete {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin: 6px 0 2px 58px; padding: 8px 10px; font-size: 12px;
  background: var(--warn-bg); border: 1px solid var(--warn-line); border-radius: 6px;
}
.admin-col-delete select { width: auto; flex: 1 1 140px; }
.admin-add { display: flex; gap: 8px; margin-top: 10px; }
.admin-add input { flex: 1; min-width: 0; }

.admin-user-row { display: flex; align-items: center; gap: 10px; padding: 6px; border-radius: 5px; }
.admin-user-row:hover { background: var(--hover); }
.admin-user-row.inactive .admin-user-name, .admin-user-row.inactive .uav { opacity: .5; }
.admin-user-main { flex: 1; min-width: 0; }
.admin-user-name { font-weight: 550; overflow-wrap: anywhere; }
.admin-user-sub { font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.admin-badge {
  display: inline-block; margin-left: 6px; padding: 0 8px; border-radius: 10px;
  font-size: 10.5px; font-weight: 600; background: var(--soft); color: var(--muted);
}
.admin-badge.off { background: var(--danger-soft); color: var(--danger-chip); }

.admin-user-form { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 12px 14px; margin-bottom: 10px; }
.admin-user-form .actions { margin-top: 12px; }

@media (max-width: 560px) {
  .admin-col-main { flex-wrap: wrap; }
  .admin-col-main input[type=text] { flex-basis: 100%; order: -1; }
  .admin-col-delete { margin-left: 0; }
}

/* ---------- touch screens: tap areas of at least 32px ----------
   The small controls keep the size they are drawn at; on a touch screen an
   invisible area around each (a centred ::after, part of the control, so a
   tap on it is a tap on the control) makes them easier to hit. Neighbours are
   at least a few pixels apart, so an area reaching past its control mostly
   covers empty room or plain text; where two areas meet, the later control
   takes the overlap, which splits it between them. */
@media (pointer: coarse) {
  .obs-x, .detail-info .info-pill, .obs-add, .col-head .add, .assign-btn, .bell-dot, .fmt-btn, .btn.tiny { position: relative; }
  .obs-x::after, .detail-info .info-pill::after, .obs-add::after, .col-head .add::after, .assign-btn::after,
  .bell-dot::after, .fmt-btn::after, .btn.tiny::after {
    content: ""; position: absolute; left: 50%; top: 50%;
    width: max(100%, 32px); height: max(100%, 32px);
    transform: translate(-50%, -50%);
  }
  /* A tag chip clips what sticks out of it (for its …); its × needs room
     outside it. The text has its own clipping (.tag-x-text). */
  .tag.tag-x-chip { overflow: visible; }
  /* The project name on a card clips too (its …), so it grows from inside:
     padding, given back by negative margins, so nothing moves. */
  .project-link { padding-top: 8px; padding-bottom: 8px; margin-top: -8px; margin-bottom: -8px; }
}

/* ---------- the smallest phones (320px) ----------
   The one-row header needs about 350px once the filter button carries its
   badge, and only the board name can shrink (to nothing, with …). Below
   340px the gaps and side paddings tighten, so every button still fits on
   the row. 360px and up are untouched. */
@media (max-width: 340px) {
  .toolbar { gap: 3px; padding-left: 8px; padding-right: 8px; }
  .toolbar .icon-btn { width: 34px; }
}

/* -------- links between cards (v141; rows with icons since v144) -------- */
/* Every link is one row: its icon, the other card's number and title — the
   title shortened with … (a long one never widens the card or the card
   view), a finished card's crossed out and faded. At most five, then
   "+N további". (Until v147 a card blocking this one was red while open.) */
.card .card-links {
  display: flex; flex-direction: column; gap: 1px; width: 0; min-width: 100%;   /* adds nothing to the card's own width */
  margin: 2px 0 6px;
}
.link-row {
  display: flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%;
  font: inherit; font-size: 12px; line-height: 1.5; color: var(--ink-2); text-align: left;
  background: none; border: 0; padding: 1px 0; cursor: pointer;
}
.link-row .link-ico { flex: 0 0 auto; color: var(--muted); }
.link-row .link-num { flex: 0 0 auto; color: var(--muted); font-variant-numeric: tabular-nums; }
.link-row .link-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.link-row:hover .link-title, .link-row:focus-visible .link-title { color: var(--accent-text); text-decoration: underline; }
.done > .link-row .link-title, .link-row.done .link-title { text-decoration: line-through; color: var(--muted); }
.link-more {
  align-self: flex-start; font: inherit; font-size: 12px; color: var(--accent-text); background: none; border: 0;
  padding: 1px 0; cursor: pointer;
}
.link-more:hover, .link-more:focus-visible { text-decoration: underline; }
/* In the card view: the same rows, each with its ×, and + under them. */
.detail-info .links-list { flex-direction: column; flex-wrap: nowrap; align-items: flex-start; gap: 2px; }
.detail-info .info-links { align-items: start; }                     /* the label on the first row, not the middle */
.detail-info .info-links .info-label { padding-top: 4px; }
.link-item { display: flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%; }
.link-item .link-row { font-size: 13px; }
.links-list .links-add { margin-top: 4px; }
/* In the editor the rows are not links (the editor stays open). */
.edit-links .link-row { cursor: default; }
.edit-links .link-row:hover .link-title { color: inherit; text-decoration: none; }
.edit-links .done > .link-row:hover .link-title { color: var(--muted); text-decoration: line-through; }
.link-rel-btn { display: inline-flex; align-items: center; gap: 5px; }
/* The picker opens in place under the grid: the type, a search, the cards. */
.link-pick {
  margin: 10px 0 0; padding: 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface);
  display: flex; flex-direction: column; gap: 8px;
}
.link-rels { display: flex; flex-wrap: wrap; gap: 4px; }
.link-rel-btn {
  font: inherit; font-size: 12px; height: 26px; padding: 0 10px; border-radius: 13px; cursor: pointer;
  border: 1px solid var(--line); background: none; color: var(--ink);
}
.link-rel-btn:hover, .link-rel-btn:focus-visible { border-color: var(--line-strong); background: var(--hover); }
.link-rel-btn.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-text); font-weight: 500; }
.link-search { width: 100%; }
.link-opts { display: flex; flex-direction: column; max-height: 260px; overflow-y: auto; }
.link-opt {
  font: inherit; font-size: 13px; text-align: left; background: none; border: 0; border-radius: 6px; padding: 7px 10px;
  cursor: pointer; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.link-opt:hover, .link-opt:focus-visible { background: var(--hover); }
.link-opt:disabled { cursor: progress; opacity: .6; }
.link-pick .err-msg { margin: 0; }

/* -------- Beállítások (v167): the looks, a card each -------- */
.modal.settings { max-width: 520px; }
.settings-h { margin: 18px 0 6px; font-size: 13px; font-weight: 600; }
.detail-head + .settings-h, .push-box .settings-h { margin-top: 0; }
.theme-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.theme-card {
  display: flex; flex-direction: column; gap: 7px; margin: 0; padding: 10px;
  border: 1px solid var(--line); border-radius: 8px; cursor: pointer; color: var(--ink); font-size: 13px;
}
.theme-card:hover { border-color: var(--line-strong); }
.theme-card.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.theme-card:focus-within { outline: 2px solid var(--accent); outline-offset: 1px; }
.theme-card-head { display: flex; align-items: center; gap: 7px; font-weight: 600; }
.theme-card input { width: auto; margin: 0; flex: 0 0 auto; }
.theme-swatch { display: flex; height: 18px; border-radius: 4px; overflow: hidden; border: 1px solid var(--line); }
.theme-swatch i { flex: 1 1 0; }
.theme-desc { font-size: 12px; color: var(--muted); line-height: 1.35; }
.theme-hint { margin: 8px 0 0; }

/* -------- type roles (v167) --------
   Which text takes which face: --font-display for names of things (the
   board, columns, lanes, dialogs, sections, the main buttons), --font-mono
   for data (dates, counts, initials, card numbers, tags). Both are --font
   in the default look, so nothing here changes it. After the rules above,
   some of which reset the face (font: inherit). */
.toolbar .brand, .login h1, .col-head h2, .lane-label, .agenda-group h2, .modal h3, .settings-h,
.chk-head strong, .att-head strong, .detail-tab, .bell-head strong, .rich .md-h, .btn.primary {
  font-family: var(--font-display);
}
.col-head .count, .lane-label .lane-count, .agenda-group h2 .count, .detail-tab .tab-count, .deadline, .detail-info .pick-trigger.info-deadline,
.badge-ico, .chk-count, .link-num, .tag, .tag.clickable, .tags-badge, .uav, .pav, .avatar-mono,
.detail-info .info-created .created-at, .log-row .when, .bell-time {
  font-family: var(--font-mono);
}
.tag.project { font-family: var(--font); }     /* a project is a name, not data */

/* Új kártya (v159): a round button floating at the bottom right, on every
   screen (until v158 a button in the header). Last in the file: its
   paddings must win over the rules above. */
.fab {
  display: inline-flex; align-items: center; justify-content: center;
  position: fixed; z-index: 30;    /* over the board and its pinned headers, under every panel, menu and dialog */
  right: calc(24px + env(safe-area-inset-right, 0px)); bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  width: 56px; height: 56px; padding: 0; border: 0; border-radius: 50%;
  box-shadow: var(--shadow-modal);
}
/* Never over anything open on top of the board. */
#app:has(.overlay, .menu, .bell-panel, .filters.open, .assign-pop, .detail-pick) .fab { display: none; }
/* Room under the last card and above the messages, so the button covers
   neither: 24 + 56 + 16. (Lanes: the board scrolls, not the columns.) */
.board:not(.lanes) .col-body, .board.lanes, .agenda { padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }
.toasts { bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }
/* A phone: 16px from the edges. */
@media (max-width: 640px) {
  .fab { right: calc(16px + env(safe-area-inset-right, 0px)); bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
  .board:not(.lanes) .col-body, .board.lanes, .agenda { padding-bottom: calc(88px + env(safe-area-inset-bottom, 0px)); }
  .toasts { bottom: calc(88px + env(safe-area-inset-bottom, 0px)); }
}
