/* ==========================================================================
   FinanceSeyco2 — Design System (Finance, перекрашенный в тёмно-зелёный)

   iOS-style liquid glass: translucent panels floating over a slow field of
   light, continuous corner radii, specular highlights, spring easing. The
   accent is the red of the Seyco Group mark, on black and white — the panel is
   the company's own lockup rather than a palette invented next to it.

   Tokens first — change them here and every screen follows.
   ========================================================================== */

:root{
  /* --- Accent: dark green (FinanceSeyco2), with a brighter partner for the gradients.
     Not the blue of FinanceSeyco and not the red of HR: three
     panels of the same company, told apart at a glance. --------------------- */
  --accent-1: #14532D;        /* primary brand dark green  */
  --accent-1-dark: #0D3B20;   /* pressed / hover-deep      */
  --accent-1-light: #2F9E5E;  /* gradient partner          */
  --accent-tint: rgba(20,83,45,.11);
  /* A filled surface and a coloured word are two different jobs. `--accent-1`
     is the word: it sits on the page background. The pair below is the fill,
     and it is picked so white text on the lighter end still clears 4.5:1 —
     the old gradient started at #2F9E5E, where it did not. */
  --accent-fill-a: #1E7A46;
  --accent-fill-b: #14532D;

  /* Translucent tints of the status colours and of the accent.

     Each is written twice on purpose. The first line is the literal value; the
     second recomputes it from the token above, so changing --danger changes
     every surface tinted with it. A browser without color-mix() cannot parse
     the second declaration, drops it, and keeps the first — same result, no
     fallback machinery. This is the fix for what kept happening by hand: the
     accent moved and a dozen hard-coded rgba() values stayed behind. */
  --tint-success: rgba(31,157,85,.16);
  --tint-success: color-mix(in srgb, var(--success) 16%, transparent);
  --tint-warn: rgba(245,165,36,.18);
  --tint-warn: color-mix(in srgb, var(--warn) 18%, transparent);
  --tint-danger: rgba(229,72,77,.16);
  --tint-danger: color-mix(in srgb, var(--danger) 16%, transparent);
  --tint-neutral: rgba(142,142,147,.20);
  --tint-neutral: color-mix(in srgb, var(--text-muted) 22%, transparent);
  --accent-glow: rgba(20,83,45,.52);
  --accent-glow: color-mix(in srgb, var(--accent-1) 52%, transparent);
  --ink: #111111;             /* the black of the wordmark */
  --danger: #E5484D;
  --success: #1F9D55;
  --warn: #F5A524;

  /* iOS squircles are flatter at the corner than a plain circle; the sizes
     below are the ones that read as "system", not as "rounded box". */
  /* Скругления сдержанные: крупные радиусы и «таблетки» делали панель
     похожей на шаблон, а не на рабочий инструмент бухгалтерии. */
  --radius-xl: 12px;
  --radius-lg: 10px;
  --radius-md: 8px;
  --radius-sm: 6px;
  --radius-xs: 5px;

  /* Two faces, one job each. Inter reads at 13px in a dense table without
     turning to mush; Manrope is wider and rounder, so a heading and a number
     carry weight the body text does not. Both cover Cyrillic *and* the Kazakh
     extension, which is the requirement a three-language panel actually has.
     The system stack stays behind them for the first paint. */
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Text',
               'Segoe UI', Roboto, sans-serif;
  --font-display: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont,
                  'SF Pro Display', 'Segoe UI', sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;

  --shadow-soft: 0 1px 2px rgba(17,17,17,.05), 0 10px 30px -14px rgba(17,17,17,.16);
  --shadow-lift: 0 6px 14px rgba(17,17,17,.08), 0 26px 56px -20px rgba(17,17,17,.26);
  --shadow-accent: 0 10px 26px -6px rgba(20,83,45,.40);

  /* Two easings do all the work: `ease-ios` for anything that travels (the
     system's own decelerate curve), `spring` for anything that should feel
     like it has weight — buttons, cards, toasts. */
  --ease-ios: cubic-bezier(.32,.72,0,1);
  --spring: cubic-bezier(.34,1.42,.64,1);
  --transition: 260ms var(--ease-ios);
}

/* ---------- Light: paper white ----------
   The page is plain white; the only colour is the accent and the soft bloom
   behind the glass. The greys are the system label colours, so text on white
   sits at the contrast the OS itself uses.

   The glass surfaces are translucent, so the browser's own painting of native
   controls shows through them; `color-scheme` is what stops a device in dark
   mode from filling our light inputs with charcoal. */
:root, [data-theme="light"]{
  color-scheme: light;
  --bg: #FFFFFF;
  --bg-elevated: #FFFFFF;
  --surface: rgba(255,255,255,.58);
  --surface-strong: rgba(246,246,248,.86);
  --surface-solid: #FFFFFF;
  --border: rgba(0,0,0,.07);
  --line: rgba(0,0,0,.09);
  --text: #09090B;
  --text-muted: #5A5A61;
  --text-faint: #767680;
  --input-bg: rgba(255,255,255,.72);
  /* The thin bright line along the top edge of a glass panel — the single
     detail that makes it read as a lit surface rather than a grey box. */
  --sheen: rgba(255,255,255,.9);
  --sheen-soft: rgba(255,255,255,.45);
  --blob: .34;
}

/* ---------- Dark: true black ----------
   #000, not charcoal: on an OLED screen the background is then genuinely off,
   and the glass panels read as lit sheets floating on nothing. */
[data-theme="dark"]{
  color-scheme: dark;
  --bg: #000000;
  --bg-elevated: #0B0B0D;
  --surface: rgba(28,28,30,.62);
  --surface-strong: rgba(44,44,46,.78);
  --surface-solid: #0B0B0D;
  --border: rgba(255,255,255,.12);
  --line: rgba(255,255,255,.13);
  --text: #FFFFFF;
  --text-muted: #A2A2AA;
  --text-faint: #80808A;
  --input-bg: rgba(28,28,30,.72);
  --sheen: rgba(255,255,255,.14);
  --sheen-soft: rgba(255,255,255,.05);
  --blob: .42;
  /* The same green, lifted so it holds its saturation against true black. */
  --accent-1: #3FBF74;
  --accent-1-light: #6FD69A;
  --accent-tint: rgba(63,191,116,.18);
  /* The accent itself is lifted for black; the fill is not, because white text
     on #6FD69A came out at 2.7:1 — a button nobody could read comfortably. */
  --accent-fill-a: #23894F;
  --accent-fill-b: #145C33;
  --shadow-soft: 0 1px 2px rgba(0,0,0,.35), 0 10px 30px -14px rgba(0,0,0,.7);
  --shadow-lift: 0 6px 14px rgba(0,0,0,.4), 0 26px 56px -20px rgba(0,0,0,.8);
  --shadow-accent: 0 10px 26px -6px rgba(63,191,116,.40);
}

*{ box-sizing: border-box; }

body{
  margin:0;
  min-height:100vh;
  font-family: var(--font-body);
  font-size:15px;
  line-height:1.55;
  letter-spacing:-.01em;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- Background field ---------------------------------------------
   Light behind the glass. Deliberately still: a blurred shape this large,
   moving under translucent panels, forces the browser to re-sample and re-blur
   the backdrop of every one of them on every frame — which is what the whole
   interface was stuttering on. Painted once, it costs nothing and looks the
   same. */
.field-bg{ position:fixed; inset:0; z-index:-1; overflow:hidden; }
.field-bg span{
  position:absolute; border-radius:50%; filter:blur(110px); opacity: var(--blob, .4);
}
.field-bg span:nth-child(1){
  width:56vw; height:56vw; left:-12vw; top:-16vw;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent-1-light) 40%, transparent), transparent 70%);
}
.field-bg span:nth-child(2){
  width:48vw; height:48vw; right:-14vw; bottom:-18vw; animation-delay:-15s;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent-1) 32%, transparent), transparent 70%);
}
.field-bg span:nth-child(3){
  width:34vw; height:34vw; left:42vw; top:48vh; animation-delay:-8s;
  /* A third light, not a third helping of the accent: two greens alone read as
     one flat wash. Deliberately not derived from a token. */
  background: radial-gradient(circle, rgba(28,150,140,.20), transparent 70%);
}

/* ---------- Typography ---------- */
h1,h2,h3{
  margin:0 0 10px; color:var(--text); font-family:var(--font-display);
  letter-spacing:-.03em; line-height:1.15;
  /* Optical sizing and a slightly tighter track: at display sizes the default
     spacing reads loose, and the tightening is what makes a heading look set
     rather than typed. */
  font-feature-settings:'ss01' 1, 'cv11' 1;
}
h1{ font-size:31px; font-weight:800; }
h2{ font-size:22px; font-weight:750; letter-spacing:-.025em; }
h3{ font-size:16.5px; font-weight:700; letter-spacing:-.02em; }
p{ margin:0 0 14px; color:var(--text-muted); }
a{ color:var(--accent-1); text-decoration:none; }
code{ font-family:var(--font-mono); font-size:.86em; background:var(--surface-strong);
      padding:2px 7px; border-radius:4px; }
/* Money only reads as money when the digits sit in a grid. */
.num, .money{ font-variant-numeric: tabular-nums; }

/* ---------- Liquid glass -------------------------------------------------
   Three layers stacked: the blurred backdrop, a top-to-bottom sheen that
   fakes a lit edge, and a soft outer shadow to lift it off the field. */
.glass{
  position:relative;
  background: var(--surface);
  border:1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft), inset 0 1px 0 var(--sheen);
  backdrop-filter: blur(30px) saturate(180%);
  -webkit-backdrop-filter: blur(30px) saturate(180%);
}
.glass::after{
  /* Specular sweep across the top third. `inherit` on the radius keeps it
     glued to the corner no matter which radius the panel uses.
     z-index:-1 lays it under the content and over the panel's own fill: the
     backdrop-filter above makes the panel a stacking context, so -1 stays
     inside it. Painted on top, the sweep washed out whatever sat in the top
     third — in the light theme the logo tile and the heading came out pale. */
  content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  z-index:-1;
  background: linear-gradient(170deg, var(--sheen-soft) 0%, transparent 42%);
}

/* ---------- Buttons ---------- */
.btn{
  position:relative;
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  font:inherit; font-weight:600; letter-spacing:-.01em;
  padding:13px 24px; border:1px solid transparent;
  /* Не «таблетка»: при коротком тексте радиус в половину высоты съедает углы
     и кнопка выглядит шире, чем есть, а длинный текст в ней переносится
     посередине слова. Скруглённый прямоугольник читается как кнопка и не
     спорит с полями рядом. */
  border-radius: var(--radius-md); cursor:pointer;
  /* «Добавить строку» — одна строка: перенос внутри кнопки делает её вдвое
     выше соседних, и ряд действий разъезжается. */
  white-space:nowrap;
  background: var(--surface-strong); color: var(--text);
  transition: transform 220ms var(--spring), box-shadow var(--transition),
              background var(--transition), opacity var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.btn:hover{ transform: translateY(-1.5px); }
/* iOS presses shrink; they do not ripple. */
.btn:active{ transform: scale(.965); transition-duration:90ms; }
.btn:focus-visible{ outline:none; box-shadow: 0 0 0 4px var(--accent-tint); }
.btn-primary{
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  color:#fff; box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,.28);
}
.btn-primary:hover{ box-shadow: 0 14px 34px -8px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.3); }
.btn-ghost{ background:transparent; border-color:var(--line); color:var(--text-muted); }
.btn-ghost:hover{ background: var(--surface-strong); color:var(--text); }
.btn-sm{ padding:8px 14px; font-size:13px; border-radius: var(--radius-sm); }
.btn-block{ width:100%; }
.btn[disabled]{ opacity:.5; pointer-events:none; }
/* The spinner the sign-in button shows while the form is in flight. */
.btn.is-busy{ color:transparent; pointer-events:none; }
.btn.is-busy::before{
  content:''; position:absolute; width:18px; height:18px; border-radius:50%;
  border:2px solid rgba(255,255,255,.35); border-top-color:#fff;
  animation: spin 700ms linear infinite;
}
@keyframes spin{ to{ transform: rotate(360deg); } }

/* ---------- Fields ---------- */
.field{ margin-bottom:16px; }
.field label{
  display:block; margin-bottom:7px; font-size:12px; font-weight:600;
  letter-spacing:.02em; color:var(--text-muted);
}
/* «Нужна платёжка»: галочка в плашке той же высоты и формы, что поле
   «Срок оплаты» рядом, — ряд формы не ломается, а цель для пальца крупная.
   Как у .seg: настоящий checkbox внутри ярлыка (клавиатура и форма работают
   без скрипта), видимая часть — соседний span, его и красит :checked. */
.field label.check-tile{ display:block; position:relative; margin:0; cursor:pointer;
  font-size:inherit; font-weight:inherit; letter-spacing:normal; color:inherit;
  -webkit-tap-highlight-color: transparent; }
.check-tile input{ position:absolute; opacity:0; pointer-events:none; }
.check-tile-card{
  display:flex; align-items:center; gap:12px; padding:14px 18px;
  background: var(--input-bg); border:1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: inset 0 1px 0 var(--sheen-soft);
  font-weight:600; color:var(--text-muted);
  transition: background var(--transition), color var(--transition),
              border-color var(--transition), box-shadow var(--transition);
}
.check-tile-box{
  flex:0 0 22px; width:22px; height:22px; border-radius:7px; position:relative;
  background: var(--surface-solid); border:1.5px solid var(--text-faint);
  transition: background var(--transition), border-color var(--transition);
}
/* Галка — два края повёрнутого прямоугольника: без картинки и шрифта. */
.check-tile-box::after{
  content:""; position:absolute; left:6.5px; top:2.5px; width:6px; height:11px;
  border:solid #fff; border-width:0 2.5px 2.5px 0; transform:rotate(45deg) scale(.4);
  opacity:0; transition: opacity var(--transition), transform var(--transition);
}
.check-tile:hover .check-tile-card{ border-color: var(--accent-1); }
.check-tile input:checked + .check-tile-card{
  border-color: var(--accent-1); background: var(--accent-tint); color: var(--text);
}
.check-tile input:checked + .check-tile-card .check-tile-box{
  border-color:transparent;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
}
.check-tile input:checked + .check-tile-card .check-tile-box::after{
  opacity:1; transform:rotate(45deg) scale(1);
}
.check-tile input:focus-visible + .check-tile-card{ box-shadow: 0 0 0 4px var(--accent-tint); }
/* Платёжка на листе счёта у «Оплаты» и бухгалтера: строка состояния, под
   ней выбор файла и кнопка. Кнопку выбора файла рисует браузер — красим её
   под свои кнопки, а не прячем: так выбранное имя файла видно без скрипта. */
.po-form{ display:grid; gap:12px; margin-top:16px; padding-top:14px;
  border-top:1px solid var(--line); }
.po-form .po-status{ display:flex; flex-wrap:wrap; align-items:center; gap:6px 10px; margin:0; }
.po-row{ display:flex; flex-wrap:wrap; align-items:center; gap:10px 12px; }
.po-row input[type=file]{ flex:1 1 220px; min-width:0; max-width:100%;
  font:inherit; font-size:13px; color:var(--text-muted); }
.po-row input[type=file]::file-selector-button{
  font:inherit; font-size:13px; font-weight:600; color:var(--text);
  margin-right:12px; padding:8px 14px; cursor:pointer;
  background: var(--surface-strong); border:1px solid var(--line);
  border-radius: var(--radius-sm); transition: background var(--transition);
}
.po-row input[type=file]::file-selector-button:hover{ background: var(--accent-tint); }
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], select, textarea{
  width:100%; font:inherit; color:var(--text); padding:14px 18px;
  background: var(--input-bg); border:1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: inset 0 1px 0 var(--sheen-soft);
  transition: border-color var(--transition), box-shadow var(--transition),
              background var(--transition);
}
textarea{ min-height:110px; resize:vertical; }
select:disabled{ opacity:.55; cursor:not-allowed; }
input::placeholder, textarea::placeholder{ color:var(--text-faint); }
input:focus, select:focus, textarea:focus{
  outline:none; border-color: var(--accent-1);
  background: var(--surface-solid);
  box-shadow: 0 0 0 4px var(--accent-tint);
}
.password-field{ position:relative; }
.password-field input{ padding-right:52px; }
.password-eye{
  position:absolute; right:10px; top:50%; transform:translateY(-50%);
  border:0; background:transparent; cursor:pointer; font-size:16px;
  padding:6px 8px; border-radius:50%; opacity:.6; transition:opacity var(--transition);
}
.password-eye:hover{ opacity:1; }
.checkbox-row{
  display:flex; align-items:center; gap:9px; margin-bottom:20px;
  font-size:14px; color:var(--text-muted); cursor:pointer;
}
.checkbox-row input{ accent-color: var(--accent-1); width:17px; height:17px; }

/* ---------- Role picker -------------------------------------------------
   The development sign-in screen: one card per role, stacked. Radio inputs
   live inside the labels, so the whole card is the hit area and
   `:checked + .role-card` is what paints the chosen one. */
.role-picker{ display:grid; gap:8px; }
.role-option{ display:block; cursor:pointer; -webkit-tap-highlight-color: transparent; }
.role-option input{ position:absolute; opacity:0; pointer-events:none; }
.role-card{
  display:grid; grid-template-columns:auto 1fr; align-items:center;
  column-gap:13px; row-gap:1px; padding:12px 15px;
  background: var(--input-bg); border:1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: inset 0 1px 0 var(--sheen-soft);
  transition: transform 260ms var(--spring), background var(--transition),
              border-color var(--transition), box-shadow var(--transition);
}
.role-option:hover .role-card{ transform: translateY(-1.5px); }
.role-option:active .role-card{ transform: scale(.98); }
.role-ico{
  grid-row:1 / span 2; width:36px; height:36px; display:grid; place-items:center;
  border-radius:var(--radius-sm); font-size:16px; font-weight:700;
  background: var(--accent-tint); color: var(--accent-1);
  transition: background var(--transition), color var(--transition);
}
.role-name{ font-size:14.5px; font-weight:650; color:var(--text); letter-spacing:-.01em; }
.role-hint{ font-size:12.5px; color:var(--text-faint); line-height:1.35; }

.role-option input:checked + .role-card{
  border-color:transparent;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,.26);
}
.role-option input:checked + .role-card .role-name{ color:#fff; }
.role-option input:checked + .role-card .role-hint{ color:rgba(255,255,255,.78); }
.role-option input:checked + .role-card .role-ico{
  background: rgba(255,255,255,.22); color:#fff;
}
/* The radio itself is invisible, so the focus ring has to be drawn on the card. */
.role-option input:focus-visible + .role-card{ box-shadow: 0 0 0 4px var(--accent-tint); }

/* ---------- Segmented picker --------------------------------------------
   Два-три варианта одним рядом: радио внутри ярлыка, поэтому выбор работает
   с клавиатуры и без скрипта, а `:checked + .seg-card` красит выбранный. */
.seg{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
.seg-option{ display:block; cursor:pointer; -webkit-tap-highlight-color: transparent; }
.seg-option input{ position:absolute; opacity:0; pointer-events:none; }
.seg-card{
  /* Не «таблетка»: кнопка во всю строку с закруглением в её половину высоты
     читается как ползунок, а не как выбор. Тот же радиус, что у кнопок. */
  display:block; padding:9px 18px; border-radius: var(--radius-md);
  background: var(--input-bg); border:1px solid var(--border);
  font-size:14px; font-weight:600; color:var(--text-muted);
  transition: background var(--transition), color var(--transition),
              border-color var(--transition), box-shadow var(--transition);
}
.seg-option input:checked + .seg-card{
  border-color:transparent; color:#fff;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,.26);
}
.seg-option input:focus-visible + .seg-card{ box-shadow: 0 0 0 4px var(--accent-tint); }

/* Два раздела — во всю строку и поровну: выбор из двух читается как две
   половины, а не как два ярлыка, к которым можно дописать третий. */
.seg-two{ gap:10px; }
.seg-two .seg-option{ flex:1 1 0; min-width:140px; }
.seg-two .seg-card{ text-align:center; padding:12px 18px; }

/* Подпись под полем: тише подписи самого поля и теснее к нему, чем card-lead. */
.field-hint{
  margin:6px 0 0; font-size:12.5px; line-height:1.45; color:var(--text-muted);
}

/* Кто подтверждает документы категории — очередь одной строкой под названием. */
.cat-signers{ margin:8px 0 0; font-size:13.5px; line-height:1.45; }

/* ---------- Очередь оплат ------------------------------------------------
   Тринадцать колонок той таблицы, которую вели в Excel. Ячейки узкие, шрифт
   мельче обычного: строку надо читать целиком, не прокручивая её по
   горизонтали дважды. */
/* Таблица очереди: сорок-пятьдесят строк на экране — обычный недельный план,
   и каждая лишняя пара пикселей в строке это ещё один документ, до которого
   надо прокручивать. */
/* Таблица укладывается в ширину экрана и не уезжает вбок: ширины колонок
   заданы долями, а поля внутри тянутся по ячейке. Раньше каждое поле несло
   свою ширину, сумма их не помещалась, и план приходилось читать, катая его
   влево-вправо — а читают его целой строкой. */
.payq-table{ font-size:12.5px; width:100%; table-layout:fixed; }
/* Ниже этой ширины колонки становятся щелями, где дата не помещается целиком:
   таблица уходит под горизонтальную прокрутку, а не сжимается до нечитаемого. */
.table-wrap .payq-table{ min-width:1120px; }
.payq-table th, .payq-table td{ padding:5px 6px; vertical-align:middle; }
/* Заголовок переносится по словам и стоит на нижней линии. «Согласованная дата
   оплаты» не встаёт в одну строку ни при какой ширине колонки, а в nowrap она
   наезжала на соседнюю — шапка читалась как каша из слипшихся слов. */
.payq-table thead th{
  white-space:nowrap; vertical-align:bottom; hyphens:none;
  padding:9px 4px 7px 11px; font-size:10px; letter-spacing:.02em;
}
/* У числовых колонок значение прижато вправо — заголовок тоже. */
.payq-table thead th.num{ padding:9px 11px 7px 4px; }
/* Поле тянется по своей ячейке. Раньше каждое несло собственную ширину в
   пикселях — 150, 230, 126; их сумма была шире экрана, и строка вылезала за
   карточку, а таблицу приходилось катать влево-вправо. */
.payq-table .cell-input{
  width:100%; min-width:0; max-width:100%; padding:4px 6px; font-size:12.5px;
  /* Ячейка таблицы скруглена меньше обычного поля: строка из двенадцати
     скруглённых полей читается как россыпь, а не как строка. */
  border-radius:4px;
}
/* Доли ширины: имя, поставщик и описание — широкие; даты ровно под
   «12.09.2026» вместе с календарём; выбор — под трёхбуквенный код. */
.payq-table th:nth-child(1){ width:4%; }      /* очерёдность   */
.payq-table th:nth-child(2){ width:9.5%; }    /* кто отвечает  */
.payq-table th:nth-child(3){ width:8%; }      /* категория     */
.payq-table th:nth-child(4){ width:10%; }     /* поставщик     */
.payq-table th:nth-child(5){ width:10.5%; }   /* описание      */
.payq-table th:nth-child(6){ width:13%; }     /* сумма         */
.payq-table th:nth-child(7){ width:7%; }      /* USD           */
.payq-table th:nth-child(8){ width:7%; }      /* покупатель    */
.payq-table th:nth-child(9){ width:9.5%; }    /* согласовано   */
.payq-table th:nth-child(10){ width:9.5%; }   /* оплачено      */
.payq-table th:nth-child(11){ width:6%; }     /* условия       */
.payq-table th:nth-child(12){ width:6%; }     /* пометка и «×» */
/* Строка тела — одна строка, как в Excel: перенос внутри ячейки сдвигает
   соседние вниз, и план из пятидесяти платежей перестаёт читаться глазами —
   в нём начинают искать вместо того, чтобы смотреть. Длинное прячется в самом
   поле, по которому и так ходят курсором. */
.payq-table tbody td{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.payq-table .cell-sub{
  display:block; margin-top:1px; font-size:11px;
  overflow:hidden; text-overflow:ellipsis;
}
/* Стрелки числового поля забирали половину узкой колонки, а очерёдность правят
   с клавиатуры. */
.payq-table .cell-num{ text-align:right; -moz-appearance:textfield; }
.payq-table .cell-num::-webkit-outer-spin-button,
.payq-table .cell-num::-webkit-inner-spin-button{ -webkit-appearance:none; margin:0; }
/* Сумма и валюта делят одну ячейку: число тянется, код валюты — по буквам.
   Флекс внутри ячейки, а не на самой ячейке: display:flex на <td> выбивает её
   из табличной сетки, и колонка справа уезжает под строку. */
.payq-table .cell-cur{
  flex:0 0 48px; width:48px; margin:0; padding:4px 1px 4px 4px; font-size:11px;
}
/* Дата: поле ровно под «12.09.2026» с календарём. В прежние 126px колонка не
   укладывалась, и год обрезался на середине. */
.payq-table .cell-date{ padding:3px 4px; font-size:11.5px; }
/* Стрелка выбора — своя и узкая. Родная забирает около восемнадцати пикселей
   там, где вся ячейка отведена под трёхбуквенный код: «BORC» превращалось в
   «BOR(». Повторена для :focus, потому что фокус задаёт фон короткой записью и
   вместе с ней стирает картинку. */
.payq-table select.cell-input,
.payq-table select.cell-input:focus{
  -webkit-appearance:none; appearance:none; padding:4px 12px 4px 5px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M1 1l3 3 3-3' fill='none' stroke='%23888F99' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 4px center;
}
/* Полоса блока: пачка, заведённая и отправленная за один раз, начинается
   строкой с датой и временем — по ней её и находят («что я подал во
   вторник»). Полоса не ячейка с данными: она тише строк и плотнее их. */
.payq-table .payq-block-head td{
  padding:9px 11px 7px; background: var(--surface-strong);
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  font-size:11.5px; color: var(--text-faint); white-space:nowrap;
}
.payq-table .payq-block-when{ font-weight:650; color: var(--text-muted); }
.payq-table .payq-block-meta{ margin-left:4px; }
/* «Перекорректировать» стоит в самой полосе блока: пачку возвращают там же,
   где на неё смотрят. Кнопка тише строк — это действие над блоком, а не над
   таблицей, и место ей справа от его подписи. */
.payq-table .payq-block-back{
  margin-left:10px; padding:1px 9px; font-size:11px; line-height:1.6;
  vertical-align:baseline;
}
/* Итог пачки: та же строка таблицы, но тяжелее шрифтом и с чертой сверху —
   её читают как подведение, а не как ещё один платёж. */
.payq-block-total td{
  border-top:1px solid var(--line);
  font-weight:600; color:var(--text);
  background: color-mix(in srgb, var(--surface-strong) 60%, transparent);
}
.payq-block-total .payq-block-meta{ font-weight:400; }
/* Открытый блок — тот, в котором сейчас работают: подсвечен слева, как
   строка с состоянием, и назван словами, а не датой, которой у него ещё
   нет. */
.payq-table .payq-block.is-open .payq-block-head td{
  background: var(--accent-tint);
  box-shadow: inset 3px 0 0 var(--accent-1);
}
.payq-table .payq-block.is-open .payq-block-when{ color: var(--accent-1); }
/* Блоки идут встык: двойная линия между ними читается как разрыв таблицы. */
.payq-table tbody:first-of-type .payq-block-head td{ border-top:0; }
/* Хронология: короткие строки одна под другой, без рамок. */
/* Итог над таблицей: строка, а не карточка. */
.sum-line{
  display:flex; align-items:baseline; flex-wrap:wrap; gap:12px;
  margin:0 0 10px; font-size:14px;
}
.sum-line .sum-amount{ font-weight:700; font-variant-numeric:tabular-nums; }
/* Черновик: строка заведена, но ещё не показана тем, кто платит. */
.payq-table tr.is-draft{ background:var(--surface-strong); }
.payq-table tr.is-draft td:first-child{ box-shadow:inset 3px 0 0 var(--text-faint); }
/* Курс рядом с кнопкой сохранения: подпись и узкое поле в одну строку. */
/* Ряд блоков-месяцев над таблицей и строка правки открытого. */
.plan-bar{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px; }
.plan-head{ display:flex; flex-wrap:wrap; gap:10px; margin-bottom:12px; }
.plan-head .cell-input{ width:220px; }
/* «Курс $» стоит в одном ряду с кнопками страницы. Поле со своей высотой
   ломало ряд: оно было на шесть пикселей выше кнопок и торчало над ними и
   под ними — у админа, который один его и видит, шапка выглядела съехавшей.
   Теперь это такая же таблетка: подпись и поле внутри, высота кнопки. */
.rate-field{
  display:inline-flex; align-items:center; gap:8px; margin:0;
  height:38px; padding:0 6px 0 13px;
  border:1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-strong);
  font-size:12.5px; font-weight:600; color:var(--text-muted); white-space:nowrap;
}
.rate-field input.cell-input{
  width:72px; height:28px; padding:0 9px; font-size:13px; border-radius:var(--radius-xs);
  background: var(--surface-solid);
}
.payq-table .cell-num{ text-align:right; }
/* Сумма и валюта делят одну ячейку. */
.payq-table .range-pair{ display:flex; gap:4px; align-items:center; }
.payq-table .range-pair .cell-input{ flex:1 1 auto; min-width:0; }
/* Крестик вместо слова «Убрать»: слово забирало целую колонку. */
.cell-drop{ padding:3px 7px; font-size:14px; line-height:1; vertical-align:middle; }
.payq-table .money{ font-variant-numeric:tabular-nums; white-space:nowrap; }
/* Цвет строки — это её состояние, и читается он раньше любых цифр: зелёная
   оплачена, жёлтой платить на днях, красная просрочена. Заливка слабая, а
   полоса слева плотная: сорок строк подряд, залитых в полную силу, читаются
   хуже, чем белая таблица. */
.payq-table tr.is-paid td{ background: color-mix(in srgb, var(--success) 9%, transparent); }
.payq-table tr.is-soon td{ background: color-mix(in srgb, var(--warn) 12%, transparent); }
.payq-table tr.is-late td{ background: color-mix(in srgb, var(--danger) 9%, transparent); }
.payq-table tr.is-paid td:first-child{ box-shadow:inset 3px 0 0 var(--success); }
.payq-table tr.is-soon td:first-child{ box-shadow:inset 3px 0 0 var(--warn); }
.payq-table tr.is-late td:first-child{ box-shadow:inset 3px 0 0 var(--danger); }
/* Подпись к цветам: цвет без подписи каждый читает по-своему. */
.payq-legend{
  display:flex; flex-wrap:wrap; align-items:center; gap:4px 16px;
  margin:0 0 10px; font-size:12px; color:var(--text-faint);
}
.legend-mark{
  display:inline-block; width:10px; height:10px; margin-right:5px;
  border-radius:3px; vertical-align:-1px;
}
.legend-mark.is-paid{ background:var(--success); }
.legend-mark.is-soon{ background:var(--warn); }
.legend-mark.is-late{ background:var(--danger); }
/* Ручная пометка строки — после вычисленных цветов, поэтому она их и
   перекрывает: цвет, поставленный человеком, важнее посчитанного. Заливка
   заметнее автоматической — её ставили нарочно, чтобы найти строку взглядом. */
.payq-table tr.is-marked td{ background: color-mix(in srgb, #F5A524 38%, transparent); }
/* Поля внутри помеченной строки тоже в цвете: иначе строка оранжевая только
   между ячейками, а сами поля белые — и цвета не видно там, где смотрят. */
.payq-table tr.is-marked .cell-input{
  background: color-mix(in srgb, #F5A524 16%, var(--surface-solid));
  border-color: color-mix(in srgb, #F5A524 50%, var(--line));
}
/* Сама пометка: кружок, который закрашивается нажатием. Список из четырёх
   цветов заставлял выбирать оттенок там, где решение одно — вернуться к этой
   строке или нет. */
.mark-toggle{ display:inline-block; cursor:pointer; padding:3px; vertical-align:middle; }
.mark-toggle input{ position:absolute; opacity:0; width:0; height:0; }
.mark-toggle span{
  display:block; width:15px; height:15px; border-radius:50%;
  border:1.5px solid var(--line);
  transition: background var(--transition), border-color var(--transition);
}
.mark-toggle input:checked + span{ background:#F5A524; border-color:#F5A524; }
.mark-toggle input:focus-visible + span{ box-shadow:0 0 0 4px var(--tint-warn); }

/* Перестановка строк: номер, стрелки и ручка живут в первой ячейке одной
   строчкой — колонка и так узкая. */
.order-cell{ white-space:nowrap; }
.order-no{ display:inline-block; min-width:16px; text-align:right;
           font-variant-numeric:tabular-nums; color:var(--text-muted); }
.row-move{ display:inline-flex; flex-direction:column; margin-left:4px; vertical-align:middle; }
.move-btn{
  border:0; background:none; cursor:pointer; padding:0 2px;
  font-size:11px; line-height:1; color:var(--text-faint);
  transition: color var(--transition), transform 140ms var(--spring);
}
.move-btn:hover{ color:var(--accent-1); transform:scale(1.25); }
/* Ручка: за неё берутся мышью, поэтому она размером с палец, а не с букву.
   Точки бледные, пока на строку не навели, — иначе двенадцать ручек в
   таблице перетягивают взгляд на себя. */
.drag-handle{
  display:inline-flex; align-items:center; justify-content:center;
  width:22px; height:26px; margin-left:2px; vertical-align:middle;
  border-radius:var(--radius-xs); cursor:grab; user-select:none;
  color:var(--text-faint); opacity:.45;
  transition: opacity var(--transition), background var(--transition),
              color var(--transition);
}
.drag-handle svg{ width:9px; height:15px; }
.payq-table tr:hover .drag-handle{ opacity:1; }
.drag-handle:hover{ background:var(--surface-strong); color:var(--accent-1); }
.drag-handle:active{ cursor:grabbing; background:var(--accent-tint); }
/* Строка, которую несут: приподнята и чуть светлее — видно, что она в руке,
   и видно место, куда встанет, потому что соседи уже разошлись. */
.payq-table tr.is-dragging td{
  opacity:.9; background:var(--surface-strong);
  box-shadow:0 10px 24px -12px rgba(17,17,17,.45);
}
.payq-table tr.is-dragging .drag-handle{ opacity:1; color:var(--accent-1); }
/* Куда строка приехала — видно секунду после перестановки. */
.payq-table tr.just-moved td{ animation: row-landed 700ms var(--ease-ios); }
@keyframes row-landed{
  0%{ background: color-mix(in srgb, var(--accent-1) 18%, transparent); }
  100%{ background: transparent; }
}
@media (prefers-reduced-motion: reduce){
  .payq-table tr.just-moved td{ animation:none; }
}
/* Ячейку не превращаем во флекс-контейнер — она перестаёт быть ячейкой и
   уходит за край таблицы. Кружок и крестик и так стоят рядом: строка одна.
   display задан прямо: общий .row-actions ниже по файлу — флекс. */
.payq-table td.row-actions{
  display:table-cell; text-align:right; white-space:nowrap;
}
/* Кнопка, внутри которой спрятан выбор файла: её нажимают, а не поле. */
.file-button{ cursor:pointer; }
/* «В корзину»: выбор документа и кнопка одной строкой. */
.basket-add{ display:flex; flex-wrap:wrap; gap:10px; align-items:center; }
.basket-add select{ flex:1; min-width:260px; }
/* Шапка корзины: три способа положить платёж — одной строкой, чтобы таблица
   начиналась сразу, а не за полтора экрана объяснений. */
.basket-tools{ display:flex; flex-wrap:wrap; align-items:center; gap:10px; }
.basket-tools .basket-add{ flex:0 1 auto; margin:0; }
.basket-tools .basket-add:first-child{ flex:1 1 320px; }
.basket-head .card-lead{ margin:12px 0 4px; }
.basket-hint{ margin:0; font-size:12.5px; }
/* Загрузка плана: поле файла, кнопка и пояснение под ними одной строкой. */
/* Загрузка плана в шапке страницы: поле и кнопка одной строкой. */
.inline-upload{ display:flex; align-items:center; gap:8px; }
.inline-upload input[type="file"]{ max-width:210px; font-size:12.5px; }
.basket-import{ margin-top:12px; align-items:center; }
.basket-import input[type="file"]{ flex:1; min-width:240px; font-size:13px; }
.basket-import .cell-sub{ flex-basis:100%; margin-top:2px; }

/* ---------- Flash messages ---------- */
.flash-stack{
  position:fixed; top:16px; left:50%; transform:translateX(-50%);
  z-index:80; display:grid; gap:10px; width:min(440px, calc(100vw - 32px));
}
.flash{
  padding:13px 22px; border-radius: var(--radius-xs); color:#fff; font-weight:600;
  font-size:14px; text-align:center;
  box-shadow: var(--shadow-lift), inset 0 1px 0 rgba(255,255,255,.22);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  animation: flash-in 520ms var(--spring) both;
}
.flash-success{ background: linear-gradient(145deg, color-mix(in srgb, var(--success) 78%, #fff), var(--success)); }
.flash-error{ background: linear-gradient(145deg, color-mix(in srgb, var(--danger) 80%, #fff), var(--danger)); }
.flash-info{ background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b)); }
@keyframes flash-in{
  from{ opacity:0; transform: translateY(-22px) scale(.92); }
  to{ opacity:1; transform: translateY(0) scale(1); }
}

/* ---------- Auth / error card ---------- */
.auth-wrap{ min-height:100vh; display:grid; place-items:center; padding:24px; }
.auth-card{
  width:100%; max-width:430px; padding:40px 34px;
  border-radius: var(--radius-xl);
  animation: card-in 420ms var(--ease-ios) both;
}
@keyframes card-in{
  from{ opacity:0; transform: translateY(14px); }
  to{ opacity:1; transform:none; }
}
.auth-card h2{ text-align:center; font-size:25px; }
.auth-card .sub{ text-align:center; margin-bottom:26px; font-size:14.5px; }
.auth-card.center{ text-align:center; }
.error-code{
  font-size:74px; font-weight:800; letter-spacing:-.05em; line-height:1;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  -webkit-background-clip:text; background-clip:text; color:transparent;
  margin-bottom:12px;
}

/* A banner the login page shows only while the password is switched off, so
   the state is never a surprise. */
.notice{
  display:flex; gap:10px; align-items:flex-start;
  padding:12px 16px; margin-bottom:22px;
  border-radius: var(--radius-md); border:1px solid var(--line);
  background: var(--accent-tint);
  font-size:13px; line-height:1.45; color:var(--text-muted); text-align:left;
}
.notice strong{ color:var(--text); display:block; font-size:13.5px; }
.notice-ico{ font-size:15px; line-height:1.35; }

/* ---------- Brand lockup ---------- */
/* The SF tile on its own; the wordmark only on the printed sheet — see the
   note in templates/brand.html. Alone in the sidebar corner it is a size up. */
.brand{ display:flex; align-items:center; gap:12px; color:var(--text); }
.brand-text{ display:grid; line-height:1.2; }

/* The mark: an S for SEYCO with a light stroke under it — the flourish of a
   signature, since signing is what the panel is for. The tab icons
   (static/images/favicon-*) are rendered from this same drawing. Colours are
   fixed, not theme tokens: the dark theme lightens --accent-1, and the tile
   must stay the same green as the icon in the tab above it. Everything is in
   proportions of the tile, so one rule serves 42 px in the sidebar and 64 px
   on the sign-in card. */
.brand-mark{
  position:relative; flex:none; display:grid; place-items:center;
  width:42px; height:42px; border-radius:var(--radius-md);
  background: linear-gradient(145deg, #2D8F55 0%, #186236 55%, #104526 100%);
  color:#fff; font-family:var(--font-display);
  font-size:25px; font-weight:800; line-height:1;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28), inset 0 -2px 6px rgba(0,0,0,.18),
              0 6px 16px rgba(15,66,36,.30);
  user-select:none;
}
.brand-mark > span{ transform: translateY(-10%); }
.brand-mark::after{
  content:""; position:absolute; left:50%; bottom:19%;
  width:40%; height:7%; border-radius:99px;
  transform: translateX(-50%) rotate(-4deg);
  background: linear-gradient(90deg, #9FDDB5, #D5F0DF);
}
/* How the wordmark is actually set lives in one place, further down. */

/* ---------- Panel shell ---------- */
.shell{ display:flex; min-height:100vh; gap:18px; padding:18px; }
.sidebar{
  width:256px; flex:none; padding:22px 16px;
  display:flex; flex-direction:column; gap:26px; position:sticky; top:18px;
  height: calc(100vh - 36px);
  border-radius: var(--radius-xl);
}
.nav{ display:grid; gap:3px; }
.nav-item{
  position:relative;
  display:flex; align-items:center; gap:11px; padding:11px 15px;
  border-radius: var(--radius-md); color:var(--text-muted);
  font-weight:600; font-size:14.5px;
  transition: color var(--transition), background var(--transition),
              transform 220ms var(--spring);
}
.nav-item:hover{ background: var(--surface-strong); color:var(--text); }
.nav-item:active{ transform: scale(.97); }
/* На широком экране значок слева от подписи, ровной колонкой: глаз ведёт по
   одной вертикали и не спотыкается о разную длину слов. Кнопка «Ещё» здесь
   не нужна — список виден целиком, прятать за ней нечего. */
.nav-ico{ width:19px; height:19px; flex:none; opacity:.9; }
.nav-more{ display:none; }
.nav-item.is-active{
  color:#fff;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,.26);
}
.sidebar-foot{ margin-top:auto; display:grid; gap:12px; }
.who{
  display:flex; align-items:center; gap:10px;
  padding:9px 11px; border-radius: var(--radius-md); background: var(--surface-strong);
}
.who-avatar{
  width:34px; height:34px; flex:none; border-radius:50%; display:grid; place-items:center;
  font-size:13px; font-weight:700; color:#fff;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
}
.who-text{ display:grid; min-width:0; }
.who-text strong{ font-size:13.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.who-text small{ font-size:11.5px; color:var(--text-faint); }
.theme-toggle{
  justify-self:start; border:1px solid var(--line); background:transparent;
  width:36px; height:36px; border-radius:50%; cursor:pointer; font-size:15px;
  display:grid; place-items:center;
  transition: background var(--transition), transform 300ms var(--spring);
}
.theme-toggle:hover{ background: var(--surface-strong); transform: rotate(-18deg); }
.theme-toggle:active{ transform: scale(.9); }

.content{ flex:1; min-width:0; padding:6px 6px 48px; }

/* The panel keeps theme and language in its sidebar; the sign-in and error
   screens have no sidebar, so theirs float in the corner. Somebody who only
   reads Turkish has to be able to switch before signing in, not after. */
.floating-controls{
  position:fixed; top:18px; right:18px; z-index:70;
  display:flex; align-items:center; gap:8px;
}
.theme-float{
  width:42px; height:42px; flex:none; border-radius:50%; cursor:pointer; font-size:16px;
  display:grid; place-items:center;
  background: var(--surface-strong); border:1px solid var(--border);
  box-shadow: var(--shadow-soft), inset 0 1px 0 var(--sheen);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  transition: transform 300ms var(--spring), box-shadow var(--transition);
}
.theme-float:hover{ transform: rotate(-18deg) scale(1.06); box-shadow: var(--shadow-lift); }
.theme-float:active{ transform: scale(.92); }

/* ---------- Language menu ------------------------------------------------
   The current language on one button, the four under it. A POST per option
   rather than a link: a language is a change to the session, and a GET that
   changes state can be triggered by anything that embeds the URL. */
.foot-row{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.lang-menu{ position:relative; }
.lang-current{
  list-style:none; cursor:pointer; user-select:none;
  display:flex; align-items:center; gap:8px;
  height:42px; padding:0 14px 0 12px; border-radius: var(--radius-xs);
  font-size:13.5px; font-weight:600; letter-spacing:-.01em; color:var(--text);
  background: var(--surface-strong); border:1px solid var(--border);
  box-shadow: var(--shadow-soft), inset 0 1px 0 var(--sheen);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  transition: transform 220ms var(--spring), box-shadow var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.lang-current::-webkit-details-marker{ display:none; }
.lang-current:hover{ box-shadow: var(--shadow-lift), inset 0 1px 0 var(--sheen); }
.lang-current:active{ transform: scale(.96); }
.lang-current:focus-visible{ outline:none; box-shadow: 0 0 0 3px var(--accent-tint); }
.lang-globe, .lang-chevron, .lang-check{
  fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round;
}
.lang-globe{ width:17px; height:17px; color:var(--accent-1); }
.lang-chevron{ width:14px; height:14px; color:var(--text-faint); transition: transform 220ms var(--spring); }
.lang-menu[open] .lang-chevron{ transform: rotate(180deg); }

.lang-list{
  position:absolute; top:calc(100% + 8px); right:0; z-index:80;
  min-width:184px; margin:0; padding:6px;
  display:grid; gap:2px;
  background: var(--surface-solid); border:1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lift);
  transform-origin: top right;
  animation: lang-pop 180ms var(--spring);
}
@keyframes lang-pop{ from{ opacity:0; transform: scale(.94) translateY(-4px); } }
.lang-option{
  font:inherit; font-size:14px; font-weight:500; text-align:left;
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  width:100%; padding:10px 12px; border:0; border-radius: var(--radius-sm);
  background:transparent; color:var(--text); cursor:pointer;
  transition: background var(--transition);
  -webkit-tap-highlight-color: transparent;
}
.lang-option:hover{ background: var(--surface-strong); }
.lang-option:focus-visible{ outline:none; box-shadow: 0 0 0 3px var(--accent-tint); }
.lang-option.is-active{ color:var(--accent-1); font-weight:650; }
.lang-check{ width:16px; height:16px; visibility:hidden; }
.lang-option.is-active .lang-check{ visibility:visible; }
@media (prefers-reduced-motion: reduce){
  .lang-list{ animation:none; }
}

/* iOS large title: full size at the top of the page, shrinking into a compact
   glass bar once the page scrolls. `.is-stuck` is set from main.js. */
.page-head{
  position:sticky; top:8px; z-index:20;
  display:flex; align-items:center; justify-content:space-between;
  gap:16px; margin-bottom:22px; padding:10px 14px; flex-wrap:wrap;
  border-radius: var(--radius-lg);
  border:1px solid transparent;
  transition: background 200ms var(--ease-ios), border-color 200ms var(--ease-ios);
}
/* `transform`, not `font-size`: scaling is done by the compositor, resizing
   text re-lays out the whole header — and the heading sits above the page, so
   that reflow reached everything under it. */
.page-head h1{
  margin:0; transform-origin:left center;
  transition: transform 200ms var(--ease-ios);
}
.page-head.is-stuck{
  background: var(--surface-strong); border-color: var(--border);
}
.page-head.is-stuck h1{ transform: scale(.74); }

/* ---------- Stat tiles ---------- */
.stat-grid{
  display:grid; gap:14px; margin-bottom:20px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.stat{
  padding:20px 22px; border-radius: var(--radius-lg);
  transition: transform 200ms var(--ease-ios);
}
.stat:hover{ transform: translateY(-3px); }
.stat-label{
  display:flex; align-items:center; gap:8px;
  font-size:12.5px; font-weight:600; color:var(--text-muted); margin-bottom:10px;
}
.stat-value{
  font-size:27px; font-weight:750; letter-spacing:-.035em; line-height:1.1;
  font-variant-numeric: tabular-nums; color:var(--text);
}
.stat-hint{ font-size:12.5px; color:var(--text-faint); margin:6px 0 0; }

/* ---------- Empty state ---------- */
.empty{ padding:52px 40px; text-align:center; max-width:660px; border-radius: var(--radius-xl); }
.empty-mark{
  width:68px; height:68px; margin:0 auto 18px; border-radius:var(--radius-lg);
  display:grid; place-items:center; font-size:31px; font-weight:800; color:#fff;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,.3);
}
.empty-hint{ font-size:13.5px; color:var(--text-faint); margin-bottom:0; }

/* ---------- Tables (for the first finance screen) ---------- */
.table-wrap{ overflow-x:auto; border-radius: var(--radius-lg); }
table{ width:100%; border-collapse:collapse; background: var(--surface-solid); }
th, td{ padding:14px 18px; text-align:left; border-bottom:1px solid var(--line); }
th{
  font-size:11.5px; font-weight:650; letter-spacing:.06em; text-transform:uppercase;
  color:var(--text-muted); background: var(--surface-strong);
}
td.num, th.num{ text-align:right; font-variant-numeric: tabular-nums; }
tbody tr:last-child td{ border-bottom:0; }
tbody tr{ transition: background 160ms var(--ease-ios); }
tbody tr:hover{ background: var(--surface-strong); }

/* ---------- Motion policy -------------------------------------------------
   Pages arrive already in place: no staged entrances, nothing that loops, and
   nothing animated behind a translucent surface. Movement is kept for what a
   person causes — a press, a modal, a toast — where it confirms an action
   rather than delaying the content. */

/* Circular reveal when the theme flips, driven from main.js. Without these the
   browser cross-fades instead, which on a full-page colour change looks like a
   flash rather than a wipe. */
::view-transition-old(root),
::view-transition-new(root){ animation:none; mix-blend-mode:normal; }
::view-transition-old(root){ z-index:0; }
::view-transition-new(root){ z-index:1; }

/* ---------- Mobile ---------- */
@media (max-width: 860px){
  h1{ font-size:25px; }
  .shell{ flex-direction:column; padding:12px 12px 96px; }
  .sidebar{
    width:auto; height:auto; position:static; flex-direction:row;
    align-items:center; gap:14px; padding:12px 14px;
  }
  /* The nav becomes an iOS tab bar pinned to the bottom edge. */
  .nav{
    position:fixed; left:12px; right:12px; bottom:12px; z-index:60;
    grid-auto-flow:column; gap:4px; padding:7px;
    background: var(--surface-strong); border:1px solid var(--border);
    border-radius: var(--radius-xl); box-shadow: var(--shadow-lift);
    backdrop-filter: blur(30px) saturate(180%);
    -webkit-backdrop-filter: blur(30px) saturate(180%);
  }
  /* Ровно четыре кнопки, всегда: три раздела и «Ещё». Не листается вбок —
     то, что за краем панели, для человека не существует, а заметить, что
     панель вообще листается, можно только случайно. Остальные разделы живут
     в «Ещё», и там они видны все сразу. */
  .nav{ grid-template-columns: repeat(4, 1fr); overflow:visible; }
  .nav .nav-item.is-extra{ display:none; }

  /* Значок над подписью, и подпись остаётся: картинку каждый читает
     по-своему, слово — одинаково. */
  .nav-item{
    flex-direction:column; gap:3px; font-size:10.5px; font-weight:600;
    padding:7px 4px; white-space:nowrap; text-align:center;
    letter-spacing:-.01em; border-radius:var(--radius-md);
  }
  .nav-item .nav-label{
    max-width:100%; overflow:hidden; text-overflow:ellipsis;
  }
  .nav-ico{ width:22px; height:22px; flex:none; }
  /* Активная вкладка — залитая пилюля, а не просто другой цвет текста: на
     ходу и одной рукой заливка видна боковым зрением, а оттенок букв нет. */
  .nav-item.is-active{
    background: var(--accent-tint); color: var(--accent-1);
  }
  .nav-item.is-active .nav-ico{ stroke-width:2; }
  .nav-count{ position:absolute; top:2px; right:8px; }
  .nav-item{ position:relative; }
  .nav-more{ display:flex; border:0; background:none; font:inherit; cursor:pointer; }

  /* Лист «Ещё»: выезжает снизу, оттуда же, где палец. */
  .modal-sheet{
    top:auto; bottom:0; margin-bottom:0; width:100%; max-width:none;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    padding-bottom: calc(16px + env(safe-area-inset-bottom));
  }
  .sheet-grid{ display:grid; grid-template-columns:repeat(3, 1fr); gap:8px; margin:14px 0; }
  .sheet-item{
    display:flex; flex-direction:column; align-items:center; gap:6px;
    padding:14px 6px; border-radius:var(--radius-md);
    background:var(--surface); border:1px solid var(--border);
    font-size:11.5px; font-weight:600; text-align:center; color:var(--text);
    position:relative;
  }
  .sheet-item .nav-ico{ width:24px; height:24px; }
  .sheet-item.is-active{ border-color:var(--accent-1); color:var(--accent-1); }
  .sidebar-foot{ margin:0 0 0 auto; grid-auto-flow:column; align-items:center; gap:10px; }
  .floating-controls{ top:12px; right:12px; }
  .who{ background:transparent; padding:0; }
  .who-text{ display:none; }
  .page-head{ top:0; }
}

/* ---------- Reduced motion -----------------------------------------------
   Everything above is decoration; nothing here carries meaning that is lost
   when it stops. Animations collapse to their end state rather than turning
   into an instant jump mid-flight. */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important; scroll-behavior:auto !important;
  }
  .field-bg span{ animation:none; }
}

/* ==========================================================================
   Wordmark
   ========================================================================== */

/* With nothing beside it, the name has to hold the corner on its own: caps,
   opened up. Tight tracking is for long words read as shapes; a five-letter
   wordmark wants air between the letters instead.

   The qualifier under it is the one place the accent appears in the lockup —
   the same trick as the printed version, where the name is black and the line
   under it is the company colour. */
.brand-text strong{
  font-size:17px; font-weight:800; letter-spacing:.11em;
  /* Caps have no descenders, so the optical gap under them reads wider than it
     measures; the negative margin takes that back. */
  margin-bottom:-1px;
}
.brand-text small{
  font-size:9.5px; font-weight:700; color: var(--accent-1);
  letter-spacing:.3em; text-transform:uppercase;
}

/* On the sign-in card there is nothing above it and nothing beside it, so it
   is set as a title rather than as a label: the tile goes on top, larger, and
   the name is centred under it. */
.brand-lg{ flex-direction:column; justify-content:center; gap:18px; margin-bottom:28px; }
.brand-lg .brand-mark{
  width:64px; height:64px; font-size:38px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.25),
              0 10px 26px rgba(20,83,45,.32);
}
.brand-lg .brand-text{ text-align:center; }
.brand-lg .brand-text strong{ font-size:31px; letter-spacing:.14em; margin-bottom:1px; }
.brand-lg .brand-text small{ font-size:11px; letter-spacing:.42em; }

/* Centred text with wide tracking hangs to the left: the space after the last
   letter is real, the one before the first is not. */
.brand-lg .brand-text strong,
.brand-lg .brand-text small{ text-indent:.14em; }

/* --- Анимация логотипа на входе -------------------------------------------
   Только на большом лого страницы входа (в сайдбаре оно статично — дёргать
   его при каждом переходе было бы навязчиво). SEYCO поднимается, FINANCE
   проявляется, разводя буквы к финальному трекингу — сдержанно, «дорого»,
   в тему финансов. Тонкая линия прочерчивается под словом. Первой, раньше
   слов, появляется плитка SF: она чуть подрастает до своего размера. */
.brand-lg .brand-mark{
  animation: mark-lg-in 560ms var(--ease-ios) 40ms both;
}
.brand-lg .brand-text strong{
  animation: seyco-lg-in 620ms var(--ease-ios) 140ms both;
}
.brand-lg .brand-text small{
  position: relative;
  animation: fin-lg-in 760ms var(--ease-ios) 380ms both;
}
.brand-lg .brand-text small::after{
  content:""; position:absolute; left:50%; bottom:-8px; height:2px; width:0;
  border-radius:2px; transform:translateX(-50%);
  background: linear-gradient(90deg, var(--accent-1-light), var(--accent-1));
  animation: fin-rule 620ms var(--ease-ios) 720ms both;
}
@keyframes mark-lg-in{
  from{ opacity:0; transform: scale(.82); }
  to{   opacity:1; transform: none; }
}
@keyframes seyco-lg-in{
  from{ opacity:0; transform: translateY(12px); }
  to{   opacity:1; transform: none; }
}
@keyframes fin-lg-in{
  from{ opacity:0; letter-spacing:.12em; }
  to{   opacity:1; letter-spacing:.42em; }
}
@keyframes fin-rule{
  from{ width:0; opacity:0; }
  to{   width:60%; opacity:1; }
}
/* Кто отключил анимации в системе — получает готовый кадр без движения. */
@media (prefers-reduced-motion: reduce){
  .brand-lg .brand-mark,
  .brand-lg .brand-text strong,
  .brand-lg .brand-text small,
  .brand-lg .brand-text small::after{ animation: none; }
  .brand-lg .brand-text small::after{ width:60%; opacity:1; }
}

/* ==========================================================================
   Document workflow
   ========================================================================== */

.visually-hidden{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}
.lead{ max-width:70ch; margin-bottom:20px; }
.muted{ color:var(--text-faint); }
.mono{ font-family:var(--font-mono); font-size:.9em; }
.narrow{ max-width:520px; }
.mt{ margin-top:14px; }
.section-title{ margin:26px 0 12px; font-size:16px; }

.card{ padding:22px 24px; margin-bottom:16px; }
.card-lead{ margin-bottom:18px; }
.card-head{
  display:flex; align-items:center; justify-content:space-between;
  gap:12px; margin-bottom:14px;
}
.card-head h3{ margin:0; }
.card-foot{
  display:flex; align-items:center; justify-content:space-between;
  gap:12px; margin-top:16px; padding-top:14px; border-top:1px solid var(--line);
}
.two-col{ display:grid; gap:16px; grid-template-columns:repeat(auto-fit, minmax(320px, 1fr)); }
.form-grid{ display:grid; gap:14px; grid-template-columns:repeat(auto-fit, minmax(190px, 1fr)); }
.form-grid .field{ margin-bottom:0; }
/* Комментарий в форме счёта — своей сеткой под полями: с тем же зазором,
   что между полями, а не впритык к подсказке над ним. */
.comment-grid{ margin-top:14px; }
.field-wide{ grid-column:1 / -1; }
.field-submit{ display:flex; align-items:flex-end; }

/* Language switch and the role picker are defined once, up with the other
   controls. A second copy lived here and won by being later in the file: its
   `.role-card` was a flex row, which put the role's hint beside its name
   instead of under it. */

/* ---------- Badges, chips, verdicts ------------------------------------- */
.badge{
  display:inline-flex; align-items:center; gap:5px;
  padding:3px 10px; border-radius:var(--radius-xs);
  font-size:11.5px; font-weight:700; letter-spacing:.01em; white-space:nowrap;
  background:var(--surface-strong); color:var(--text-muted);
}
.badge-urgent{ background:var(--accent-1); color:#fff; }
.badge-muted{ background:var(--surface-strong); color:var(--text-faint); }
.badge-processing{ background:var(--tint-neutral); color:var(--text-muted); }
.badge-pending-admin12,
.badge-pending-admin1,
.badge-pending-admin2,
.badge-pending-admin3{ background:var(--accent-tint); color:var(--accent-1); }
.badge-approved{ background:var(--tint-success); color:var(--success); }
.badge-rejected{ background:var(--tint-danger); color:var(--danger); }
.badge-needs-review{ background:var(--tint-warn); color:var(--warn); }

.chip{
  display:inline-flex; align-items:center; gap:6px;
  padding:3px 11px; border-radius:var(--radius-xs);
  font-size:12px; font-weight:600; white-space:nowrap;
  color:var(--chip, var(--accent-1));
  background:color-mix(in srgb, var(--chip, var(--accent-1)) 14%, transparent);
}
.chip-empty{ color:var(--text-faint); background:var(--surface-strong); }

.verdict{
  display:inline-flex; align-items:center; gap:6px;
  padding:6px 13px; border-radius:var(--radius-xs);
  font-size:13px; font-weight:650;
}
.verdict-ok{ background:var(--tint-success); color:var(--success); }
.verdict-warn{ background:var(--tint-warn); color:var(--warn); }
.verdict-unknown{ background:var(--surface-strong); color:var(--text-muted); }
.verdicts{ display:flex; flex-wrap:wrap; gap:8px; margin:14px 0; }
.ok-tick{ color:var(--success); font-weight:700; }
.warn-tick{ color:var(--warn); font-weight:700; }

.pin-mark{
  display:inline-block; padding:1px 7px; border-radius:var(--radius-xs);
  font-size:10px; font-weight:800; letter-spacing:.08em;
  background:var(--accent-1); color:#fff;
}

/* ---------- Dashboard cards ---------------------------------------------- */
.card-grid{
  display:grid; gap:12px; margin-bottom:18px;
  grid-template-columns:repeat(auto-fit, minmax(158px, 1fr));
}
.count-card{
  display:grid; gap:2px; padding:18px 20px; color:var(--text);
  border-radius:var(--radius-lg);
  transition: transform 200ms var(--ease-ios);
}
.count-card:hover{ transform:translateY(-3px); }
.count-card:active{ transform:scale(.98); }
.count-value{ font-size:30px; font-weight:750; letter-spacing:-.035em; font-variant-numeric:tabular-nums; }
.count-label{ font-size:12.5px; color:var(--text-muted); font-weight:600; }
/* An urgent count that is not zero should be impossible to scroll past. */
.count-card.is-hot{
  background:linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  border-color:transparent; color:#fff; box-shadow:var(--shadow-accent);
}
.count-card.is-hot .count-label{ color:rgba(255,255,255,.88); }

/* ---------- Document rows ------------------------------------------------ */
.doc-list{ display:grid; gap:10px; }
.doc-row{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:14px 18px; color:var(--text);
  background:var(--surface-strong); border:1px solid var(--border);
  border-radius:var(--radius-md); box-shadow:var(--shadow-soft);
  /* Transform only. Animating box-shadow repaints the row on every frame, and
     a list is where that is felt. */
  transition: transform 180ms var(--ease-ios), border-color var(--transition);
}
.doc-row:hover{ transform:translateY(-2px); border-color:var(--line); }

/* Две кнопки в одной ячейке таблицы: «Сохранить» и «Выдать пароль». */
.row-actions{ display:flex; gap:6px; flex-wrap:wrap; }

/* Выключенная категория: её держат ради старых документов, поэтому она
   остаётся на экране, но не должна выглядеть как рабочая. */
.cat-card.is-off{ opacity:.72; }
.cat-card.is-off .cat-dot{ filter:grayscale(1); }
.cat-off-note{
  margin:0 0 4px; font-size:12.5px; color:var(--text-muted);
  background:var(--tint-warn); border-radius:var(--radius-sm); padding:8px 10px;
}

/* ---------- Оплата -------------------------------------------------------
   Строка «ждёт оплаты»: сам документ — ссылка, кнопка рядом. Кнопку нельзя
   класть внутрь ссылки, поэтому это две части одной строки, а не одна. */
.pay-list{ display:grid; gap:10px; margin-top:14px; }
.pay-row{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:12px 16px; flex-wrap:wrap;
  background:var(--surface-strong); border:1px solid var(--border);
  border-radius:var(--radius-md); box-shadow:var(--shadow-soft);
}
.pay-doc{ display:grid; gap:4px; min-width:0; flex:1; color:var(--text); }
.pay-top{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.pay-side{ display:flex; align-items:center; gap:12px; }
.paid-mark{
  display:inline-flex; align-items:center; gap:4px;
  font-size:12px; font-weight:650; color:var(--success);
  background:var(--tint-success); border-radius:var(--radius-xs); padding:3px 9px;
}
@media (max-width: 560px){
  .pay-side{ width:100%; justify-content:space-between; }
}
.doc-row:active{ transform:scale(.995); }
/* Urgent rows carry a red edge — the queue is sorted by it too, so the colour
   confirms the order rather than being the only signal. */
.doc-row.is-urgent{
  border-color:color-mix(in srgb, var(--accent-1) 45%, transparent);
  box-shadow:var(--shadow-soft), inset 3px 0 0 var(--accent-1);
}
/* Просрочка видна и на телефоне, где текст метаданных скрыт: полоса слева
   красная, как у срочного — синяя. Срочность и просрочка вместе бывают, и
   тогда выигрывает просрочка: срок уже нарушен, а не «важно». */
.doc-row.is-overdue{
  border-color:color-mix(in srgb, var(--danger) 45%, transparent);
  box-shadow:var(--shadow-soft), inset 3px 0 0 var(--danger);
}
/* Срок, до которого ещё далеко: дата без цвета — она не новость. */
.due-plain{ font-size:12.5px; color:var(--text-faint); white-space:nowrap; }

/* Левая колонка забирает всё свободное место: имя строки важнее меток. */
.doc-main{ display:grid; gap:3px; min-width:0; flex:1 1 auto; }
/* The number is an identifier, not code. The mono face was drawing it with
   slab hyphens and slots too wide for four digits; the display face with
   tabular figures keeps the columns aligned down the list and still reads as
   one word. */
.doc-number{
  font-family:var(--font-display); font-size:12.5px; font-weight:700;
  letter-spacing:.04em; color:var(--text-faint);
  font-variant-numeric: tabular-nums lining-nums;
}
/* Служебный ярус: номер, кто сдал, когда, БИН. Одной строкой и мельче — это
   справка, а не имя: читают её, только когда уже нашли нужную строку. */
.doc-meta{
  font-size:12.5px; color:var(--text-faint);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* Имя строки: компания, на которую пришёл документ, и поставщик. */
.doc-company{
  font-size:15px; font-weight:650; color:var(--text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* Метки справа под суммой: приоритет, статус, оплата, срок, категория. В одну
   строку и с переносом — их бывает пять, и все они короткие. */
.doc-marks{
  display:flex; align-items:center; justify-content:flex-end;
  flex-wrap:wrap; gap:6px;
}
/* Правая колонка: сумма и метки. flex:none здесь был ошибкой — метки
   (приоритет, статус, оплата, срок, категория) в сумме шире имени, и колонка,
   которая не сжимается, выдавливала левую часть до нуля: строка выглядела
   пустой, а метки уезжали под сумму через всю ширину. Теперь сжимается она, а
   не имя, и шире 44% строки не становится. */
.doc-side{
  display:grid; gap:6px; justify-items:end; text-align:right;
  flex:0 1 auto; min-width:0; max-width:min(44%, 340px);
}
.doc-amount{ font-weight:700; font-variant-numeric:tabular-nums; white-space:nowrap; }
/* Метка длиннее колонки («Ремонт и техническое обслуживание» в узкой строке
   на главной) обрезается многоточием, а не вылезает за карточку: полное
   название — во всплывающей подсказке у самой метки. */
.doc-marks{ min-width:0; max-width:100%; }
.doc-marks > *{ max-width:100%; min-width:0; }
.doc-marks .chip{ display:inline-block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* Плотная очередь — ТЗ: «уменьшить размер строки, чтобы на страницу вмещалось
   больше 10 счетов». На большом экране строка — полтора яруса вместо трёх:
   слева имя и справка, справа сумма и метки в одну линию; отступы и метки
   мельче, между строками 6px. Строка ~52px вместо ~80: на обычном ноутбуке
   под фильтрами помещается 12–14 счетов. */
/* Только в очереди (.doc-list.is-dense): на главной та же строка стоит в
   колонке вдвое уже, и сумма с метками в одну линию туда не помещаются. */
@media (min-width: 861px){
  .doc-list.is-dense{ gap:6px; }
  .is-dense .doc-row{ padding:8px 14px; gap:12px; border-radius:var(--radius-sm); }
  .is-dense .doc-row:hover{ transform:none; }
  .is-dense .doc-main{ gap:1px; }
  .is-dense .doc-company{ font-size:14px; }
  .is-dense .doc-meta{ font-size:12px; }
  .is-dense .doc-side{
    display:flex; align-items:center; justify-content:flex-end; gap:10px;
    max-width:min(58%, 560px);
  }
  .is-dense .doc-side .doc-amount{ order:2; min-width:9ch; text-align:right; }
  .is-dense .doc-marks{ order:1; gap:4px; }
  .is-dense .doc-marks .badge, .is-dense .doc-marks .chip, .is-dense .doc-marks .paid-mark{
    font-size:11px; padding:2px 7px;
  }
}

/* Кружок статуса. На большом экране его нет: там статус написан словом. Цвет
   берётся из класса badge-<статус>, поэтому точка и бейдж не разъедутся. */
.doc-dot{
  display:none; width:9px; height:9px; border-radius:50%;
  margin-right:8px; flex:none; vertical-align:middle;
  /* У бейджей цвет статуса — в тексте, у точки он должен быть в заливке. */
  background:currentColor;
}

/* ---------- Страница «Оплата»: строки шага --------------------------------
   Плотнее прежних карточек (ТЗ: «посмотреть списком сразу 10 и более
   счетов»): одна строка — номер, компания, поставщик, метки; под ней мелкая
   справка; справа сумма к оплате и кнопки шага. */
.desk-list{ gap:6px; }
.desk-row{ padding:8px 12px; gap:10px; flex-wrap:nowrap; }
.desk-row .pay-doc{ gap:2px; }
.desk-row .pay-top{ gap:6px; font-size:14px; }
.desk-row .doc-meta{ font-size:12px; }
.desk-supplier{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:32ch; }
/* № счёта на оплату рядом с поставщиком: по нему видно повторно пришедший счёт. */
.desk-invoice{
  font-weight:650; color:var(--text); font-variant-numeric: tabular-nums lining-nums;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:24ch;
}
.desk-row .pay-side{ gap:6px; flex:none; }
.desk-row .pay-side form{ display:inline; margin:0; }
@media (max-width: 860px){
  .desk-row{ flex-wrap:wrap; }
  .desk-row .pay-side{ width:100%; flex-wrap:wrap; justify-content:flex-start; }
}

/* Очередь оплат в Google Таблице: блок-дорога к ней, кнопка открывает её в
   новой вкладке. */
.sheet-card .btn{ margin-top:6px; }

/* ---------- Подпись пачкой ------------------------------------------------
   Галочка слева от строки очереди и панель над списком: сколько выбрано и
   одна кнопка на все. Панель липнет к верху экрана, пока список листают. */
.batch-bar{
  position:sticky; top:8px; z-index:5;
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  padding:8px 14px; margin:0 0 8px; border-radius:var(--radius-md);
}
.batch-bar.has-picks{ box-shadow:var(--shadow-accent); }
.batch-all{ display:flex; align-items:center; gap:8px; font-size:13px; cursor:pointer; }
.batch-count{ font-size:13px; font-weight:650; color:var(--text-muted); margin-left:auto; }
.doc-pickrow{ display:flex; align-items:center; gap:8px; }
.doc-pickrow > .doc-row{ flex:1 1 auto; min-width:0; }
.doc-pick{ flex:none; width:28px; display:grid; place-items:center; cursor:pointer; }
.doc-pick input{ width:18px; height:18px; cursor:pointer; }

/* ---------- Upload ------------------------------------------------------- */
/* Процент оплаты: ползунок и число рядом — одно значение, два способа. */
/* Шире, чем кажется нужным: «100» и знак «%» должны поместиться целиком,
   а у числового поля ещё и стрелки. */
.percent-field{ width:120px; flex:none; }
.percent-field input{ width:100%; text-align:right; padding-right:34px; }
/* Рядом с «обычным» — текст из ТЗ про вторник и четверг: на виду, но тише
   самого выбора. */
.urgency-note{ margin-top:6px; }
/* Окно «Проверьте документ перед отправкой»: всё, что заполнено, списком. */
.check-list{ max-height:55vh; overflow:auto; margin:10px 0 4px; }
.check-list dd{ white-space:pre-wrap; word-break:break-word; }
.upload-form{ max-width:760px; }
.dropzone{
  display:grid; place-items:center; gap:6px; padding:44px 24px; cursor:pointer;
  border:2px dashed var(--line); border-radius:var(--radius-lg);
  background:var(--input-bg); text-align:center;
  transition: border-color var(--transition), background var(--transition),
              transform 220ms var(--spring);
}
.dropzone:hover, .dropzone.is-over{
  border-color:var(--accent-1); background:var(--accent-tint);
}
.dropzone.is-over{ transform:scale(1.01); }
.dropzone.has-file{ border-style:solid; border-color:var(--success); }
.dropzone-ico{
  width:46px; height:46px; display:grid; place-items:center; border-radius:var(--radius-md);
  font-size:21px; color:#fff;
  background:linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  box-shadow:var(--shadow-accent);
}
.dropzone-text{ font-weight:650; }
.dropzone-hint{ font-size:12.5px; color:var(--text-faint); }

/* Запрет на личные документы: сплошной красный, а не подсказка — его должны
   заметить до того, как выберут файл. Заливка темнее --danger, чтобы белый
   текст держал 4.5:1; одна и та же в светлой и тёмной теме. */
.pii-ban{
  display:flex; align-items:flex-start; gap:14px;
  margin-bottom:16px; padding:16px 20px; border-radius:var(--radius-xl);
  color:#fff; background:linear-gradient(145deg, #D42C32, #A51D23);
  box-shadow:var(--shadow-soft), 0 12px 28px -12px rgba(197,32,38,.6);
}
.pii-ban-ico{
  flex:none; width:32px; height:32px; display:grid; place-items:center;
  border-radius:50%; background:#fff; color:#B4232A;
  font-size:19px; font-weight:800; line-height:1;
}
/* Цвет задан явно: общий p{} красит абзацы в --text-muted, и белый от
   .pii-ban до них не доходит. */
.pii-ban-title{ margin:4px 0 4px; font-family:var(--font-display); font-size:17px; font-weight:800; color:#fff; }
.pii-ban-text{ margin:0; font-size:14px; line-height:1.5; font-weight:500; color:#fff; }
/* То же коротко — прямо под полем файла, где его выбирают. */
.pii-ban-line{
  margin:10px 0 0; padding:8px 12px; border-radius:var(--radius-sm);
  border-left:3px solid var(--danger); background:var(--tint-danger);
  font-size:13.5px; font-weight:700; color:#B8232A;
}
[data-theme="dark"] .pii-ban-line{ color:#FF7B7F; }

/* The URGENT control: a switch that looks like the button the specification
   asks for, and turns red the moment it is on. */
.urgent-switch{ display:block; cursor:pointer; margin-top:4px; }
.urgent-switch input{ position:absolute; opacity:0; pointer-events:none; }
.urgent-face{
  display:flex; align-items:center; gap:14px; padding:14px 18px;
  border:1px solid var(--line); border-radius:var(--radius-md);
  background:var(--input-bg);
  transition: background var(--transition), border-color var(--transition),
              transform 200ms var(--spring);
}
.urgent-switch:active .urgent-face{ transform:scale(.99); }
.urgent-switch input:checked + .urgent-face{
  background:linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  border-color:transparent; color:#fff; box-shadow:var(--shadow-accent);
}
.urgent-switch input:checked + .urgent-face small{ color:rgba(255,255,255,.85); }
.urgent-switch input:focus-visible + .urgent-face{ box-shadow:0 0 0 4px var(--accent-tint); }
.urgent-bolt{ font-size:22px; }
.urgent-body{ display:grid; }
.urgent-body strong{ letter-spacing:.06em; font-size:14px; }
.urgent-body small{ font-size:12.5px; color:var(--text-faint); }
.form-foot{
  display:flex; align-items:center; justify-content:space-between;
  gap:16px; flex-wrap:wrap; margin-top:4px;
}
.foot-note{ margin:0; font-size:13px; max-width:46ch; }

/* ---------- Review layout ------------------------------------------------ */
.review{ display:grid; gap:16px; grid-template-columns:minmax(0, 1.05fr) minmax(0, .95fr); }
.review-doc{ padding:14px; position:sticky; top:74px; height:calc(100vh - 110px); display:flex; flex-direction:column; }
.review-doc-head{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:4px 6px 12px;
}
.review-doc-head strong{ display:block; font-size:14.5px; }
.review-doc-head small{ font-size:12px; color:var(--text-faint); }
.pdf-frame{
  flex:1; width:100%; border:0; border-radius:var(--radius-md);
  background:var(--surface-solid);
}
/* Наблюдатель: на месте PDF — те же страницы картинками, что на экране
   просмотра (admin/review.html), со своей прокруткой внутри карточки. */
.pdf-pages{
  flex:1; min-height:0; overflow:auto; display:flex; flex-direction:column;
  align-items:center; gap:12px; padding:10px;
  border-radius:var(--radius-md); background:var(--surface-solid);
}
.review-side{ min-width:0; }

.fact-row{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:14px; }
.facts{ display:grid; grid-template-columns:auto 1fr; gap:6px 16px; margin:0; }
.facts dt{ font-size:12.5px; color:var(--text-faint); }
.facts dd{ margin:0; font-size:13.5px; }
/* «К оплате» в карточке документа — первым и крупно; сумма счёта, если
   платят не всё, — мелкой строкой под ней (macros.amount_facts). */
.facts dd .money-lead{
  display:block; font-size:22px; font-weight:700; line-height:1.15;
  letter-spacing:-.015em; font-variant-numeric:tabular-nums lining-nums;
}
.facts dd .money-sub{
  display:block; margin-top:3px; font-size:12.5px; color:var(--text-muted);
  font-variant-numeric:tabular-nums;
}
.quote{
  margin:4px 0 0; padding:8px 12px; font-size:13px;
  border-left:3px solid var(--line); background:var(--surface-strong);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0; color:var(--text-muted);
}

/* ---------- AI analysis block -------------------------------------------- */
.ai-card{ border-color:color-mix(in srgb, var(--accent-1) 22%, var(--border)); }
.ai-summary{ font-size:14.5px; color:var(--text); margin-bottom:12px; }
.ai-note{ font-size:13px; margin:6px 0; }
.ai-disclaimer{
  font-size:12px; color:var(--text-faint); margin:10px 0 0;
  padding:9px 12px; border-radius:var(--radius-sm); background:var(--surface-strong);
}
.risk{
  padding:4px 11px; border-radius:var(--radius-xs);
  font-size:11.5px; font-weight:700;
}
.risk-low{ background:var(--tint-success); color:var(--success); }
.risk-medium{ background:var(--tint-warn); color:var(--warn); }
.risk-high{ background:var(--tint-danger); color:var(--danger); }
.risk-list{ margin-top:14px; font-size:13px; }
.risk-list ul{ margin:6px 0 0; padding-left:18px; color:var(--text-muted); }
.risk-list li{ margin-bottom:4px; }

/* ---------- Recognised fields -------------------------------------------- */
.fields{ display:grid; gap:1px; background:var(--line); border-radius:var(--radius-md); overflow:hidden; }
.field-row{
  display:grid; grid-template-columns:150px 1fr auto; align-items:center; gap:10px;
  padding:10px 14px; background:var(--surface-solid);
}
.field-row.is-weak{ background:color-mix(in srgb, var(--warn) 7%, var(--surface-solid)); }
.field-key{ font-size:12.5px; color:var(--text-faint); }
.field-value{ font-size:14px; display:flex; align-items:center; gap:7px; min-width:0; }
.field-value > span:first-child{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.tag{
  width:18px; height:18px; flex:none; display:grid; place-items:center;
  border-radius:50%; font-size:10px; font-weight:800;
}
.tag-ok{ background:var(--tint-success); color:var(--success); }
.tag-warn{ background:var(--tint-warn); color:var(--warn); }
/* The edit form replaces the value in place; it is hidden until asked for, so
   a screen of read-only facts does not look like a screen of inputs. */
.field-edit{ display:none; grid-column:1 / -1; gap:8px; }
.field-row.is-editing .field-edit{ display:flex; }
.field-row.is-editing .field-value{ opacity:.45; }
.field-input{ flex:1; padding:8px 12px; border-radius:var(--radius-sm); }
.field-toggle{ padding:4px 10px; }

/* ---------- Stage track --------------------------------------------------- */
.stage-track{ display:grid; gap:8px; margin-bottom:16px; }
.stage-pill{
  display:flex; align-items:flex-start; gap:12px; padding:11px 14px;
  border-radius:var(--radius-md); border:1px solid var(--line);
  background:var(--surface-strong);
}
.stage-num{
  width:26px; height:26px; flex:none; display:grid; place-items:center;
  border-radius:50%; font-size:12px; font-weight:800;
  background:var(--surface-solid); color:var(--text-faint);
}
.stage-body{ display:grid; gap:1px; min-width:0; }
.stage-body strong{ font-size:13.5px; }
.stage-body small{ font-size:12px; color:var(--text-muted); }
.stage-who{ color:var(--text-faint) !important; }
.stage-pill.is-confirmed{ border-color:color-mix(in srgb, var(--success) 40%, transparent); }
.stage-pill.is-confirmed .stage-num{ background:var(--success); color:#fff; }
.stage-pill.is-waiting{ border-color:color-mix(in srgb, var(--accent-1) 45%, transparent); }
.stage-pill.is-waiting .stage-num{ background:var(--accent-1); color:#fff; }
.stage-pill.is-rejected{ border-color:color-mix(in srgb, var(--danger) 40%, transparent); }
.stage-pill.is-rejected .stage-num{ background:var(--danger); color:#fff; }
.stage-pill.is-review .stage-num{ background:var(--warn); color:#fff; }
.stage-pill.is-blocked{ opacity:.6; }
/* Не нужен по категории: тише, чем «ещё не дошло», и пунктиром — этого этапа
   у документа нет, а не «пока нет». */
.stage-pill.is-skipped{ opacity:.45; border-style:dashed; background:transparent; }

/* ---------- Timeline ------------------------------------------------------ */
.timeline{ list-style:none; margin:0; padding:0 0 0 18px; position:relative; }
.timeline::before{
  content:''; position:absolute; left:4px; top:6px; bottom:6px;
  width:2px; background:var(--line); border-radius:2px;
}
.timeline-item{ position:relative; padding:0 0 14px 6px; }
.timeline-item:last-child{ padding-bottom:0; }
.timeline-dot{
  position:absolute; left:-18px; top:5px; width:10px; height:10px;
  border-radius:50%; background:var(--text-faint);
  box-shadow:0 0 0 3px var(--bg);
}
.timeline-item.is-confirmed .timeline-dot{ background:var(--success); }
.timeline-item.is-rejected .timeline-dot{ background:var(--danger); }
.timeline-item.is-sent_to_review .timeline-dot{ background:var(--warn); }
.timeline-item.is-confirm_cancelled .timeline-dot{ background:var(--warn); }
.timeline-item.is-uploaded .timeline-dot{ background:var(--accent-1); }
.timeline-body strong{ font-size:13.5px; margin-right:6px; }
.timeline-body small{ display:block; font-size:12px; color:var(--text-faint); }
.timeline-compact .timeline-item{ padding-bottom:10px; }
/* Номер документа в ленте на главной: по нему понятно, о каком счёте строка. */
.timeline-doc{ font-weight:650; font-variant-numeric:tabular-nums; color:var(--accent-1); }
.timeline-note{ display:block; font-size:12px; color:var(--text-muted); margin-top:2px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; }
.timeline-item.is-reassigned .timeline-dot, .timeline-item.is-signer_added .timeline-dot{
  background:var(--text-faint); }

/* ---------- Decision ------------------------------------------------------ */
.decide{ border-color:color-mix(in srgb, var(--accent-1) 30%, var(--border)); }
.decide-actions{ display:flex; flex-wrap:wrap; gap:10px; }
/* Перенесено на завтра: пометка и «Отменить перенос» над кнопками решения. */
.postponed-note{ display:flex; align-items:center; flex-wrap:wrap; gap:10px; margin:0 0 12px; }
.btn-lg{ padding:15px 28px; font-size:15px; letter-spacing:.02em; }
.btn-danger{ background:var(--tint-danger); color:var(--danger); border-color:transparent; }
.btn-danger:hover{ background:var(--danger); color:#fff; }
.btn-warn{ background:var(--tint-warn); color:var(--warn); border-color:transparent; }
.btn-warn:hover{ background:var(--warn); color:#fff; }
.btn-pin{ background:var(--surface-strong); border-color:var(--accent-1); color:var(--accent-1); }
.btn-pin:hover{ background:var(--accent-tint); }

/* ---------- Modal --------------------------------------------------------- */
.modal{
  width:min(440px, calc(100vw - 32px)); padding:26px 28px; border:1px solid var(--border);
  border-radius:var(--radius-xl); color:var(--text); background:var(--surface-strong);
  box-shadow:var(--shadow-lift);
  backdrop-filter: blur(30px) saturate(180%);
  -webkit-backdrop-filter: blur(30px) saturate(180%);
}
/* Окно — по центру экрана и не выше его. .glass ставит position:relative, а
   открытому модальному окну нужен fixed из стиля браузера: без этой строки
   окна вставали у верхнего края, а высокое («Проверьте документ перед
   отправкой») уходило заголовком за экран. Длинное — прокручивается внутри. */
dialog.modal{
  position:fixed; inset:0; margin:auto;
  max-height:calc(100dvh - 32px); overflow:auto;
}
.modal::backdrop{ background:rgba(0,0,0,.45); backdrop-filter:blur(4px); }
.modal[open]{ animation: modal-in 380ms var(--spring) both; }
@keyframes modal-in{
  from{ opacity:0; transform:translateY(18px) scale(.94); }
  to{ opacity:1; transform:none; }
}
.modal h3{ margin-bottom:6px; }
.modal-actions{ display:flex; gap:10px; justify-content:flex-end; margin-top:18px; }
/* The PIN reads as a code, not as a word: spaced digits in the mono face. */
.pin-input{ font-family:var(--font-mono); letter-spacing:.42em; font-size:17px; }

/* ---------- Filters ------------------------------------------------------- */
.filters{ padding:16px 18px; margin-bottom:16px; }
.filter-search{ display:flex; gap:10px; margin-bottom:12px; }
.filter-search input{ flex:1; }
.chip-row{ display:flex; flex-wrap:wrap; gap:7px; }
.chip-btn{
  font:inherit; font-size:12.5px; font-weight:600; cursor:pointer;
  padding:6px 14px; border-radius:var(--radius-xs);
  border:1px solid var(--line); background:transparent; color:var(--text-muted);
  transition: background var(--transition), color var(--transition),
              border-color var(--transition), transform 180ms var(--spring);
}
.chip-btn:hover{ background:var(--surface-strong); color:var(--text); }
.chip-btn:active{ transform:scale(.95); }
/* Два чипа про деньги: жёлтый — ждёт оплаты, зелёный — оплачено. Цвет здесь
   несёт смысл, а не украшает: в списке из сорока строк это первое, что ищут
   глазами. Активный чип красится общим правилом ниже, поэтому эти два стоят
   перед ним. */
.chip-warn{ color:var(--warn); background:var(--tint-warn); border-color:transparent; }
.chip-warn:hover{ background:var(--tint-warn); color:var(--warn); }
.chip-ok{ color:var(--success); background:var(--tint-success); border-color:transparent; }
.chip-ok:hover{ background:var(--tint-success); color:var(--success); }

.chip-btn.is-active{
  background:linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  border-color:transparent; color:#fff;
}
.filter-more{ margin-top:14px; }
.filter-more summary{
  cursor:pointer; font-size:13px; font-weight:650; color:var(--text-muted);
  padding:6px 0;
}
.filter-grid{
  display:grid; gap:12px; margin-top:12px;
  grid-template-columns:repeat(auto-fit, minmax(170px, 1fr));
}
.filter-grid .field{ margin-bottom:0; }
.filter-foot{ display:flex; justify-content:flex-end; gap:10px; margin-top:14px; }

/* ---------- Category bars ------------------------------------------------- */
.cat-bars{ display:grid; gap:10px; }
.cat-bar{ display:grid; grid-template-columns:1fr 2fr auto; align-items:center; gap:12px; }
.cat-name{ font-size:13.5px; }
.cat-name small{ color:var(--text-faint); }
.cat-track{ height:8px; border-radius:4px; background:var(--surface-strong); overflow:hidden; }
.cat-fill{
  display:block; height:100%; width:var(--w, 0%); border-radius:4px;
  background:var(--chip, var(--accent-1));
  transition: width 700ms var(--ease-ios);
}
.cat-count{ font-variant-numeric:tabular-nums; font-size:13px; color:var(--text-muted); }
.cat-cards{ display:grid; gap:14px; grid-template-columns:repeat(auto-fit, minmax(320px, 1fr)); }
.cat-card{ margin:0; }
.cat-dot{
  display:inline-block; width:10px; height:10px; border-radius:50%;
  background:var(--chip); margin-right:8px;
}
.add-form summary{ cursor:pointer; font-weight:650; }
.add-form[open] summary{ margin-bottom:16px; }
.cell-input{ padding:7px 11px; border-radius:var(--radius-sm); font-size:13px; }
/* Подпись под полем в строке таблицы: почта, устройство. Своей строкой, иначе
   она тянет колонку в ширину и сжимает поля соседних. */
.cell-sub{ display:block; margin-top:3px; font-size:12px; line-height:1.35; }
.row-denied{ background:color-mix(in srgb, var(--danger) 8%, transparent); }
.nav-count{
  margin-left:auto; padding:1px 8px; border-radius:var(--radius-xs);
  font-size:11px; font-weight:700; background:var(--accent-1); color:#fff;
}

/* ---------- Mobile -------------------------------------------------------- */
@media (max-width: 1100px){
  .review{ grid-template-columns:1fr; }
  .review-doc{ position:static; height:auto; }
  .pdf-frame{ height:62vh; }
  .pdf-pages{ flex:none; height:62vh; }
}
@media (max-width: 860px){
  .field-row{ grid-template-columns:1fr; gap:4px; }
  .doc-row{ flex-direction:column; align-items:flex-start; gap:10px; }
  .doc-side{ justify-items:start; text-align:left; flex-direction:row; display:flex; gap:10px; }
}


/* ---------- Type: the display face on the things that carry weight -------- */
.stat-value, .count-value, .doc-amount, .error-code, .brand-text strong{
  font-family: var(--font-display);
  /* Lining figures of one width, so a column of money does not shuffle as the
     numbers change. */
  font-variant-numeric: tabular-nums lining-nums;
}
.stat-value, .count-value{ letter-spacing:-.04em; }
/* Inter's default comma sits low next to a digit; the contextual set fixes the
   spacing in "2 450 000,00" without touching anything else. */
body{ font-feature-settings:'cv05' 1, 'cv11' 1, 'ss03' 1; }

/* ==========================================================================
   Refinements

   Last in the file on purpose: everything here sharpens what is defined above,
   and the media query at the end deliberately overrides it. Anything that has
   to win has to come last — that is the only ordering rule this sheet has.
   ========================================================================== */

::selection{ background: var(--accent-1); color:#fff; }

/* A heading breaks where the lines come out even, rather than dropping one
   orphan word onto the last line. Browsers without it just wrap as before. */
h1, h2, h3{ text-wrap: balance; }
p, .sub, .lead, .role-hint, .stat-hint{ text-wrap: pretty; }

/* One ring for anything keyboard-reachable that has not drawn its own. */
:focus-visible{ outline:2px solid var(--accent-1); outline-offset:2px; }

/* Without this a long queue gets a slab of system grey down its side, which is
   the one part of the page the design does not reach. */
*{ scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
::-webkit-scrollbar{ width:11px; height:11px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{
  background: var(--line); border-radius:11px;
  border:3px solid transparent; background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover{ background: var(--text-faint); background-clip: content-box; }

/* The buttons that sit beside a page title. */
.page-actions{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }

/* A tile lifts toward the light: an accent edge arrives along the top rather
   than the whole card changing colour under the pointer. */
/* No `overflow:hidden` here: the strip is already inset from both corners, and
   clipping a card would quietly kill any `position:sticky` placed inside one. */
.stat, .card{ position:relative; }
.stat::before, .card::before{
  content:''; position:absolute; left:16px; right:16px; top:0; height:2px;
  border-radius:0 0 2px 2px;
  background: linear-gradient(90deg, transparent, var(--accent-1-light), transparent);
  opacity:0; transition: opacity 320ms var(--ease-ios);
}
.stat:hover::before, .card:hover::before{ opacity:.9; }

/* A wide table scrolls sideways on a narrow screen; give it momentum and keep
   the columns from being crushed into unreadable slivers. */
.table-wrap{
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  border:1px solid var(--border);
  box-shadow: var(--shadow-soft);
}
.table-wrap table{ min-width: 560px; }

/* ---------- Touch and small screens -------------------------------------- */
@media (max-width: 860px){
  /* Safari zooms the whole page in when it focuses an input under 16px, and
     never zooms back out. This is the fix, not a preference. */
  input[type=text], input[type=email], input[type=password], input[type=number],
  input[type=date], input[type=search], input[type=tel], select, textarea{
    font-size:16px;
  }

  /* Панель не уходит под домашнюю полоску iPhone. Колонок по-прежнему
     четыре: сколько бы разделов ни было у роли, в панель попадают три и
     «Ещё». */
  .nav{ bottom: calc(12px + env(safe-area-inset-bottom)); }
  .shell{ padding-bottom: calc(100px + env(safe-area-inset-bottom)); }
  .floating-controls{ top: calc(12px + env(safe-area-inset-top)); }

  /* Roughly the smallest target a thumb hits reliably. */
  /* min-width здесь больше не нужен: колонок ровно четыре и они равные, а
     заданная ширина мешала бы им сжиматься на узком экране. */
  .nav-item{ min-height:52px; justify-content:center; }
  .btn{ min-height:46px; }
  .btn-sm{ min-height:38px; }
  .lang-current{ height:44px; }
  .theme-float{ width:44px; height:44px; }
  .theme-toggle{ width:40px; height:40px; }
  .role-card{ padding:13px 14px; }

  .auth-wrap{ padding:16px; }
  .auth-card{ padding:30px 22px; border-radius: var(--radius-lg); }
  .content{ padding:4px 2px 40px; }
  .page-head{ padding:8px 10px; }
  th, td{ padding:12px 14px; }
}

@media (max-width: 560px){
  h1{ font-size:23px; }
  .page-head.is-stuck h1{ font-size:18px; }
  /* Two narrow tiles read better than one wide one on a phone. */
  .stat-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap:10px; }
  .stat{ padding:15px 16px; }
  .stat-value{ font-size:21px; }
  .stat-label{ font-size:11.5px; }
  .empty{ padding:38px 22px; }
}



/* На телефоне очередь листают, а не читают: в строке остаются имя и сумма,
   статус — точкой, всё остальное открывается нажатием. Четыре яруса на
   документ (номер со статусом, имя, реквизиты, сумма с категорией) помещали
   на экран три документа — очередь из тридцати превращалась в прокрутку. */
@media (max-width: 560px){
  .doc-list{ gap:7px; }
  .doc-row{
    flex-direction:row; align-items:center; gap:12px; padding:11px 14px;
  }
  /* Номер, бейджи, реквизиты и категория — в карточке документа. В строке
     остаётся то, по чему её узнают: имя, компания, сумма. */
  /* Служебный ярус и метки — в карточке документа: в строке остаётся то, по
     чему её узнают, — компания и сумма. */
  .doc-row .doc-meta,
  .doc-row .doc-marks{ display:none; }
  .doc-row .doc-company{ font-size:14.5px; }
  /* min-width:0 обязателен, иначе длинное имя не даёт себя обрезать и
     выдавливает сумму за край строки. */
  .doc-main{ min-width:0; flex:1; }
  .doc-side{ display:block; flex:none; text-align:right; }
  .doc-dot{ display:inline-block; }
}

/* ---------- Print ---------------------------------------------------------
   A finance panel gets printed: a queue taken into a meeting, a document
   attached to a file. On paper the glass, the navigation and the controls are
   noise, and a table that scrolls sideways on screen has to fit the sheet. */
@media print{
  @page{ margin: 14mm; }

  .field-bg, .sidebar, .nav, .floating-controls, .flash-stack,
  .page-actions, .lang-menu, .theme-toggle, .theme-float{ display:none !important; }

  body{ background:#fff; color:#000; font-size:11pt; }
  .shell{ display:block; padding:0; min-height:0; }
  .content{ padding:0; }
  .content > *, .content-main > *{ animation:none !important; }

  /* Paper greys, not theme colours: these follow the sheet, not the screen. */
  .glass, .card, .stat, .auth-card{
    background:#fff !important; border:1px solid #ccc !important;
    box-shadow:none !important; backdrop-filter:none !important;
  }
  .glass::after, .stat::before, .card::before{ display:none; }

  .page-head{ position:static; padding:0; margin-bottom:10mm; }
  h1{ font-size:18pt; }
  a{ color:#000; text-decoration:none; }

  .table-wrap{ overflow:visible; border:0; box-shadow:none; }
  .table-wrap table{ min-width:0; }
  th{ background:#f2f2f2 !important; color:#000; }
  th, td{ padding:6pt 8pt; }
  /* Nothing should be cut in half by a page break. */
  tr, .card, .stat, .doc-row{ break-inside: avoid; }
  thead{ display: table-header-group; }
}

/* ==========================================================================
   Approval sheet — a page that exists to be printed
   ========================================================================== */

.sheet-wrap{ max-width:900px; margin:0 auto; padding:24px 20px 60px; }
.sheet-actions{ display:flex; justify-content:flex-end; gap:10px; margin-bottom:16px; }
.sheet{
  padding:40px 44px; border-radius:var(--radius-lg);
  background:var(--surface-solid); border:1px solid var(--line);
  box-shadow:var(--shadow-soft);
}
.sheet-head{
  display:flex; align-items:flex-start; justify-content:space-between;
  gap:24px; padding-bottom:20px; margin-bottom:24px;
  border-bottom:2px solid var(--accent-1);
}
.sheet-brand{ display:flex; align-items:center; gap:11px; }
.sheet-title{ text-align:right; }
.sheet-title h1{ font-size:19px; margin:0 0 4px; }
.sheet-number{
  margin:0; font-family:var(--font-mono); font-size:15px; font-weight:700;
  color:var(--accent-1);
}
.sheet-block{ margin-bottom:26px; }
.sheet-block h2{ font-size:14px; margin-bottom:10px; }
.sheet-table{ width:100%; border-collapse:collapse; background:transparent; }
.sheet-table th, .sheet-table td{
  padding:8px 0; text-align:left; vertical-align:top;
  border-bottom:1px solid var(--line); font-size:13.5px;
}
.sheet-table > tbody > tr > th, .sheet-table > tr > th{
  width:190px; font-size:12px; font-weight:600; letter-spacing:0;
  text-transform:none; color:var(--text-faint); background:transparent;
}
.sheet-amount{ font-family:var(--font-display); font-size:17px; font-weight:750; }
.sheet-note{ font-size:12.5px; color:var(--text-muted); margin-top:3px; }
.sheet-stages td{ font-size:14px; }
.sheet-result th, .sheet-result td{ border-bottom:0; padding-top:12px; }
.sheet-log thead th{
  font-size:11px; color:var(--text-faint); background:transparent;
  letter-spacing:.04em; text-transform:uppercase;
}
.sheet-log td{ font-size:12.5px; padding:6px 10px 6px 0; }
.sheet-foot{
  margin-top:28px; padding-top:14px; border-top:1px solid var(--line);
  font-size:11.5px; color:var(--text-faint);
}

/* On paper the page is the sheet: no chrome, no shadow, black on white, and
   a history that is allowed to break across sheets rather than be clipped. */
@media print{
  .sheet-wrap{ max-width:none; margin:0; padding:0; }
  .sheet-actions{ display:none !important; }
  .sheet{
    padding:0; border:0; border-radius:0; box-shadow:none !important;
    background:#fff !important; color:#000 !important;
  }
  .sheet-head{ border-bottom:2px solid #000; }
  .sheet-number, .sheet-brand .brand-text small{ color:#000 !important; }
  /* Printers drop backgrounds, and white letters on nothing vanish: on paper
     the tile is drawn as an outline instead. */
  .sheet-brand .brand-mark{
    background:none !important; box-shadow:none !important;
    border:2px solid #000; color:#000 !important;
  }
  .sheet-brand .brand-mark::after{ background:#000 !important; }
  .sheet-table th, .sheet-table td{ border-color:#ccc !important; color:#000 !important; }
  .sheet-block{ break-inside:avoid; }
  .sheet-log tr{ break-inside:avoid; }
}

/* ---------- Two-step confirmation ----------------------------------------
   One button opens a form with two panes. `hidden` does the switching, so the
   dialog works even if the script never loads — the second pane is simply
   visible below the first instead of after it. */
[hidden]{ display:none !important; }
.confirm-doc{
  font-family: var(--font-display); font-size:17px; font-weight:700;
  color:var(--text); font-variant-numeric: tabular-nums lining-nums;
  margin-bottom:8px;
}
.pin-why{ font-size:12.5px; line-height:1.45; margin-top:-4px; }

/* ---------- Data export --------------------------------------------------- */
.narrow-wide{ max-width:720px; }
.backup-actions{ display:flex; flex-wrap:wrap; gap:12px; margin:22px 0 6px; }
.backup-actions .btn{ flex:1; min-width:240px; }

/* ---------- Хранилище сервера (settings.html) -------------------------------
   Полоса занятого места на диске VPS. Жёлтой она становится, только когда
   места мало (storage.card → low), иначе это просто справка. */
.storage-meter{
  height:10px; border-radius:999px; overflow:hidden;
  background: var(--surface-strong); border:1px solid var(--border);
}
.storage-meter > span{
  display:block; height:100%; min-width:4px; border-radius:inherit;
  background: linear-gradient(90deg, var(--accent-fill-a), var(--accent-fill-b));
}
.storage-meter.is-low > span{ background: var(--warn); }
.storage-used{ margin:8px 0 16px; font-size:13px; color:var(--text-muted); }

/* ---------- Passkeys ------------------------------------------------------
   A registered device is a row, not a chip: it carries a name, when it was
   last used, and a way to remove it. */
.passkey-list{ list-style:none; margin:0 0 4px; padding:0; display:grid; gap:8px; }
.passkey-item{
  display:flex; align-items:center; gap:12px; padding:11px 14px;
  border:1px solid var(--border); border-radius: var(--radius-md);
  background: var(--input-bg); box-shadow: inset 0 1px 0 var(--sheen-soft);
}
.passkey-ico{
  width:34px; height:34px; flex:none; display:grid; place-items:center;
  border-radius:var(--radius-sm); font-size:15px;
  background: var(--accent-tint); color: var(--accent-1);
}
.passkey-text{ display:grid; min-width:0; flex:1; }
.passkey-text strong{ font-size:14px; font-weight:650; }
.passkey-text small{ font-size:12px; color:var(--text-faint); }
.passkey-item form{ margin:0; }

/* The device button leads, so it is the filled one; the PIN below it is the
   fallback and is styled as an ordinary field. */
.btn-passkey{ font-size:15.5px; }
.or-line{
  display:flex; align-items:center; gap:10px;
  margin:14px 0 12px; font-size:12.5px; color:var(--text-faint);
}
.or-line::before, .or-line::after{
  content:''; flex:1; height:1px; background: var(--line);
}

/* ---------- Money in several currencies -----------------------------------
   A total is a stack, not a number: one line per currency, because adding
   tenge to dollars would produce a figure nobody can act on. */
.money-stack{ display:grid; gap:1px; }
.money-line{ display:block; font-variant-numeric: tabular-nums lining-nums; }
/* Inside a stat tile the first line leads and the rest follow a step smaller,
   so four currencies still read as one answer rather than four headlines. */
.stat-value .money-line{ font-size:inherit; }
.stat-value .money-line ~ .money-line{ font-size:.72em; color:var(--text-muted); }
.stat-hint .money-stack{ display:inline-grid; vertical-align:bottom; }

/* ---------- «Копировать» в «Моих документах» (documents/list.html) ----------
   Кнопка рядом со строкой: строка — ссылка на счёт, вложить в неё нельзя.
   На телефоне — одна иконка, чтобы строке осталась ширина. */
.doc-row-copy{ display:grid; grid-template-columns:minmax(0, 1fr) auto; gap:8px; align-items:center; }
.doc-copy{ display:inline-flex; align-items:center; gap:7px; white-space:nowrap; }
.doc-copy svg{ width:16px; height:16px; flex:none; }
@media (max-width: 560px){
  .doc-copy{ padding:9px 10px; }
  .doc-copy span{ display:none; }
}

/* ---------- Подтверждено и оплачено (admin/dashboard.html) -------------------
   Три плитки с крупными суммами наверху главной. Цвет у плитки — смысл, как у
   чипов очереди: синий — подтверждено, зелёный — деньги ушли, жёлтый — ещё
   ждут. Он же заливает угол плитки — мягко, чтобы цифра оставалась главной. */
.money-board{ margin-bottom:20px; }
.money-head{
  display:flex; align-items:center; justify-content:space-between; gap:10px 16px;
  flex-wrap:wrap; margin-bottom:12px;
}
.money-title{ margin:0; font-size:17px; font-weight:700; letter-spacing:-.015em; }
.period-switch{
  display:inline-flex; gap:2px; padding:3px; border-radius:var(--radius-md);
  background:var(--surface-strong); border:1px solid var(--border);
}
.period-btn{
  padding:6px 13px; border-radius:var(--radius-sm); white-space:nowrap;
  font-size:13px; font-weight:600; color:var(--text-muted);
  transition: background var(--transition), color var(--transition), box-shadow var(--transition);
}
.period-btn:hover{ color:var(--text); }
.period-btn.is-active{
  color:#fff;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  box-shadow: var(--shadow-accent), inset 0 1px 0 rgba(255,255,255,.22);
}

.money-grid{ display:grid; gap:14px; grid-template-columns:repeat(3, minmax(0, 1fr)); }
/* Плитки периода стоят в сетке сами, обёртка только прячет чужие периоды. */
.money-period{ display:contents; }
.money-tile{
  --tone: var(--accent-1);
  --tone-tint: var(--accent-tint);
  display:flex; flex-direction:column; gap:3px; min-width:0;
  padding:20px 22px 18px; color:var(--text);
  background: radial-gradient(130% 100% at 100% 0%, var(--tone-tint), transparent 58%), var(--surface);
  /* Размер цифры — от ширины самой плитки (cqi): миллиард в узкой колонке
     уменьшается, а не вылезает за край и не рвётся посередине числа. */
  container-type: inline-size;
  transition: transform 200ms var(--ease-ios), box-shadow var(--transition);
  animation: money-in 380ms var(--ease-ios) backwards;
}
.money-tile.is-paid{ --tone: var(--success); --tone-tint: var(--tint-success); }
.money-tile.is-unpaid{ --tone: var(--warn); --tone-tint: var(--tint-warn); }
.money-period > .money-tile + .money-tile{ animation-delay:60ms; }
.money-tile:hover{ transform:translateY(-3px); box-shadow: var(--shadow-lift), inset 0 1px 0 var(--sheen); }
.money-tile:active{ transform:scale(.985); }
@keyframes money-in{ from{ opacity:0; transform:translateY(8px); } }

.money-label{
  display:flex; align-items:center; gap:9px; margin-bottom:8px;
  font-size:13px; font-weight:650; color:var(--text-muted);
}
.money-dot{
  width:8px; height:8px; flex:none; border-radius:50%;
  background:var(--tone); box-shadow:0 0 0 4px var(--tone-tint);
}
.money-value{
  display:grid; gap:2px; font-family:var(--font-display);
  font-variant-numeric: tabular-nums lining-nums;
}
.money-value .money-line{
  font-size:28px; font-size:clamp(19px, 9cqi, 34px);
  font-weight:780; letter-spacing:-.04em; line-height:1.08; white-space:nowrap;
}
.money-value .money-line ~ .money-line{
  font-size:18px; font-size:clamp(14px, 5.5cqi, 20px); font-weight:700; color:var(--text-muted);
}
.money-cents{ font-size:.56em; font-weight:650; letter-spacing:-.01em; color:var(--text-faint); }
.money-symbol{ font-size:.62em; font-weight:700; color:var(--text-muted); }
.money-meta{ margin-top:8px; font-size:13px; font-weight:650; color:var(--text); }
.money-hint{ font-size:12.5px; color:var(--text-faint); }
/* Доля оплаченных счетов — только за всё время (workflow.money_overview). */
.money-bar{
  display:block; height:6px; margin:8px 0 3px; border-radius:999px; overflow:hidden;
  background:var(--surface-strong); border:1px solid var(--border);
}
.money-bar > span{ display:block; height:100%; border-radius:inherit; background:var(--tone); }

@media (max-width: 860px){
  .money-grid{ grid-template-columns:1fr; gap:12px; }
}
@media (max-width: 560px){
  .period-switch{ display:flex; width:100%; }
  .period-btn{ flex:1; text-align:center; padding:7px 6px; }
}
@media (prefers-reduced-motion: reduce){
  .money-tile{ animation:none; transition:none; }
  .money-tile:hover, .money-tile:active{ transform:none; }
}

/* ---------- Курсы валют (admin/dashboard.html, static/js/fx.js) -------------
   Окошки TradingView. Уже 280 px виджет прячет изменение за день, поэтому
   ширину плитки задаёт он: четыре в ряд — только на широком экране, на
   ноутбуке два на два, на телефоне лента, которую листают пальцем. Решает
   ширина самого блока, а не экрана: меню сбоку отнимает своё. */
.fx-board{ margin-bottom:20px; container-type:inline-size; }
.fx-source{ font-size:12.5px; color:var(--text-faint); }
.fx-grid{
  display:grid; gap:12px; grid-auto-flow:column; grid-auto-columns:284px;
  overflow-x:auto; overscroll-behavior-x:contain; scroll-snap-type:x mandatory;
  /* Прокрутка обрезала бы тень плиток снизу — место под неё. */
  padding-bottom:10px; margin-bottom:-10px; scrollbar-width:thin;
}
/* Пальцем ленту листают и так; мышью без полосы до рубля и юаня не добраться. */
@media (pointer: coarse){
  .fx-grid{ scrollbar-width:none; }
  .fx-grid::-webkit-scrollbar{ display:none; }
}
.fx-tile{ height:128px; padding:0; overflow:hidden; scroll-snap-align:start; }
.fx-frame{
  display:block; width:100%; height:100%; border:0;
  /* Документ TradingView схему цветов не объявляет. Не совпади она с нашей
     (у тёмной темы — dark), браузер подложит под окошко непрозрачный белый
     фон, и тёмный виджет окажется на белом. */
  color-scheme:normal;
}
/* Плитка со своей подписью (рубль): строка названия виджета — «USDKZT/USDRUB»
   — срезана, курс и график под ней остаются его. На её месте .fx-label тем же
   шрифтом и цветами, что у соседних плиток. Срез — clip-path, а не заплатка
   с фоном: у стеклянной плитки фон полупрозрачный, и заплатку было бы видно. */
.fx-frame.is-relabelled{ clip-path:inset(46px 0 0 0); }
.fx-label{
  position:absolute; top:9px; left:18px; right:14px; pointer-events:none;
  font-family:-apple-system, BlinkMacSystemFont, "Trebuchet MS", Roboto, Ubuntu, sans-serif;
}
.fx-label b{
  display:block; font-size:14px; line-height:20px; font-weight:700;
  letter-spacing:.2px; color:#131722;
}
.fx-label span{
  display:block; font-size:12.5px; line-height:18px; letter-spacing:.6px;
  text-transform:uppercase; color:#787b86;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
[data-theme="dark"] .fx-label b{ color:#d1d4dc; }
.fx-note{ margin:8px 2px 0; font-size:12px; color:var(--text-faint); }
@container (min-width: 580px){
  .fx-grid{
    grid-auto-flow:row; grid-template-columns:repeat(2, minmax(0, 1fr));
    overflow:visible; padding-bottom:0; margin-bottom:0;
  }
}
@container (min-width: 1172px){
  .fx-grid{ grid-template-columns:repeat(4, minmax(0, 1fr)); }
}

/* ==========================================================================
   Темы

   Две: светлая и тёмная, выбор по освещению. Сами цвета — в токенах в начале
   файла; здесь только карточки выбора на странице настроек.
   ========================================================================== */

/* ---------- Выбор темы в настройках ---------- */
.theme-grid{
  display:grid; gap:12px; grid-template-columns:repeat(auto-fit, minmax(150px, 1fr));
}
.theme-option input{ position:absolute; opacity:0; pointer-events:none; }
.theme-card{
  display:block; cursor:pointer; padding:12px; border-radius:var(--radius-md);
  border:1px solid var(--line); background:var(--surface-strong);
  transition: border-color var(--transition), transform 160ms var(--ease-ios);
}
.theme-card:active{ transform:scale(.98); }
.theme-option input:checked + .theme-card{
  border-color:var(--accent-1); box-shadow:0 0 0 3px var(--accent-tint);
}
/* Каждая тема показывает себя: полоски — фон, панель, текст и акцент именно
   той темы, а не текущей. Выбирать вслепую по названию — не выбирать. */
.theme-swatch{
  display:flex; height:46px; border-radius:var(--radius-sm); overflow:hidden;
  border:1px solid var(--line); margin-bottom:9px;
}
.theme-swatch i{ flex:1; display:block; }
.theme-swatch i:nth-child(3){ flex:.5; }
.theme-name{ font-size:13.5px; font-weight:650; display:block; }
.theme-hint{ font-size:11.5px; color:var(--text-faint); }

/* ==========================================================================
   Поля с числами
   ========================================================================== */

/* Сумма и БИН — это цифры, и читать их надо как цифры: моноширинные по
   ширине знака, чтобы разряды стояли столбиком, и крупнее обычного поля,
   потому что ошибка в одной цифре здесь стоит дороже опечатки в названии. */
.num-field{ position:relative; }
.num-field input{
  font-family: var(--font-display);
  font-size: 17px; font-weight: 650; letter-spacing: .02em;
  font-variant-numeric: tabular-nums lining-nums;
  padding-right: 54px;
}
.num-suffix{
  position:absolute; right:16px; top:50%; transform:translateY(-50%);
  font-size:12.5px; font-weight:700; color:var(--text-faint);
  pointer-events:none; font-variant-numeric: tabular-nums;
}
.num-field input:focus + .num-suffix{ color:var(--accent-1); }
/* Счётчик цифр у БИН: 12 — не «примерно двенадцать». */
.num-suffix.is-full{ color:var(--success); }

/* --------------------------------------------------------------------------
   Предоплата: ползунок и цифра рядом с ним
   -------------------------------------------------------------------------- */
.prepay-row{ display:flex; align-items:center; gap:16px; }

.prepay-row input[type=range]{
  --fill: 0%;
  flex:1; min-width:0; height:28px; margin:0;
  -webkit-appearance:none; appearance:none; background:transparent;
  cursor:pointer;
}
/* Дорожка закрашена до бегунка: видно не только где он стоит, но и сколько
   это от целого — а процент и есть доля от целого. */
.prepay-row input[type=range]::-webkit-slider-runnable-track{
  height:6px; border-radius:var(--radius-xs);
  background:linear-gradient(90deg,
    var(--accent-1) 0 var(--fill), var(--tint-neutral) var(--fill) 100%);
}
.prepay-row input[type=range]::-moz-range-track{
  height:6px; border-radius:var(--radius-xs); background:var(--tint-neutral);
}
.prepay-row input[type=range]::-moz-range-progress{
  height:6px; border-radius:var(--radius-xs); background:var(--accent-1);
}
.prepay-row input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:22px; height:22px; margin-top:-8px; border-radius:50%;
  background:#fff; border:1px solid rgba(17,17,17,.10);
  box-shadow:var(--shadow-soft);
  transition:transform .16s var(--spring);
}
.prepay-row input[type=range]::-moz-range-thumb{
  width:22px; height:22px; border-radius:50%;
  background:#fff; border:1px solid rgba(17,17,17,.10);
  box-shadow:var(--shadow-soft);
}
.prepay-row input[type=range]:active::-webkit-slider-thumb{ transform:scale(1.12); }
.prepay-row input[type=range]:focus-visible{ outline:none; }
.prepay-row input[type=range]:focus-visible::-webkit-slider-thumb{
  box-shadow:0 0 0 4px var(--accent-tint), var(--shadow-soft);
}

/* Ширина под «Без предоплаты», чтобы поле не дёргалось на каждом делении. */
.prepay-value{
  min-width:9.5ch; text-align:right;
  font-weight:700; font-size:15px; color:var(--accent-1);
  font-variant-numeric: tabular-nums;
}
.prepay-value.is-none{ font-weight:600; font-size:13px; color:var(--text-faint); }

@media (max-width: 860px){
  .prepay-row{ gap:12px; }
  .prepay-value{ min-width:8ch; font-size:14px; }
}

/* ==========================================================================
   iPhone
   ========================================================================== */

@media (max-width: 860px){
  /* Safari увеличивает страницу, когда фокус попадает в поле мельче 16px, и
     обратно уже не отматывает. Шестнадцать — это не про читаемость, это про
     то, чтобы экран не прыгал. */
  input[type=text], input[type=email], input[type=password], input[type=number],
  input[type=date], input[type=search], select, textarea{ font-size: 16px; }
  .num-field input{ font-size: 18px; }

  /* Панель вкладок не должна стоять на полосе жестов. */
  .nav{ padding-bottom: calc(8px + env(safe-area-inset-bottom)); }
  .shell{ padding-bottom: calc(96px + env(safe-area-inset-bottom)); }

  /* Кнопка, до которой нельзя промахнуться пальцем. */
  .btn, .chip-btn, .lang-option, .theme-toggle, .field-toggle{ min-height: 44px; }
  .btn-sm{ min-height: 38px; }

  body{ overflow-x: hidden; }
  .page-head{ position: static; }
  .page-actions{ display:flex; gap:8px; flex-wrap:wrap; }
  .modal{ width: calc(100vw - 24px); padding: 22px 20px; }
  .modal-actions{ flex-direction: column-reverse; }
  .modal-actions .btn{ width: 100%; }
  .backup-actions .btn{ min-width: 0; }
  .facts{ grid-template-columns: 1fr; gap: 2px 0; }
  .facts dt{ margin-top: 8px; }
}

/* iOS Safari не показывает PDF внутри iframe — вместо документа остаётся
   серый прямоугольник. Поэтому на узком экране вместо рамки стоит кнопка, и
   ведёт она на свой экран просмотра (documents/viewer.html): страницы там
   нарисованы картинками, и «Назад» — наша кнопка. Ссылка на сам файл увела
   бы в Safari, откуда в приложение с домашнего экрана не вернуться.

   Ссылки на файл в шапке карточки на телефоне прячутся: их работу делает эта
   же кнопка, а два «Открыть PDF» рядом, ведущие в разные места, — это выбор,
   которого человек не просил. */
@media (max-width: 700px){
  .pdf-frame, .pdf-pages{ display: none; }
  .pdf-fallback{ display: flex; }
  .review-doc-links{ display: none; }
}
.pdf-fallback{
  display: none; flex-direction: column; align-items: center; gap: 10px;
  padding: 28px 20px; text-align: center;
  border: 1px dashed var(--line); border-radius: var(--radius-md);
  background: var(--surface-strong);
}
.pdf-fallback small{ color: var(--text-faint); font-size: 12.5px; }

/* ==========================================================================
   Просмотр документа страницами (documents/viewer.html)

   Весь экран — документ, и одна вещь всегда на виду: «Назад». На телефоне
   это единственный выход: в приложении с домашнего экрана браузерной кнопки
   «назад» нет вовсе, а жест «смахнуть от края» там не работает. Поэтому
   кнопка липнет к верху при прокрутке и повторяется внизу — под большим
   пальцем у того, кто дочитал страницу до конца.
   ========================================================================== */
.viewer{ display:flex; flex-direction:column; min-height:100vh; min-height:100dvh; }
.viewer-bar{
  position:sticky; top:0; z-index:30;
  display:flex; align-items:center; gap:10px;
  padding: calc(8px + env(safe-area-inset-top)) 14px 8px;
  border-bottom:1px solid var(--line);
  background: var(--surface-strong);
  background: color-mix(in srgb, var(--surface-solid) 86%, transparent);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
}
/* 44 px в высоту — размер, в который палец попадает не целясь. */
.viewer-back{
  display:inline-flex; align-items:center; gap:2px; flex:none;
  min-height:44px; padding:6px 10px 6px 2px; margin-left:-2px;
  color:var(--accent-1); font-weight:600; font-size:15px; text-decoration:none;
}
.viewer-back svg{ width:22px; height:22px; }
.viewer-back:active{ opacity:.55; }
.viewer-title{ flex:1; min-width:0; text-align:center; }
.viewer-title strong{
  display:block; font-size:14px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.viewer-title small{ display:block; font-size:11.5px; color:var(--text-faint); }
.viewer-file, .viewer-share{ flex:none; }
.viewer-pages{
  flex:1; display:flex; flex-direction:column; align-items:center; gap:16px;
  padding:16px 14px;
}
.viewer-page{ width:100%; max-width:920px; margin:0; }
.viewer-failed{
  width:100%; max-width:520px; margin:24px 0 0; padding:18px 20px;
  border-radius:var(--radius-md); text-align:center; font-size:14px;
  color:var(--text-muted);
}
/* Белая подложка под картинкой: страница документа белая и в тёмной теме — */
/* пока она грузится, на её месте должен быть лист, а не дыра. */
.viewer-page img{
  display:block; width:100%; height:auto;
  background:#FFFFFF; border-radius:var(--radius-sm);
  box-shadow: var(--shadow-soft);
}
.viewer-page figcaption{
  padding-top:6px; text-align:center; font-size:12px; color:var(--text-faint);
}
.viewer-foot{
  display:flex; justify-content:center; flex-wrap:wrap; gap:10px;
  padding: 4px 14px calc(22px + env(safe-area-inset-bottom));
}
@media (max-width: 700px){
  .viewer-file, .viewer-bar .viewer-share{ padding:7px 11px; font-size:12px; }
  .viewer-pages{ gap:12px; padding:12px 10px; }
  /* Где телефон умеет «Поделиться» (share.js), в шапке остаётся одна эта
     кнопка: «Открыть файл» увёл бы во встроенный просмотрщик, откуда в
     приложение не вернуться, а на узкой шапке две кнопки съедают номер. */
  .viewer.can-share .viewer-file{ display:none; }
}
/* В приложении с домашнего экрана «Открыть файл» — ловушка: PDF ляжет в окно
   самого приложения, где нет «Назад» (жалоба 06.10). Файл там сохраняют
   «Скачать» и «Поделиться». Класс ставит main.js — iPhone не всегда отвечает
   на display-mode. */
.is-standalone .viewer-file{ display:none; }
@media (display-mode: standalone){ .viewer-file{ display:none; } }

/* Подпись шага внутри окна подтверждения: не `label` при поле, а заголовок
   над кнопкой, поэтому отступы свои. */
.field-label-plain{
  display:block; margin:14px 0 7px;
  font-size:12px; font-weight:600; color:var(--text-muted);
}

/* Поле, которое просит внимания: короткая подсветка вместо модального окна. */
.pin-input.is-off{
  border-color: var(--warn);
  box-shadow: 0 0 0 4px var(--tint-warn);
}

/* ==========================================================================
   Графики

   Геометрия — на рамках и флексе; SVG остался только там, где нужна кривая.
   Текста внутри рисунков нет: SVG с width:100% масштабирует подписи вместе с
   собой, и одна диаграмма рисовала текст вдвое крупнее другой. Подписи —
   обычный DOM, один кегль на всю страницу.

   Палитра проверена валидатором в обеих темах: ординальная шкала — один тон с
   монотонной светлотой, категориальная — три различимых при дальтонизме
   слота, статусная — отдельная, она никогда не изображает серию.
   ========================================================================== */

.viz{
  --viz-track: color-mix(in srgb, var(--text) 8%, transparent);
  --viz-seq: #23874F;
  --viz-o1: #88CDA2; --viz-o2: #4FB078; --viz-o3: #23874F;
  --viz-o4: #1B6B3C; --viz-o5: #104281; --viz-o6: #0a2d5a;
  --viz-c1: #23874F; --viz-c2: #eb6834; --viz-c3: #1baf7a;
  --viz-good: #0ca30c; --viz-warn: #fab219; --viz-crit: #d03b3b;
  --viz-idle: #8e8e93;
  --viz-radius: 4px;
}
/* Тёмная тема — не инверсия светлой, а собственные ступени тех же тонов,
   проверенные против тёмного фона. */
[data-theme="dark"] .viz{
  --viz-seq: #2E9A5C;
  --viz-o1: #CDEBD8; --viz-o2: #A3DBB8; --viz-o3: #6CC08B;
  --viz-o4: #2E9A5C; --viz-o5: #217A45; --viz-o6: #185E36;
  --viz-c1: #2E9A5C; --viz-c2: #d95926; --viz-c3: #199e70;
}

/* ---------- Заливки ---------- */
.viz-bar-fill{ background: var(--viz-seq); }
.viz-step-1{ background: var(--viz-o1); }
.viz-step-2{ background: var(--viz-o2); }
.viz-step-3{ background: var(--viz-o3); }
.viz-step-4{ background: var(--viz-o4); }
.viz-step-5{ background: var(--viz-o5); }
.viz-step-6{ background: var(--viz-o6); }
.viz-cat-1{ background: var(--viz-c1); }
.viz-cat-2{ background: var(--viz-c2); }
.viz-cat-3{ background: var(--viz-c3); }
.viz-good{ background: var(--viz-good); }
.viz-warn{ background: var(--viz-warn); }
.viz-crit{ background: var(--viz-crit); }
.viz-idle{ background: var(--viz-idle); }

/* ---------- Полосы --------------------------------------------------------
   Скругляется только значащий конец: основание стоит на оси. Скруглить оба —
   слегка соврать о начале отсчёта. */
.viz-rows{ display:grid; gap:9px; }
.viz-row{
  display:grid; grid-template-columns: minmax(84px, 33%) 1fr auto;
  align-items:center; gap:12px;
}
.viz-row-label{
  font-size:12.5px; color:var(--text-muted);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.viz-row-track{
  position:relative; display:block; height:12px; min-width:40px;
  background: var(--viz-track); border-radius: var(--viz-radius);
}
.viz-row-fill{
  display:block; height:100%; min-width:3px;
  border-radius: 0 var(--viz-radius) var(--viz-radius) 0;
  transition: width 420ms var(--ease-ios);
}
.viz-row-value{
  font-family:var(--font-display); font-size:12.5px; font-weight:650;
  font-variant-numeric: tabular-nums; color:var(--text); white-space:nowrap;
}

/* ---------- Воронка ---------- */
.viz-funnel{ display:grid; gap:12px; }
.viz-funnel-row{
  display:grid; grid-template-columns: minmax(96px, 26%) 1fr 42px;
  align-items:center; gap:12px;
}
.viz-funnel-label{ font-size:13px; color:var(--text-muted); }
.viz-funnel-bar{ display:flex; align-items:center; gap:10px; min-width:0; }
.viz-funnel-fill{
  display:block; height:16px; min-width:3px;
  border-radius: 0 var(--viz-radius) var(--viz-radius) 0;
  transition: width 480ms var(--ease-ios);
}
.viz-funnel-value{
  font-family:var(--font-display); font-size:13.5px; font-weight:700;
  font-variant-numeric: tabular-nums; color:var(--text);
}
.viz-funnel-drop{
  font-family:var(--font-display); font-size:12px; font-weight:650;
  font-variant-numeric: tabular-nums; color:var(--danger); text-align:right;
}

/* ---------- Доли ---------- */
.viz-segments{
  display:flex; height:26px; border-radius: var(--viz-radius);
  overflow:hidden; gap:2px; background: var(--viz-track);
}
.viz-segment{ display:block; min-width:3px; }

.viz-legend{ display:flex; flex-wrap:wrap; gap:7px 16px; margin-top:12px; }
.viz-key{ display:inline-flex; align-items:center; gap:7px;
          font-size:12.5px; color:var(--text-muted); }
.viz-key b{ color:var(--text); font-variant-numeric:tabular-nums; }
.viz-dot{ width:10px; height:10px; border-radius:3px; flex:none; }

/* ---------- Столбцы ---------- */
.viz-columns{ display:flex; align-items:flex-end; gap:3px; height:132px; }
.viz-column{
  flex:1; display:flex; flex-direction:column; justify-content:flex-end;
  align-items:center; height:100%; min-width:0;
}
.viz-column-bar{
  width:100%; min-height:2px;
  border-radius: var(--viz-radius) var(--viz-radius) 0 0;
  transition: height 420ms var(--ease-ios);
}
.viz-column-tick{
  margin-top:6px; font-size:10px; color:var(--text-faint);
  font-variant-numeric: tabular-nums; height:12px;
}

/* ---------- Область ---------- */
.viz-area-wrap{ position:relative; height: var(--viz-h, 110px); }
.viz-area-svg{ display:block; width:100%; height:100%; }
.viz-area{ fill: var(--viz-seq); opacity:.15; }
/* vector-effect держит толщину линии постоянной, хотя SVG растянут по
   ширине: без него линия на широкой карточке становится тоньше. */
.viz-line{
  fill:none; stroke: var(--viz-seq); stroke-width:2;
  stroke-linejoin:round; stroke-linecap:round;
  vector-effect: non-scaling-stroke;
}
/* Точки — элементы поверх рисунка, поэтому остаются круглыми при любом
   растяжении. Кольцо цветом подложки не даёт им слиться с линией. */
.viz-point{
  position:absolute; width:9px; height:9px; margin:0 0 -4.5px -4.5px;
  border-radius:50%; background: var(--viz-seq);
  box-shadow: 0 0 0 2px var(--surface-solid);
}
.viz-axis-labels{
  display:flex; justify-content:space-between; align-items:baseline;
  margin-top:8px; font-size:11px; color:var(--text-faint);
  font-variant-numeric: tabular-nums;
}
.viz-axis-peak{ color:var(--text-muted); font-weight:600; }

/* ---------- Измеритель ---------- */
.viz-meter{ margin-bottom:15px; }
.viz-meter:last-child{ margin-bottom:0; }
.viz-meter-head{
  display:flex; justify-content:space-between; align-items:baseline;
  gap:10px; margin-bottom:7px; font-size:13px; color:var(--text-muted);
}
.viz-meter-head b{ color:var(--text); font-variant-numeric:tabular-nums; }
.viz-meter .viz-row-track{ height:10px; }
.viz-meter small{ display:block; margin-top:6px; font-size:11.5px; color:var(--text-faint); }

/* ---------- Сетка карточек ---------- */
.chart-grid{
  display:grid; gap:16px; margin-bottom:16px;
  grid-template-columns:repeat(auto-fit, minmax(330px, 1fr));
}
.chart-card{ padding:20px 22px; display:flex; flex-direction:column; }
.chart-card h3{ margin-bottom:4px; }
.chart-note{ font-size:12px; color:var(--text-faint); margin:0 0 16px; }
.chart-wide{ grid-column:1 / -1; }
.chart-empty{ color:var(--text-faint); font-size:13px; padding:16px 0; }

@media (max-width: 860px){
  .viz-row{ grid-template-columns: minmax(72px, 40%) 1fr auto; gap:9px; }
  .viz-funnel-row{ grid-template-columns: minmax(84px, 34%) 1fr 36px; }
  .viz-columns{ height:104px; }
}

/* На печати графики остаются: это отчёт, а не украшение страницы. Фон
   печатается принудительно — без этого браузер выбрасывает заливки, и от
   диаграммы остаются пустые рамки. */
@media print{
  .chart-card{ break-inside:avoid; }
  .viz-row-fill, .viz-funnel-fill, .viz-segment, .viz-column-bar, .viz-dot{
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
  }
}

/* Кнопка выхода в шапке — заметная, но не кричащая; отделена от действий страницы. */

/* --- Сайдбар: длинное меню скроллится, низ с аккаунтом и выходом закреплён --
   13 пунктов меню перерастали высоту экрана, и подвал (аккаунт + «Выход»)
   уходил за нижний край — кнопки выхода было не видно. Теперь прокручивается
   только список пунктов, а логотип сверху и подвал снизу стоят на месте. */
.sidebar{ min-height:0; }
.sidebar .nav{ flex:1 1 auto; min-height:0; overflow-y:auto; overflow-x:hidden; }
/* flex:1 делает меню высотой во весь сайдбар, а сетка по умолчанию растягивает
   строки на всю свою высоту. У админа пунктов много, и это не видно; у
   сотрудника их три, и каждый вытягивался в плиту на треть экрана. Пункты
   прижаты к верху, остальное место остаётся пустым. */
.sidebar .nav{ align-content:start; }
.sidebar .nav{ scrollbar-width:thin; }
.sidebar .nav::-webkit-scrollbar{ width:6px; }
.sidebar .nav::-webkit-scrollbar-thumb{ background:var(--border-strong); border-radius:3px; }
.sidebar-foot{ margin-top:0; flex:none; padding-top:14px; border-top:1px solid var(--border); }

/* Кнопка выхода в подвале — заметная: акцентная рамка, заливка при наведении. */
.sidebar-foot form .btn{
  border:1px solid var(--accent-1); color:var(--accent-1); font-weight:700;
}
.sidebar-foot form .btn:hover{ background:var(--accent-1); color:#fff; }

/* --- Телефон: сайдбар — шапка, меню — панель вкладок внизу экрана ---------
   Две поправки к правилам выше, которые писались для компьютера.
   1. backdrop-filter у стеклянного сайдбара делает его контейнером для
      position:fixed внутри. Панель вкладок цеплялась не к низу экрана, а к
      самой шапке и закрывала логотип. Шапка стоит на фоне страницы, размывать
      под ней нечего — фильтр снимаем, и панель встаёт вниз, как задумано.
   2. `.sidebar .nav` выше запрещал прокрутку вбок, а на телефоне вкладки
      в одну строку не помещаются — возвращаем её. Разделитель над подвалом
      в строке шапки тоже лишний. */
@media (max-width: 860px){
  .sidebar{ backdrop-filter:none; -webkit-backdrop-filter:none; }
  .sidebar .nav{ flex:none; overflow-x:auto; overflow-y:hidden; }
  .sidebar-foot{ padding-top:0; border-top:0; }
}

/* --- Подпись рукой на финальном подтверждении (Admin 3) ------------------
   Поле — белый лист в любой теме: подпись рисуется тёмными чернилами и в
   таком же виде ложится на PDF, поэтому и на экране она на бумаге. */
.sign-field{ margin-top:4px; }
.sign-pad{
  position:relative; height:180px; border-radius:var(--radius-md);
  background:#fff; border:1.5px dashed var(--line);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.05);
  transition: border-color var(--transition);
}
.sign-pad:hover{ border-color: var(--accent-1-light); }
.sign-pad.has-ink{ border-style:solid; border-color: var(--accent-1-light); }
.sign-pad.is-invalid{ border-color: var(--danger); }
.sign-canvas{
  display:block; width:100%; height:100%; border-radius:inherit;
  cursor:crosshair; touch-action:none;   /* палец рисует, а не листает окно */
}
/* Линия и подсказка — как на бланке: «подпись здесь». */
.sign-pad::after{
  content:""; position:absolute; left:22px; right:22px; bottom:40px;
  border-bottom:1px solid #D9DBE3; pointer-events:none;
}
.sign-hint{
  position:absolute; left:22px; bottom:16px; font-size:12px; color:#8A8F9C;
  pointer-events:none; transition: opacity var(--transition);
}
.sign-pad.has-ink .sign-hint{ opacity:0; }
.sign-clear{
  position:absolute; top:8px; right:8px; min-height:30px !important;
  padding:4px 10px; font-size:12px; color:#5A5A61; background:rgba(0,0,0,.04);
}
.sign-error{ margin:8px 0 0; color: var(--danger); font-size:13px; font-weight:600; }
.sign-field > small{ display:block; margin-top:8px; line-height:1.45; }

/* Что осталось после подписи: сама подпись, кто и секунда. */
.sign-record{
  display:flex; align-items:center; gap:16px; margin:16px 0 4px; padding:12px 14px;
  border:1px solid var(--line); border-radius:var(--radius-md); background:#fff;
}
.sign-record img{ width:132px; max-height:60px; object-fit:contain; flex:none; }
.sign-record figcaption{ display:grid; gap:2px; font-size:13px; color:#1c1f26; min-width:0; }
.sign-record .mono{ font-family:var(--font-mono); font-size:13.5px; font-weight:700; }
.sign-record small{ color:#6b707c; }
.sign-record .sign-warn{ color: var(--danger); }
.review-doc-links{ display:flex; gap:8px; flex-wrap:wrap; justify-content:flex-end; }
@media (max-width: 560px){
  .sign-pad{ height:160px; }
  .sign-record{ flex-direction:column; align-items:flex-start; }
}

/* Чья это дверь: на двух адресах — «для сотрудников» или «для администраторов». */
.portal-tag{
  display:table; margin:-14px auto 22px; padding:5px 12px; border-radius:var(--radius-xs);
  font-size:12px; font-weight:700; letter-spacing:.04em;
  background:var(--accent-tint); color:var(--accent-1);
}
.portal-tag.portal-admin{ background:rgba(22,90,50,.92); color:#fff; }

/* Ссылка «Нет учётки? Зарегистрироваться» под формой входа — и обратная. */
.auth-switch{ margin:18px 0 0; text-align:center; font-size:14px; color:var(--text-muted); }
.auth-switch a{ font-weight:700; }

/* Заявки на регистрацию у Super Admin: над таблицей людей, пока они есть. */
.pending-card{ padding:18px 20px; margin-bottom:18px; border:1.5px solid var(--accent-1-light); }
.pending-card h3{ margin:0 0 4px; }
.pending-list{ list-style:none; margin:12px 0 0; padding:0; display:grid; gap:10px; }
.pending-item{
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  padding:10px 12px; border-radius:var(--radius-sm); background:var(--surface-strong);
}
.pending-who{ display:grid; gap:2px; min-width:0; }
.pending-who small{ color:var(--text-muted); }
.pending-item form{ display:flex; gap:8px; }

/* --- Уведомления ----------------------------------------------------------
   Список событий и переключатель доставки. Всё на переменных темы: страница
   открывается и в светлой, и в тёмной. */
.notif-list{ list-style:none; margin:0; padding:0; }
.notif-item{
  display:flex; align-items:flex-start; gap:14px; justify-content:space-between;
  padding:14px 0; border-top:1px solid var(--line);
}
.notif-item:first-child{ border-top:0; }
.notif-text{ display:flex; flex-direction:column; gap:3px; min-width:0; }
.notif-text b{ font-size:14.5px; }
.notif-text span{ font-size:13.5px; color:var(--text-muted); }
.notif-text small{ font-size:12px; color:var(--text-muted); opacity:.75; }
/* Непрочитанное помечено полосой слева, а не цветом текста: цвет уже занят
   ссылками и статусами, а полоса читается с одного взгляда и не спорит ни с
   чем на странице. */
.notif-item.is-unread{
  border-left:3px solid var(--accent-1); padding-left:12px; margin-left:-15px;
}

/* Переключатель, а не кнопка «подписаться»: состояние должно читаться
   с одного взгляда, без нажатия. */
.push-row{
  display:flex; align-items:center; gap:14px; justify-content:space-between;
  flex-wrap:wrap;
}
.push-row-text{ flex:1; min-width:180px; display:flex; flex-direction:column; gap:2px; }
.push-row-text b{ font-size:14.5px; }
.push-row-text span{ font-size:12.5px; color:var(--text-muted); }

.push-switch{ position:relative; flex:none; width:50px; height:29px; }
.push-switch input{
  position:absolute; inset:0; width:100%; height:100%; margin:0;
  opacity:0; cursor:pointer;
}
.push-switch i{
  position:absolute; inset:0; border-radius:99px; pointer-events:none;
  background:var(--tint-neutral); border:1px solid var(--line);
  transition:background .18s ease, border-color .18s ease;
}
.push-switch i::after{
  content:''; position:absolute; top:3px; left:3px; width:21px; height:21px;
  border-radius:50%; background:#fff; box-shadow:var(--shadow-soft);
  transition:transform .18s ease;
}
.push-switch input:checked + i{ background:var(--success); border-color:transparent; }
.push-switch input:checked + i::after{ transform:translateX(21px); }
/* Видимый фокус: переключатель ловят и с клавиатуры, а рамку браузера на
   прозрачном checkbox не видно. */
.push-switch input:focus-visible + i{ outline:2px solid var(--accent-1); outline-offset:2px; }
.push-switch input:disabled{ cursor:default; }
.push-switch input:disabled + i{ opacity:.5; }

.push-status{ margin:12px 0 0; min-height:1.2em; font-size:12.5px; color:var(--text-muted); }
.push-status-ok{ color:var(--success); }
.push-status-warn{ color:var(--warn); }

.push-devices{ list-style:none; margin:14px 0 0; padding:0; }
.push-devices li{
  display:flex; align-items:baseline; gap:10px; justify-content:space-between;
  padding:8px 0; border-top:1px solid var(--line); font-size:13px;
}
.push-devices li span{ color:var(--text-muted); font-size:12px; white-space:nowrap; }

/* ==========================================================================
   Номер версии внизу каждой страницы
   «Версия 3» — целое число из config.VERSION, +1 на каждую выкладку.
   Мелко и цветом подписей (--text-faint, как роль под именем в меню): кто
   ищет номер, находит его, остальным он не мешает. Разметка —
   templates/_version.html, место выбирает макет.
   ========================================================================== */
.app-version{
  margin:0; padding:8px 16px 14px;
  font-size:11.5px; line-height:16px; letter-spacing:0;
  color:var(--text-faint); text-align:center;
  font-variant-numeric: tabular-nums;
}
/* Под страницей — вход, ошибки, первый вход, лист согласования: ещё и над
   полоской «Домой» у iPhone. Карточка входа стоит посреди экрана во всю его
   высоту; эту высоту она делит со строкой версии, иначе строка уезжала бы за
   нижний край и её пришлось бы долистывать. 38px — высота строки: 8+16+14. */
body > .app-version{ padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
.auth-wrap{
  min-height: calc(100vh - 38px);
  min-height: calc(100dvh - 38px - env(safe-area-inset-bottom));
}
/* В панели — последней строкой колонки: на длинной странице под последней
   карточкой, на короткой — у нижнего края экрана. Колонка для этого — столбик
   из двух частей: страница (.content-main, внутри обычный блок, как был) и
   строка версии. Отступ снизу уже есть у самой колонки, а на телефоне — ещё и
   место под панель вкладок. */
.content{ display:flex; flex-direction:column; }
.content-main{ flex:1 0 auto; min-width:0; }
.content > .app-version{ padding:28px 0 0; }
/* В просмотрщике — своей строкой под кнопками подвала. */
.viewer-foot .app-version{ flex-basis:100%; padding:2px 0 0; }
/* На бумаге номера нет: лист согласования и распечатанная очередь — документы,
   а не страницы сайта. */
@media print{
  .app-version{ display:none !important; }
  /* Бумага режется на листы, а flex-колонку браузеры режут хуже блока. */
  .content{ display:block; }
}

/* ---------- «Отменить подтверждение» ---------------------------------------
   Плашка над очередью после подписи (10 минут) и карточка на странице
   документа. Акцент — предупреждающий: это выход назад, не главное действие. */
.undo-bar{
  display:flex; align-items:center; flex-wrap:wrap; gap:8px 14px;
  padding:10px 14px; margin:0 0 10px; border-radius:var(--radius-md);
  border-color:color-mix(in srgb, var(--warn) 45%, var(--border));
  box-shadow:inset 3px 0 0 var(--warn);
}
.undo-title{ font-size:13.5px; }
.undo-list{ list-style:none; margin:0; padding:0; display:grid; gap:6px; flex:1 1 100%; }
.undo-row{ display:flex; align-items:center; flex-wrap:wrap; gap:6px 12px; }
.undo-doc{ font-weight:650; font-variant-numeric:tabular-nums; }
.undo-party{ font-size:13px; color:var(--text-muted); min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; }
.undo-left{ font-size:13px; color:var(--warn); font-variant-numeric:tabular-nums; }
.undo-row .btn{ margin-left:auto; }
.undo-all{ margin-left:auto; }
.undo-card{ border-color:color-mix(in srgb, var(--warn) 45%, var(--border)); }
.undo-card .undo-row .btn{ margin-left:0; }
@media (max-width: 640px){
  .undo-row .btn{ margin-left:0; width:100%; }
}

/* ---------- Опрос по платформе (survey.html) --------------------------------
   Вступление с сердцем → «Начать» → вопросы поднимаются по одному → «Спасибо».
   Движения много (просьба владельца 11.10 — «макс анимация»): сердечки на фоне,
   заголовок по словам, искры у звёзд, салют на «Спасибо». С «уменьшить
   движение» в системе — ничего этого, и скрипт частиц не рисует. Без скрипта
   вступление и вопросы просто стоят друг под другом. */
.survey-wrap{
  position:relative; z-index:1;
  max-width:680px; margin:0 auto; padding:64px 16px 32px;
  min-height: calc(100vh - 38px);
  min-height: calc(100dvh - 38px - env(safe-area-inset-bottom));
}
.survey-card{ padding:40px 30px 32px; border-radius:var(--radius-xl); text-align:center; }
.survey-card h1{ font-size:27px; margin:18px 0 10px; letter-spacing:-.02em; }
.survey-lead{ color:var(--text-muted); font-size:15.5px; line-height:1.6; max-width:460px; margin:0 auto; }
.survey-sign{ margin:18px 0 0; font-family:var(--font-display); font-weight:700; font-size:14px;
  color:var(--accent-1); }
.survey-meta{ margin:12px 0 0; color:var(--text-faint); font-size:13px; }
.survey-start{ margin-top:26px; min-width:220px; }

/* Сердце: бьётся на вступлении, «выпрыгивает» на «Спасибо». */
.survey-heart{
  --heart:#EF4E6A;
  position:relative; width:78px; height:78px; margin:0 auto; border-radius:50%;
  display:grid; place-items:center; color:var(--heart);
  background: color-mix(in srgb, var(--heart) 14%, transparent);
}
.survey-heart svg{ width:38px; height:38px; fill:currentColor; position:relative; z-index:1;
  filter: drop-shadow(0 4px 10px color-mix(in srgb, var(--heart) 45%, transparent)); }
.survey-heart::before, .survey-heart::after{
  content:''; position:absolute; inset:0; border-radius:50%;
  background: color-mix(in srgb, var(--heart) 22%, transparent); opacity:0;
}
.survey-heart.is-beat svg{ animation: survey-beat 1.7s var(--ease-ios) infinite; }
.survey-heart.is-beat::before{ animation: survey-ring 1.7s var(--ease-ios) infinite; }
.survey-heart.is-beat::after{ animation: survey-ring 1.7s var(--ease-ios) .5s infinite; }
.survey-heart.is-pop{ animation: survey-pop 760ms var(--spring) both; }
.survey-heart.is-pop svg{ animation: survey-beat 1.7s var(--ease-ios) .9s infinite; }
.survey-heart.is-pop::before{ animation: survey-ring 1.1s var(--ease-ios) 260ms 3; }
@keyframes survey-beat{
  0%,100%{ transform:scale(1); } 14%{ transform:scale(1.2); } 28%{ transform:scale(1); }
  42%{ transform:scale(1.12); } 70%{ transform:scale(1); }
}
@keyframes survey-ring{ 0%{ transform:scale(.85); opacity:.75; } 100%{ transform:scale(1.9); opacity:0; } }
@keyframes survey-pop{ 0%{ transform:scale(.3); opacity:0; } 100%{ transform:scale(1); opacity:1; } }

/* Карточка вступления и «Спасибо»: выплывает, внутри — всё по очереди. */
.survey-intro, .survey-thanks{ animation: survey-in 760ms var(--spring) backwards; }
.survey-intro > *, .survey-thanks > *{ animation: survey-rise 620ms var(--ease-ios) backwards; }
.survey-intro > :nth-child(1), .survey-thanks > :nth-child(1){ animation: survey-pop 760ms var(--spring) 120ms backwards; }
.survey-intro > :nth-child(2), .survey-thanks > :nth-child(2){ animation:none; }
.survey-intro > :nth-child(3), .survey-thanks > :nth-child(3){ animation-delay: 620ms; }
.survey-intro > :nth-child(4), .survey-thanks > :nth-child(4){ animation-delay: 760ms; }
.survey-intro > :nth-child(5), .survey-thanks > :nth-child(5){ animation: survey-pop-in 700ms var(--spring) 900ms backwards; }
.survey-intro > :nth-child(6), .survey-thanks > :nth-child(6){ animation-delay: 1040ms; }
.survey-thanks > :nth-child(4){ animation:none; }
@keyframes survey-in{
  from{ opacity:0; transform: translateY(30px) scale(.94); }
  to{ opacity:1; transform:none; }
}
@keyframes survey-pop-in{
  0%{ opacity:0; transform: translateY(14px) scale(.8); }
  100%{ opacity:1; transform:none; }
}
/* Заголовок — по словам (survey.js делит его на .survey-word). */
.survey-word{ display:inline-block; animation: survey-word 640ms var(--spring) backwards;
  animation-delay: calc(var(--w, 0) * 85ms + 280ms); }
@keyframes survey-word{
  from{ opacity:0; transform: translateY(16px) scale(.9); filter: blur(6px); }
  to{ opacity:1; transform:none; filter:none; }
}
/* Блик по главной кнопке — раз в несколько секунд. */
.survey-start::after, .survey-go::after, .survey-send.is-ready::after{
  content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background: linear-gradient(110deg, transparent 32%, rgba(255,255,255,.5) 50%, transparent 68%);
  background-size: 260% 100%; background-position: 160% 0;
  animation: survey-shine 3.4s ease-in-out 1.8s infinite;
}
@keyframes survey-shine{ 0%{ background-position:160% 0; } 45%,100%{ background-position:-60% 0; } }

.survey-intro.is-leaving{ animation: survey-out 480ms var(--ease-ios) forwards; }
@keyframes survey-out{ to{ opacity:0; transform: translateY(-26px) scale(.92); filter: blur(8px); } }

/* Вопросы: поднимаются каскадом, номера «выпрыгивают», разделы въезжают. */
.survey.is-intro .survey-form, .survey.is-intro .survey-logout{ display:none; }
.survey.is-started .survey-head,
.survey.is-started .survey-progress,
.survey.is-started .survey-q,
.survey.is-started .survey-actions{
  animation: survey-rise 620ms var(--ease-ios) backwards;
  animation-delay: calc(var(--i, 0) * 110ms + 60ms);
}
.survey.is-started .survey-section{
  animation: survey-slide 620ms var(--ease-ios) backwards;
  animation-delay: calc(var(--i, 0) * 110ms + 60ms);
}
.survey.is-started .survey-num{
  animation: survey-num 700ms var(--spring) backwards;
  animation-delay: calc(var(--i, 0) * 110ms + 330ms);
}
.survey.is-started .survey-actions{ --i:5; }
@keyframes survey-rise{
  from{ opacity:0; transform: translateY(22px) scale(.98); }
  to{ opacity:1; transform:none; }
}
@keyframes survey-slide{ from{ opacity:0; transform: translateX(-18px); } to{ opacity:1; transform:none; } }
@keyframes survey-num{ 0%{ opacity:0; transform: scale(.2) rotate(-25deg); } 100%{ opacity:1; transform:none; } }

.survey-head{ display:flex; align-items:center; gap:14px; }
.survey-head h1{ font-size:24px; margin:0; letter-spacing:-.02em; }
.survey-head .survey-meta{ margin:2px 0 0; }
.survey-progress{
  position:sticky; top:0; z-index:5; margin:14px -8px 0; padding:12px 8px 8px;
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.survey-bar{ height:7px; border-radius:99px; background:var(--line); overflow:hidden; }
.survey-bar i{
  position:relative; display:block; height:100%; width:0; border-radius:99px; overflow:hidden;
  background: linear-gradient(90deg, var(--accent-fill-a), var(--accent-fill-b));
  transition: width 520ms var(--spring), box-shadow 400ms;
}
.survey-bar i::after{
  content:''; position:absolute; inset:0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent);
  transform: translateX(-100%); animation: survey-bar 1.9s ease-in-out infinite;
}
.survey-bar.is-full i{ background: linear-gradient(90deg, var(--accent-fill-a), #EF4E6A); }
@keyframes survey-bar{ to{ transform: translateX(100%); } }
.survey-progress small{ display:block; margin-top:6px; font-size:12.5px; color:var(--text-faint); }
.survey-error{
  margin-top:14px; padding:12px 16px; border-radius:var(--radius-md);
  background:var(--tint-danger); color:var(--danger); font-weight:600; font-size:14px;
  animation: survey-shake 520ms var(--ease-ios) 200ms backwards;
}
@keyframes survey-shake{
  0%{ opacity:0; transform: translateX(0); } 20%{ opacity:1; transform: translateX(-8px); }
  40%{ transform: translateX(7px); } 60%{ transform: translateX(-5px); }
  80%{ transform: translateX(3px); } 100%{ transform:none; }
}
.survey-section{
  margin:28px 0 0 4px; font-size:12px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--accent-1);
}
.survey-progress + .survey-section, .survey-error + .survey-section{ margin-top:18px; }

.survey-q{ margin-top:12px; padding:20px; border-radius:var(--radius-xl);
  transition: transform 360ms var(--spring), box-shadow 360ms var(--ease-ios); }
.survey-q:focus-within{ transform: translateY(-3px); box-shadow: var(--shadow-lift), inset 0 1px 0 var(--sheen); }
.survey-q-head{ display:flex; gap:12px; align-items:flex-start; margin-bottom:14px; }
.survey-num{
  flex:none; width:30px; height:30px; border-radius:9px; display:grid; place-items:center;
  background:var(--accent-tint); color:var(--accent-1);
  font-family:var(--font-display); font-weight:800;
  transition: background 300ms, color 300ms;
}
.survey-q.is-done .survey-num{ background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b)); color:#fff;
  animation: survey-done 520ms var(--spring); }
@keyframes survey-done{ 0%{ transform:scale(1); } 45%{ transform:scale(1.28) rotate(8deg); } 100%{ transform:none; } }
.survey-q h2{ font-size:17px; line-height:1.3; margin:4px 0 3px; }
.survey-q-head p{ margin:0; font-size:13.5px; color:var(--text-muted); }
.survey-q textarea{ min-height:96px; }
.survey-q textarea.survey-small{ min-height:64px; }

/* Звёзды: радиокнопки в обратном порядке, «~» подсвечивает те, что левее. */
.survey-rate{ display:flex; align-items:center; flex-wrap:wrap; gap:6px 14px; margin-bottom:16px; }
.survey-stars{ display:inline-flex; flex-direction:row-reverse; gap:4px; }
.survey-stars input{ position:absolute; opacity:0; pointer-events:none; }
.survey-stars label{ cursor:pointer; padding:2px; line-height:0; border-radius:8px;
  -webkit-tap-highlight-color: transparent; }
.survey-stars svg{
  width:40px; height:40px; fill: color-mix(in srgb, var(--text) 14%, transparent);
  transition: fill 160ms, transform 240ms var(--spring), filter 240ms;
}
.survey-stars input:checked ~ label svg,
.survey-stars label:hover svg, .survey-stars label:hover ~ label svg{ fill:var(--warn);
  filter: drop-shadow(0 3px 8px color-mix(in srgb, var(--warn) 45%, transparent)); }
.survey-stars:hover input:checked ~ label svg{ fill: color-mix(in srgb, var(--text) 14%, transparent); filter:none; }
.survey-stars:hover label:hover svg, .survey-stars:hover label:hover ~ label svg{ fill:var(--warn); }
.survey-stars label:hover svg{ animation: survey-wiggle 520ms var(--ease-ios); }
.survey-stars input:checked + label svg{ animation: survey-star 520ms var(--spring); }
.survey-stars input:focus-visible + label{ box-shadow:0 0 0 4px var(--accent-tint); }
@keyframes survey-star{ 0%{ transform:scale(.5) rotate(-30deg); } 60%{ transform:scale(1.3) rotate(8deg); } 100%{ transform:none; } }
@keyframes survey-wiggle{ 0%,100%{ transform:none; } 30%{ transform: rotate(-12deg) scale(1.1); } 65%{ transform: rotate(9deg) scale(1.1); } }
.survey-rate-text{ font-weight:600; color:var(--text-muted); }
.survey-rate-text.is-new{ animation: survey-pop-in 420ms var(--spring); }

.survey-label{ margin:0 0 8px; font-size:13px; font-weight:600; color:var(--text-muted); }
.survey-label span{ font-weight:400; color:var(--text-faint); }
.survey-opts{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:12px; }
.survey-opts input{ position:absolute; opacity:0; pointer-events:none; }
.survey-opts label{
  display:inline-flex; align-items:center; gap:7px; cursor:pointer; user-select:none;
  padding:8px 13px; border-radius:10px; font-size:14px;
  border:1px solid var(--line); background:var(--input-bg);
  transition: background 180ms, border-color 180ms, color 180ms, transform 240ms var(--spring);
  -webkit-tap-highlight-color: transparent;
}
.survey-opts label:hover{ transform: translateY(-1.5px); border-color: color-mix(in srgb, var(--accent-1) 40%, var(--line)); }
.survey-opts label:active{ transform:scale(.94); }
.survey-opts label::before{
  content:''; flex:none; width:16px; height:16px; border-radius:5px;
  border:1.5px solid var(--text-faint); transition: all 180ms;
}
.survey-opts input:checked + label{
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b));
  border-color:transparent; color:#fff; animation: survey-chip 460ms var(--spring);
  box-shadow: var(--shadow-accent);
}
.survey-opts input:checked + label::before{
  border-color:#fff; background:#fff
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231A3D8F' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center/12px no-repeat;
  animation: survey-num 420ms var(--spring);
}
.survey-opts input:focus-visible + label{ box-shadow:0 0 0 4px var(--accent-tint); }
@keyframes survey-chip{ 0%{ transform:scale(.9); } 55%{ transform:scale(1.07); } 100%{ transform:none; } }

.survey-actions{ margin-top:24px; display:grid; justify-items:center; gap:10px; text-align:center; }
.survey-send{ width:100%; max-width:340px; }
.survey-send.is-ready{ animation: survey-ready 2s ease-in-out infinite; }
@keyframes survey-ready{
  0%,100%{ box-shadow: var(--shadow-accent), 0 0 0 0 color-mix(in srgb, var(--accent-1) 40%, transparent); }
  50%{ box-shadow: var(--shadow-accent), 0 0 0 10px color-mix(in srgb, var(--accent-1) 0%, transparent); transform: translateY(-2px); }
}
.survey-logout{ margin-top:22px; text-align:center; }

/* «Спасибо»: звёзды загораются по одной. */
.survey-got{ display:flex; justify-content:center; gap:6px; margin-top:16px; }
.survey-got svg{ width:30px; height:30px; fill: color-mix(in srgb, var(--text) 14%, transparent); }
.survey-got span{ animation: survey-star 620ms var(--spring) backwards;
  animation-delay: calc(var(--i, 0) * 130ms + 700ms); line-height:0; }
.survey-got .on svg{ fill:var(--warn); filter: drop-shadow(0 3px 8px color-mix(in srgb, var(--warn) 45%, transparent)); }
.survey-go{ margin-top:24px; min-width:240px; }

/* Сердечки на фоне и частицы — их рисует survey.js. */
.survey-float{ position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden; }
.survey-float span{
  position:absolute; bottom:-48px; left:var(--x); width:var(--s); height:var(--s); line-height:0;
  opacity:0; animation: survey-float var(--d) linear var(--delay) infinite;
}
.survey-float svg, .survey-particle svg{ width:100%; height:100%; fill:var(--c); }
@keyframes survey-float{
  0%{ transform: translate(0, 0) rotate(0); opacity:0; }
  12%{ opacity:var(--o); }
  50%{ transform: translate(var(--sway), -55vh) rotate(var(--rot)); }
  88%{ opacity:var(--o); }
  100%{ transform: translate(0, -112vh) rotate(calc(var(--rot) * -1)); opacity:0; }
}
.survey-particle{
  position:fixed; left:var(--x); top:var(--y); z-index:90; pointer-events:none; line-height:0;
  width:var(--s); height:var(--s); margin:calc(var(--s) / -2) 0 0 calc(var(--s) / -2);
  animation: survey-burst var(--d) cubic-bezier(.15,.75,.3,1) forwards;
}
@keyframes survey-burst{
  0%{ transform: translate(0, 0) scale(.2) rotate(0); opacity:1; }
  70%{ opacity:1; }
  100%{ transform: translate(var(--dx), var(--dy)) scale(1) rotate(var(--rot)); opacity:0; }
}

/* «Ответы опроса» у Super Admin (super/survey.html): карточка на человека. */
.answers{ display:grid; gap:12px; margin-top:16px; }
.answer{ padding:18px 20px; border-radius:var(--radius-lg); }
.answer-head{ display:flex; justify-content:space-between; align-items:flex-start; gap:8px 16px;
  flex-wrap:wrap; margin-bottom:10px; }
.answer-head strong{ display:block; font-size:15.5px; }
.answer-head .muted{ font-size:13px; }
.answer-meta{ display:grid; justify-items:end; gap:2px; font-size:12.5px; }
.answer-stars{ display:inline-flex; gap:2px; line-height:0; }
.answer-stars svg{ width:17px; height:17px; fill: color-mix(in srgb, var(--text) 14%, transparent); }
.answer-stars .on svg{ fill:var(--warn); }
.answers-star{ color:var(--warn); }
.answer-body{ margin:0; display:grid; gap:4px; }
.answer-body dt{ font-size:12px; font-weight:700; letter-spacing:.02em; color:var(--accent-1); margin-top:8px; }
.answer-body dd{ margin:0; display:flex; flex-wrap:wrap; gap:6px; }
.answer-body p{ margin:0; flex-basis:100%; white-space:pre-wrap; overflow-wrap:anywhere; }
.answers-likes{ display:flex; flex-wrap:wrap; gap:6px; margin-top:6px; }
.answers-left{ margin-top:16px; }
.answers-people{ list-style:none; margin:0; padding:0 4px 4px; display:grid; gap:6px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.answers-people .muted{ font-size:12.5px; }
@media (max-width: 480px){ .answer-meta{ justify-items:start; } }

/* Музыка: круглая кнопка в углу; пока играет — прыгают столбики. */
.survey-sound{
  position:fixed; right:16px; bottom:calc(16px + env(safe-area-inset-bottom)); z-index:60;
  width:48px; height:48px; border-radius:50%; display:grid; place-items:center; cursor:pointer;
  border:1px solid var(--border); background:var(--surface-strong); color:var(--accent-1);
  box-shadow: var(--shadow-soft), inset 0 1px 0 var(--sheen);
  backdrop-filter: blur(20px) saturate(180%); -webkit-backdrop-filter: blur(20px) saturate(180%);
  transition: transform 240ms var(--spring); -webkit-tap-highlight-color: transparent;
  animation: survey-pop 600ms var(--spring) 1.2s backwards;
}
.survey-sound:hover{ transform: scale(1.08); }
.survey-sound:active{ transform: scale(.92); }
.survey-sound:focus-visible{ outline:none; box-shadow: 0 0 0 4px var(--accent-tint); }
.survey-eq{ display:flex; align-items:flex-end; gap:3px; height:18px; }
.survey-eq i{ width:4px; height:100%; border-radius:2px; background:currentColor; transform-origin:bottom;
  animation: survey-eq 900ms ease-in-out infinite; }
.survey-eq i:nth-child(2){ animation-delay:-300ms; animation-duration:780ms; }
.survey-eq i:nth-child(3){ animation-delay:-600ms; animation-duration:1040ms; }
@keyframes survey-eq{ 0%,100%{ transform: scaleY(.3); } 50%{ transform: scaleY(1); } }
.survey-muted, .survey-note, .survey-sound-text, .survey-eq{ display:none; }
.survey-muted{ width:22px; height:22px; fill:currentColor; }
.survey-note{ width:20px; height:20px; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; }
.survey-note circle{ fill:currentColor; }
.survey-sound.is-playing .survey-eq{ display:flex; }
.survey-sound.is-muted{ color:var(--text-faint); }
.survey-sound.is-muted .survey-muted{ display:block; }
/* Браузер не дал звук без нажатия: не «выключено», а приглашение — кнопка
   с надписью и пульсом. Первое нажатие где угодно на странице включает. */
.survey-sound.is-waiting{
  width:auto; padding:0 18px 0 14px; border-radius:24px; display:flex; align-items:center; gap:8px;
  font:inherit; font-weight:600; font-size:14px; color:#fff;
  background: linear-gradient(145deg, var(--accent-fill-a), var(--accent-fill-b)); border-color:transparent;
  box-shadow: var(--shadow-accent);
  animation: survey-pop 600ms var(--spring) 1.2s backwards, survey-call 1.8s ease-in-out 1.8s infinite;
}
.survey-sound.is-waiting .survey-note, .survey-sound.is-waiting .survey-sound-text{ display:block; }
@keyframes survey-call{
  0%,100%{ box-shadow: var(--shadow-accent), 0 0 0 0 color-mix(in srgb, var(--accent-1) 45%, transparent); }
  50%{ box-shadow: var(--shadow-accent), 0 0 0 12px color-mix(in srgb, var(--accent-1) 0%, transparent); }
}

@media (max-width: 480px){
  .survey-wrap{ padding-top:78px; }
  .survey-card{ padding:32px 20px 26px; }
  .survey-card h1{ font-size:23px; }
  .survey-head h1{ font-size:21px; }
  .survey-q{ padding:16px; }
  .survey-q-head{ gap:10px; }
  .survey-stars svg{ width:36px; height:36px; }
}
@media (prefers-reduced-motion: reduce){
  .survey-wrap *, .survey-wrap *::before, .survey-wrap *::after,
  .survey-intro, .survey-thanks{ animation:none !important; transition:none !important; }
  .survey-q:focus-within{ transform:none; }
  .survey-float, .survey-particle{ display:none; }
  .survey-sound, .survey-eq i{ animation:none !important; }
}
