/* =============================================================================
   ТУРБО / TOURBO — design tokens
   Art direction: Soviet-era SPORT poster (constructivism, screenprint, halftone).
   Everything below is a custom property. Screens and components MUST NOT
   redefine colour, type or spacing values — only consume these tokens.
   Texture is CSS-drawn. The one external asset is the display face, self-hosted
   below — see the @font-face block for why it stopped being optional.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   PT Sans Narrow — SELF-HOSTED, and it has to be.
   ParaType, SIL Open Font License 1.1 (fonts/OFL.txt). Google Fonts build v19,
   Cyrillic + Latin subsets, 400 and 700.

   This used to be a system-font stack, and that quietly broke the design on
   every device that is not a Mac. «PT Sans Narrow» ships with macOS, so Chrome
   there rendered the intended condensed face; Android has none of the first
   four families in the old chain and fell through to plain Roboto, ~30% wider
   at the same px size. «ПОДТВЕРЖДЕНА» in a status badge needed 124px of the
   99px it had, and `body { overflow-wrap: anywhere }` chopped the last letter
   onto its own line. Every letterspaced uppercase label had the same problem to
   a smaller degree.

   No `local()` on purpose: matching the SYSTEM copy would reintroduce exactly
   the per-platform metric differences this is here to remove. One file, one
   rendering, everywhere. A screen costs ~33KB (Cyrillic 700) — the subsets are
   fetched only as their unicode-range is used.
   ----------------------------------------------------------------------------- */
@font-face {
  font-family: "PT Sans Narrow";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/pt-sans-narrow-cyrillic-400.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "PT Sans Narrow";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/pt-sans-narrow-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "PT Sans Narrow";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/pt-sans-narrow-cyrillic-700.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "PT Sans Narrow";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/pt-sans-narrow-latin-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ---------------------------------------------------------------------------
     PALETTE — flat screenprint inks. Five plates, nothing else.
     Naming: --c-<ink>[-<variant>]. Never use a raw hex in a component.
     --------------------------------------------------------------------------- */
  --c-paper:        #F1E7D3; /* aged cream stock — app background                */
  --c-paper-2:      #E5D8BC; /* second paper tone — inset panels, striped bands  */
  --c-paper-3:      #D8C8A5; /* deepest paper — disabled fills, dividers on cream*/
  --c-ink:          #17130E; /* warm black plate — body text, bars, rules        */
  --c-ink-2:        #4A4034; /* ink at 70% — secondary copy (AA on paper: 7.4:1) */
  --c-ink-3:        #7A6C58; /* ink at 45% — meta copy only at >=14px (4.6:1)    */
  --c-red:          #C81E14; /* kumach — primary action, hero numerals, brand    */
  --c-red-deep:     #8E1009; /* red shadow plate / pressed state                 */
  --c-red-wash:     #F3D8CF; /* 12% red on paper — soft alert fills              */
  --c-ochre:        #E0A116; /* gold accent — packages, seals, warnings          */
  --c-ochre-deep:   #A6740A; /* ochre text weight (AA on paper: 4.6:1)           */
  --c-cyan:         #0E6E86; /* cold cyan — "in progress" / hold / processing    */
  --c-cyan-bright:  #1FA3C4; /* cyan on ink backgrounds only                     */
  --c-green:        #2E6B32; /* confirmed / paid — the only non-poster hue, dark */
  --c-white:        #FFFDF7; /* paper white — text on ink/red, knockout blocks   */

  /* Semantic aliases — components speak in these, not in ink names. */
  --c-bg:           var(--c-paper);
  --c-surface:      var(--c-white);
  --c-surface-alt:  var(--c-paper-2);
  --c-text:         var(--c-ink);
  --c-text-muted:   var(--c-ink-2);
  --c-text-meta:    var(--c-ink-3);
  --c-line:         var(--c-ink);        /* rules are always full-strength ink   */
  --c-line-soft:    var(--c-paper-3);    /* hairlines inside light panels        */
  --c-accent:       var(--c-red);
  --c-focus:        var(--c-cyan);

  /* State inks — booking + payment badges map their `tone` field onto these. */
  --tone-neutral:   var(--c-ink);
  --tone-positive:  var(--c-green);
  --tone-progress:  var(--c-cyan);
  --tone-warning:   var(--c-ochre-deep);
  --tone-danger:    var(--c-red);
  --tone-muted:     var(--c-ink-3);

  /* ---------------------------------------------------------------------------
     TYPE — ParaType superfamily. The DISPLAY face is self-hosted (see the
     @font-face block above): it carries the poster voice and the layout is cut
     to its widths, so it cannot be left to chance. The chain behind it is a
     last resort for a failed download, not a plan.
     --font-body / --font-mono are still system stacks: body copy and tabular
     numerals survive a substitution, letterspaced uppercase does not.
     --font-display: heavy condensed Cyrillic — headings, numbers, labels only.
     --font-body:    humanist sans — anything a member has to read as a sentence.
     --font-mono:    tabular ticket data — countdown, receipt, ids.
     --------------------------------------------------------------------------- */
  --font-display: "PT Sans Narrow", "Roboto Condensed", "Liberation Sans Narrow",
                  "Arial Narrow", "Helvetica Neue", system-ui, sans-serif;
  --font-body:    "PT Sans", "Helvetica Neue", system-ui, -apple-system,
                  "Segoe UI", Roboto, sans-serif;
  --font-mono:    "PT Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Scale — mobile-first, 390px base. Display sizes are poster-loud on purpose. */
  --fs-score:   64px; /* scoreboard hero numeral (free spots, countdown, price)  */
  --fs-score-l: 88px; /* single dominant number on a screen (hold countdown)     */
  --fs-d1:      40px; /* screen title in the header block                        */
  --fs-d2:      30px; /* section / day band title                               */
  --fs-h1:      24px; /* card title (session type)                               */
  --fs-h2:      19px; /* sub-heading, coach name                                 */
  --fs-body:    16px; /* body copy — never smaller for sentences                 */
  --fs-sm:      14px; /* dense meta lines                                        */
  --fs-xs:      12px; /* chips, badge text (uppercase display only)              */
  --fs-micro:   11px; /* rotated rail labels, tab captions                       */

  --lh-tight:   0.86; /* numerals — set as slabs, no leading                     */
  --lh-head:    0.98; /* condensed headings                                      */
  --lh-body:    1.45; /* readable paragraphs                                     */

  --ls-score:  -0.02em; /* tighten big numerals                                  */
  --ls-head:   -0.005em;
  --ls-label:   0.13em; /* letterspaced uppercase micro labels                   */

  --fw-body:    400;
  --fw-strong:  700;

  /* ---------------------------------------------------------------------------
     SPACE — 4px base grid. Poster margins grow with the viewport.
     --------------------------------------------------------------------------- */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-5:  20px;
  --sp-6:  24px;
  --sp-8:  32px;
  --sp-10: 40px;
  --sp-12: 48px;
  --sp-16: 64px;

  --gutter:      var(--sp-4);  /* horizontal page padding (grows on tablet)      */
  --shell-max:   430px;        /* content column cap — phone-first               */
  --tap-min:     44px;         /* minimum tap target, non-negotiable             */

  /* ---------------------------------------------------------------------------
     RULES — the poster's structural element. Weight carries meaning.
     --------------------------------------------------------------------------- */
  --rule-hair:  1px;  /* list dividers inside a panel                            */
  --rule:       2px;  /* default component border                                */
  --rule-thick: 4px;  /* card outline, emphasis under headings                   */
  --rule-heavy: 8px;  /* screen-level separators, day bands                      */

  /* RADII — a screenprint has none. Only seals and knobs are round. */
  --r-0:      0;
  --r-seal:   50%;
  --r-pill:   999px;

  /* PRINT MIS-REGISTRATION — the offset colour plate behind a block. */
  --misreg-x:  3px;
  --misreg-y:  3px;
  --misreg-c:  var(--c-red);

  /* Hard offset "shadow" (never blurred — flat plate only). */
  --plate:      var(--misreg-x) var(--misreg-y) 0 0 var(--c-ink);
  --plate-red:  var(--misreg-x) var(--misreg-y) 0 0 var(--c-red);
  --plate-cyan: var(--misreg-x) var(--misreg-y) 0 0 var(--c-cyan);

  /* DIAGONAL — one angle for the whole system, so cuts stay parallel. */
  --cut:      14px; /* size of the corner cut on bands and plaques              */
  --cut-deep: 26px;

  /* ---------------------------------------------------------------------------
     Z-INDEX — flat stack, documented so nothing invents a 9999.
     --------------------------------------------------------------------------- */
  --z-base:    0;
  --z-raised:  10;  /* stamps, seals, offset plates over cards                   */
  --z-sticky:  20;  /* app header, day band stickiness                           */
  --z-tabbar:  30;  /* bottom navigation                                         */
  --z-scrim:   40;  /* sheet backdrop                                            */
  --z-sheet:   50;  /* modal / bottom sheet                                      */
  --z-toast:   60;  /* notification row                                          */

  /* ---------------------------------------------------------------------------
     MOTION — mechanical, short, no easing that feels "soft".
     --------------------------------------------------------------------------- */
  --dur-fast:  110ms;
  --dur:       190ms;
  --dur-slow:  340ms;
  --ease-out:  cubic-bezier(0.2, 0.7, 0.3, 1);
  --ease-in:   cubic-bezier(0.7, 0, 0.9, 0.4);
  --ease-step: steps(3, end); /* press flicker, printing-machine feel            */

  /* TEXTURE knobs — consumed by .tex-* classes below. */
  --grain-alpha:    0.055; /* paper fibre strength                              */
  --halftone-size:  6px;   /* dot pitch                                         */
  --halftone-dot:   2.1px; /* dot radius at full tone                           */
}

/* Wider than a phone: grow the poster margins, keep the content column. */
@media (min-width: 600px) {
  :root {
    --gutter:    var(--sp-8);
    --shell-max: 560px;
    --cut:       18px;
    --cut-deep:  34px;
  }
}

/* =============================================================================
   TEXTURE RECIPES — reusable classes. Pure CSS (no data: URIs) so they survive
   a strict CSP. Apply to a container; they paint into ::before/::after and never
   intercept pointer events.
   ============================================================================= */

/* .tex-grain — aged paper fibre. Put on the page background or any large fill. */
.tex-grain { position: relative; isolation: isolate; }
.tex-grain::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  opacity: 1;
  /* Four incommensurate dot grids beat against each other into speckle —
     no repeating-radial rings, no data: URIs, no visible tiling. */
  background-image:
    radial-gradient(circle at 30% 40%, rgba(23,19,14,var(--grain-alpha)) 0 0.7px, transparent 0.8px),
    radial-gradient(circle at 70% 20%, rgba(23,19,14,calc(var(--grain-alpha) * 0.85)) 0 0.6px, transparent 0.7px),
    radial-gradient(circle at 20% 80%, rgba(142,16,9,calc(var(--grain-alpha) * 0.7)) 0 0.6px, transparent 0.7px),
    radial-gradient(circle at 85% 65%, rgba(23,19,14,calc(var(--grain-alpha) * 0.6)) 0 0.5px, transparent 0.6px),
    repeating-linear-gradient(101deg, rgba(23,19,14,0.012) 0 1px, transparent 1px 7px);
  background-size: 7px 7px, 11px 11px, 13px 13px, 17px 17px, auto;
}

/* .tex-halftone — screenprint dot field. Colour follows currentColor.
   Modifiers: --dense (tight pitch), --fade (dot ramp, use for duotone edges). */
.tex-halftone { position: relative; }
.tex-halftone::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(currentColor var(--halftone-dot), transparent calc(var(--halftone-dot) + 0.6px));
  background-size: var(--halftone-size) var(--halftone-size);
  background-position: 0 0;
  opacity: 0.85;
}
.tex-halftone--dense::after { --halftone-size: 4px; --halftone-dot: 1.5px; }
.tex-halftone--loose::after { --halftone-size: 9px; --halftone-dot: 2.6px; }
/* Ramp the dots out to the right — the classic duotone fade. */
.tex-halftone--fade::after {
  -webkit-mask-image: linear-gradient(90deg, #000 0%, rgba(0,0,0,0.35) 55%, transparent 100%);
          mask-image: linear-gradient(90deg, #000 0%, rgba(0,0,0,0.35) 55%, transparent 100%);
}
.tex-halftone--fade-up::after {
  -webkit-mask-image: linear-gradient(0deg, #000 0%, transparent 100%);
          mask-image: linear-gradient(0deg, #000 0%, transparent 100%);
}

/* .tex-stripe — diagonal barrier tape. Used for disabled / sold-out fills. */
.tex-stripe {
  background-image: repeating-linear-gradient(-45deg,
    rgba(23,19,14,0.14) 0 6px, transparent 6px 14px);
}

/* Reduced motion: kill every non-essential animation, keep the countdown text. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
