/* Аралык — shared design tokens and components.
   One stylesheet for the public landing, the therapist cabinet, and the
   internal admin — three different audiences, one visual language, so the
   product reads as a single considered thing rather than three prototypes
   stitched together. Каждая страница подключает fonts.generated.css и
   этот файл первыми, затем добавляет только то, что специфично для неё.

   Formal language: paper, hairline rules, square corners, no shadows and
   no rounded cards. The page is a ruled sheet and a ledger of days, and
   the geometry borrows from both on purpose. Structure is carried by
   rules and typographic scale alone — .ruled rows instead of boxes, a
   .sheet of lined paper instead of a highlighted panel, a .rail instead
   of a stepper. Colour is scarce and always means something: blue is the
   client's side, green is the specialist's, amber marks the one thing on
   a screen that was flagged by a person. */

:root {
  /* Declare the palette's intent. Without this a browser treats an
     undeclared page as fair game for automatic darkening -- Chrome's Auto
     Dark Theme (on by default on Android) and extensions like Dark Reader
     repaint light backgrounds dark at paint time while leaving authored
     colours alone. The result on this design was the header: its paper
     background went near-black while the ink-filled CTA sitting on it stayed
     ink, so a black button sat on a black bar.

     This is not a dark theme and does not opt out of one: the product's
     surfaces, its three meanings and the contrast between them are chosen,
     and a machine re-mixing them produces combinations nobody checked. A
     real dark palette would be its own set of tokens, validated the same way
     the chart hues were -- not an inversion. Saying so is what makes that a
     deliberate decision rather than an accident. It also puts form controls,
     date pickers and scrollbars on the light rendering the rest of the page
     assumes.

     `only` is load-bearing: plain `light` states a preference, which a UA is
     free to override, while `only light` is the documented opt-out that
     stops automatic darkening. */
  color-scheme: only light;

  /* paper and ink */
  --paper: #e9edeb;
  --sheet: #f4f7f5;
  --ink: #17262b;
  --ink-soft: #4a585a;
  --ink-faint: #78878a;
  --rule: #c6d3d0;
  --rule-soft: #d8e1de;

  /* the three meanings. blue = client, green = specialist, amber = flagged
     by a human. nothing else on the product may introduce a fourth. */
  --client: #2e5a73;
  --client-soft: rgba(46, 90, 115, 0.09);
  --spec: #3d6552;
  --spec-soft: rgba(61, 101, 82, 0.1);
  --tab: #b8892f;
  --tab-soft: rgba(184, 137, 47, 0.13);

  /* dark ground, used only for the admin bar and the landing footer */
  --dark: #17262b;
  --dark-line: #33454a;
  --dark-ink: #b6c3c1;

  /* spacing: one scale, used everywhere, no ad-hoc pixel values */
  --sp-1: 8px;
  --sp-2: 16px;
  --sp-3: 24px;
  --sp-4: 40px;
  --sp-5: 64px;
  --sp-6: 96px;
  --sp-7: 140px;

  /* type: three roles, never mixed up. Spectral carries voice (headings,
     the wordmark, diary entries), Golos Text carries function (body,
     forms, tables), IBM Plex Mono carries labels and anything that is a
     coordinate rather than a sentence — a date, a key, a count. All three
     have real Cyrillic, self-hosted; none of them is a Latin face with
     Cyrillic bolted on. */
  --display: "Spectral", ui-serif, Georgia, "Times New Roman", serif;
  --body: "Golos Text", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;
  --track: 0.14em;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; }

body {
  font-family: var(--body);
  background: var(--paper);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}

a { color: inherit; }
h1, h2, h3 {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.15;
  margin: 0 0 var(--sp-1);
}
h1 { font-size: clamp(38px, 6.2vw, 68px); }
h2 { font-size: clamp(26px, 3.4vw, 38px); }
h3 { font-size: 20px; line-height: 1.3; }

:focus-visible { outline: 2px solid var(--client); outline-offset: 3px; }

/* --------------------------------------------------------------- wordmark ---
   The name set in the display face with the period picked out in amber:
   the interval has an end, and the mark says so. Latin lowercase for the
   logotype, Cyrillic everywhere else — the same convention the product
   already uses in its domain and its bot handles. */
.brand {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--display);
  font-size: 22px;
  letter-spacing: 0.02em;
  text-decoration: none;
  color: inherit;
}
.brand-dot { color: var(--tab); }

/* ------------------------------------------------------------------ text ---*/
.label {
  display: block;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: var(--sp-2);
}
.lede, .section-lede {
  color: var(--ink-soft);
  font-size: 16px;
  max-width: 62ch;
  margin: 0 0 var(--sp-3);
}
.pull {
  font-family: var(--display);
  font-size: clamp(21px, 2.6vw, 28px);
  font-weight: 300;
  line-height: 1.35;
  max-width: 26ch;
  margin: 0;
}
.empty {
  color: var(--ink-soft);
  font-size: 16px;
  padding: var(--sp-4) 0;
  border-top: 1px solid var(--rule);
}
code {
  font-family: var(--mono);
  background: var(--sheet);
  border: 1px solid var(--rule-soft);
  padding: 1px 6px;
  font-size: 13px;
  word-break: break-all;
}

/* ----------------------------------------------------------------- links ---*/
.nav-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  text-decoration: none;
  padding: 6px 10px;
  border: 1px solid transparent;
}
.nav-link:hover, .nav-link:focus-visible { color: var(--ink); border-color: var(--rule); }
.back-link {
  display: inline-block;
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--ink-soft);
  text-decoration: none;
  margin-bottom: var(--sp-3);
}
.back-link:hover { color: var(--ink); }

/* --------------------------------------------------------------- buttons ---
   Hierarchy by fill, not by colour count. .btn is the everyday action and
   stays quiet (a hairline box on paper) because tables are mostly made of
   them; .btn-primary is the one action a screen actually wants, filled
   with ink and turning client-blue on hover. Square, no radius: the same
   edge as every rule and panel on the page. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--body);
  font-size: 14.5px;
  font-weight: 500;
  padding: 9px 16px;
  cursor: pointer;
  text-decoration: none;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink);
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.btn:hover { border-color: var(--ink); }
.btn-primary {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--sheet);
}
.btn-primary:hover {
  background: var(--client);
  border-color: var(--client);
  color: var(--sheet);
}
.btn-quiet { border-color: transparent; color: var(--ink-soft); font-weight: 400; }
.btn-quiet:hover { border-color: var(--rule); color: var(--ink); }
form.inline { display: inline; }

/* ------------------------------------------------------------------ form ---*/
.field-group { display: flex; flex-direction: column; gap: 5px; }
.field-group label {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-soft);
}
input[type=text], input[type=search], input[type=email], input[type=password], input[type=number], input[type=date], select, textarea {
  font-family: var(--body);
  font-size: 15px;
  padding: 9px 11px;
  border: 1px solid var(--rule);
  background: var(--sheet);
  color: var(--ink);
}
textarea { width: 100%; resize: vertical; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--client); outline-offset: 1px; border-color: var(--client); }
input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--client); }
.form-row, .form-grid {
  display: flex;
  gap: var(--sp-2);
  align-items: flex-end;
  flex-wrap: wrap;
  margin: var(--sp-3) 0 var(--sp-4);
  padding: var(--sp-3);
  background: var(--sheet);
  border: 1px solid var(--rule);
}

/* ----------------------------------------------------------------- table ---*/
table { width: 100%; border-collapse: collapse; margin: var(--sp-1) 0 4px; }
th {
  text-align: left;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: var(--track);
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: 0 var(--sp-2) 10px 0;
  border-bottom: 1px solid var(--ink);
}
td {
  padding: 13px var(--sp-2) 13px 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: middle;
  font-size: 15px;
}
tbody tr:hover { background: var(--sheet); }
td:last-child, th:last-child { padding-right: 0; text-align: right; }
/* A link inside a table is the way into a record, so it keeps an underline
   — but a hairline one in the rule colour, so a column of them reads as a
   column of names rather than a stack of blue. */
td a { text-decoration: underline; text-decoration-color: var(--rule); text-underline-offset: 3px; }
td a:hover { text-decoration-color: var(--ink); }

/* A wide table scrolls inside its own box rather than dragging the whole
   page sideways on a narrow screen — the header, the headings and the page
   padding all stay put while only the columns move. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: var(--sp-1) 0 4px; }
.table-scroll table { margin: 0; min-width: 660px; }

/* ----------------------------------------------------------- ruled rows ---
   The replacement for cards. A key in mono on the left, prose on the
   right, separated by a hairline — a definition list drawn the way a
   ledger draws one. Used for feature lists, data promises, plan details:
   anywhere a card grid would otherwise appear. */
.ruled { border-top: 1px solid var(--rule); }
.row {
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: var(--sp-3);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
}
.row-key {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
}
.row-body h3 { margin-bottom: 6px; }
.row-body p { color: var(--ink-soft); font-size: 15.5px; margin: 0; }

/* --------------------------------------------------------------- badge ---*/
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  border: 1px solid var(--rule);
  color: var(--ink-soft);
}
.badge::before { content: ""; width: 5px; height: 5px; background: var(--ink-faint); flex-shrink: 0; }
.badge-active { color: var(--spec); border-color: var(--spec); }
.badge-active::before { background: var(--spec); }
.badge-attention { color: var(--tab); border-color: var(--tab); }
.badge-attention::before { background: var(--tab); }

/* ------------------------------------------------------- banner/message ---
   Both are a left rule and a tint, never a boxed alert: amber when a
   decision is waiting on the reader, green when something simply
   succeeded. .note is the same shape without a fill — a marginal remark,
   used for the medical disclaimer. */
.banner {
  padding: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-3);
  border-left: 2px solid var(--tab);
  background: var(--tab-soft);
  font-size: 15px;
}
.banner a { color: var(--tab); font-weight: 500; }
.message {
  padding: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-3);
  border-left: 2px solid var(--spec);
  background: var(--spec-soft);
  font-size: 15px;
}
.message a { color: var(--spec); font-weight: 500; }
.note {
  border-left: 2px solid var(--tab);
  padding-left: var(--sp-3);
  font-size: 15.5px;
  color: var(--ink-soft);
  margin: 0;
}

/* ------------------------------------------------------------- interval ---
   The product's one recurring picture: a span of days with marks where a
   record landed. The landing draws it as a rail across the hero; here it is
   one square per day on a client's row, the same idea at working scale, so
   a therapist who learns it once reads it in both places. Absence is drawn,
   not omitted: a quiet day is a hairline square, never a gap — the cabinet
   must never render a missed day as something the therapist did wrong. */
.activity-grid { display: flex; gap: 3px; }
.activity-day {
  width: 12px;
  height: 12px;
  border: 1px solid var(--rule);
  background: transparent;
  flex-shrink: 0;
}
.activity-day.on { background: var(--client); border-color: var(--client); }

/* ----------------------------------------------------------------- sheet ---
   Lined paper. The one texture in the system, reserved for verbatim words
   — the client's own entries — so that quoted text is visibly a different
   material from the interface describing it. */
.sheet-panel {
  background: var(--sheet);
  border: 1px solid var(--rule);
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  background-image: repeating-linear-gradient(
    to bottom, transparent, transparent 33px, var(--rule-soft) 33px, var(--rule-soft) 34px);
  background-position: 0 var(--sp-4);
}
.sheet-tab {
  display: inline-block;
  background: var(--tab);
  color: var(--sheet);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 3px 10px;
  margin-bottom: var(--sp-3);
}

/* ----------------------------------------------------------------- pager ---*/
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
  padding-top: var(--sp-2);
  border-top: 1px solid var(--rule);
}
.pager-page { font-family: var(--mono); font-size: 12px; color: var(--ink-soft); }

/* -------------------------------------------------------------- loading ---
   Three signals, driven by /static/busy.js: a hairline bar across the top
   while anything is on its way (shown only past ~150 ms, so quick answers
   don't flicker), a spinner in place of the label on the button that was
   pressed, and a dimmed region while a list or a period is being replaced.
   The pressed button also stops taking clicks -- a second "Оплатить" or
   "Войти" is exactly what a slow answer invites. */
.load-bar { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 100; overflow: hidden; pointer-events: none; opacity: 0; transition: opacity 0.2s; }
.load-bar::before { content: ""; position: absolute; top: 0; bottom: 0; left: -35%; width: 35%; background: var(--client); animation: load-slide 1.1s ease-in-out infinite; }
html.is-loading .load-bar { opacity: 1; }
@keyframes load-slide { to { left: 100%; } }

.btn.is-busy,
.btn.htmx-request,
form.htmx-request button.btn:not([type="button"]) { position: relative; color: transparent !important; pointer-events: none; transition: none; }
.btn.is-busy::after,
.btn.htmx-request::after,
form.htmx-request button.btn:not([type="button"])::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 15px; height: 15px; margin: -8px 0 0 -8px;
  border: 2px solid var(--ink); border-right-color: transparent; border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
.btn-primary.is-busy::after,
.btn-primary.htmx-request::after,
form.htmx-request button.btn-primary:not([type="button"])::after { border-color: var(--sheet); border-right-color: transparent; }
@keyframes spin { to { transform: rotate(360deg); } }

.is-updating { opacity: 0.5; pointer-events: none; transition: opacity 0.15s 0.12s; }

@media (max-width: 720px) {
  .row { grid-template-columns: 1fr; gap: 6px; }
  .sheet-panel { padding: var(--sp-3); background-position: 0 var(--sp-3); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
}
