/* ===========================================================================
   TICK — design tokens and primitives.
   The single source of truth for colour, space, type, shape and motion.

   Both the room (index.html) and the win page (win.html) load this file, so the
   written rules in ../05-DESIGN-SYSTEM.md and the running product cannot drift
   apart. If a value is not here, it should not be in a page.

   Colours arrive from the server at runtime (cfg.brand.colors) and overwrite
   --bg/--surface/--line/--ink/--muted/--cold/--you/--gold. Everything below is
   derived from those six, so rebranding is one config edit.
   =========================================================================== */

:root {
  /* ---- palette: a cold room, and warmth only where it is earned ---------- */
  --bg:      #080B10;   /* the room */
  --surface: #0F141C;   /* panels sitting on it */
  --line:    #1B2430;   /* borders, dividers */
  --ink:     #E8EEF6;   /* primary text */
  --muted:   #6C7C90;   /* secondary text, labels */

  --cold: #4CC2FF;      /* everything ordinary: countdown, button, live state */
  --you:  #A855F7;      /* RESERVED. Means "you". Never decoration, never a link */
  --gold: #FFC24B;      /* money in motion. Only while it moves toward you */
  --ok:   #3FD68C;      /* a passed check. Only in the verifier */
  --bad:  #FF6B6B;      /* a failed check or a hard refusal */

  /* ---- space: a 4px grid. Only these values ------------------------------ */
  --s1: 4px;  --s2: 8px;   --s3: 12px; --s4: 16px;
  --s5: 20px; --s6: 26px;  --s7: 34px; --s8: 44px;

  /* ---- shape ------------------------------------------------------------- */
  --r-sm: 10px;   /* pills, small controls */
  --r:    14px;   /* buttons, the reel */
  --r-lg: 16px;   /* cards */
  --r-pill: 999px;

  /* ---- type: fluid, so one layout serves a 320px phone and a desktop panel */
  --f-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --f-ui: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, system-ui, sans-serif;

  --t-label: 11px;                              /* uppercase, tracked */
  --t-small: 12.5px;
  --t-body:  15px;
  --t-lead:  17px;                              /* reel names, button */
  --t-hero:  clamp(44px, 15vw, 64px);           /* countdown */
  --t-money: clamp(34px, 12.5vw, 52px);         /* the amount */

  /* ---- motion: durations are budget, not taste --------------------------- */
  --m-tap:    90ms;    /* press feedback */
  --m-fade:   180ms;   /* colour and opacity changes */
  --m-state:  250ms;   /* one element becoming another */
  --m-freeze: 300ms;   /* the still beat before the draw */
  --m-spin:   900ms;   /* the scramble */
  --m-win:    2100ms;  /* the whole win, start to gone */
  --e-out: cubic-bezier(.2, .8, .2, 1);         /* things arriving */
  --e-settle: cubic-bezier(.4, 0, .25, 1);      /* things landing */

  /* ---- the play column --------------------------------------------------- */
  --col: 330px;        /* max width of interactive content */
  --col-page: 360px;   /* max width of reading content */
}

/* ---------------------------------------------------------------------------
   Base. Every page starts here.
   --------------------------------------------------------------------------- */
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 var(--t-body)/1.45 var(--f-ui);
  font-synthesis-weight: none;
  /* Telegram's webview reports a stable viewport height that excludes its own
     chrome; fall back to dvh, then vh, so nothing is cut off on any host. */
  min-height: 100vh;
  min-height: 100dvh;
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
           env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* Numbers that change in place must not jitter. Every countdown, amount,
   ticket count and odds figure carries this. */
.num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

/* ---------------------------------------------------------------------------
   Primitives
   --------------------------------------------------------------------------- */

/* The brand lockup. Identical on every surface, so a shared card is recognisably
   the same product as the app. */
.brand { display: flex; align-items: center; gap: 9px; }
.brand .mark {
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--cold);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--cold) 14%, transparent);
}
.brand .mark.beat { animation: beat 1s ease-out infinite; }
.brand .name { font-size: 14px; font-weight: 700; letter-spacing: .16em; }
@keyframes beat {
  0%   { box-shadow: 0 0 0 3px color-mix(in srgb, var(--cold) 22%, transparent); }
  70%  { box-shadow: 0 0 0 10px color-mix(in srgb, var(--cold) 0%, transparent); }
  100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--cold) 0%, transparent); }
}

/* A label: uppercase, tracked, muted. Never larger than --t-label. */
.label {
  font-size: var(--t-label); letter-spacing: .22em;
  color: var(--muted); text-transform: uppercase;
}

/* The primary action. One per screen, 58px tall — comfortably above the 44px
   minimum, because it is tapped once every ten seconds. */
.btn {
  display: block; width: 100%; max-width: var(--col);
  height: 58px; border: 0; border-radius: var(--r);
  background: var(--cold); color: #04121C;
  font: 650 var(--t-lead)/1 var(--f-ui); letter-spacing: .02em;
  text-align: center; text-decoration: none;
  transition: transform var(--m-tap), background var(--m-fade),
              color var(--m-fade), opacity var(--m-fade);
}
.btn:active { transform: scale(.975); }
.btn[disabled] { opacity: .55; }
/* You are in: the button stops being an invitation and becomes a status. */
.btn[data-state="in"] {
  background: transparent; color: var(--you);
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--you) 55%, transparent);
}
/* Shut: not an error, just closed. Grey, never red. */
.btn[data-state="shut"] { background: var(--line); color: var(--muted); }

/* A pill: secondary, optional, never competes with .btn */
.pill {
  border: 0; border-radius: var(--r-pill); padding: 6px 13px;
  font: 650 11px/1 var(--f-ui); letter-spacing: .08em;
  background: color-mix(in srgb, var(--you) 18%, transparent);
  color: var(--you);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--you) 45%, transparent);
  transition: transform var(--m-tap);
}
.pill:active { transform: scale(.97); }

/* A panel. The only container shape in the product. */
.panel {
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface);
}

/* A bottom sheet. The only overlay in the product: everything that is not the
   game itself (wallet, claim, invite, stats) lives in one, so the room is never
   navigated away from and the next round is always three seconds away. */
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  padding: var(--s5) var(--s5) calc(var(--s6) + env(safe-area-inset-bottom));
  transform: translateY(101%);
  transition: transform var(--m-state) var(--e-out);
  max-height: 86vh; overflow-y: auto;
}
.sheet.open { transform: none; }
.sheet-grab {
  width: 36px; height: 4px; border-radius: var(--r-pill);
  background: var(--line); margin: 0 auto var(--s4);
}
.scrim {
  position: fixed; inset: 0; z-index: 19; background: rgba(0,0,0,.55);
  opacity: 0; pointer-events: none; transition: opacity var(--m-state);
}
.scrim.open { opacity: 1; pointer-events: auto; }

/* A text input. Rare — the game asks for exactly one thing, an address. */
.input {
  width: 100%; padding: 14px var(--s4); border-radius: var(--r);
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
  font: 400 14px/1.3 var(--f-mono); letter-spacing: 0;
}
.input:focus { outline: none; border-color: color-mix(in srgb, var(--cold) 55%, transparent); }
.input.bad { border-color: var(--bad); }

/* A key/value row, used for anything list-like. */
.row-kv {
  display: flex; justify-content: space-between; gap: var(--s3);
  padding: 9px 0; border-bottom: 1px solid var(--line);
  font-size: var(--t-small);
}
.row-kv > :first-child { color: var(--muted); }
.row-kv code { font-family: var(--f-mono); font-size: 11.5px; word-break: break-all; }

/* ---------------------------------------------------------------------------
   Motion policy.

   The room runs 8,640 draws a day. Anything delightful once is an obstacle by
   round forty, so: the loss path has no animation to sit through and no
   dismissal, and only the win is allowed to take time.

   prefers-reduced-motion is not a downgrade — it is a supported way to play.
   Results still arrive, they simply arrive without the journey.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001s !important;
  }
}

/* ---------------------------------------------------------------------------
   Responsive.

   One column, always. The app runs in a phone webview, in Telegram Desktop's
   narrow panel, and in a full browser tab, and it must not become a different
   product in any of them: content is capped at --col and centred, never
   stretched. Only two things flex — the two big numbers (via clamp) and the
   reel height on short screens.
   --------------------------------------------------------------------------- */

/* Short viewports: a small phone, or any phone with the keyboard up. Give back
   height by shrinking the reel first — it is decoration between draws, while
   the button and the countdown are the game. */
@media (max-height: 700px) {
  :root { --reel-row: 38px; }
}
@media (min-height: 701px) {
  :root { --reel-row: 44px; }
}

/* Desktop and tablet: the column stays a column. Widening it would spread three
   short lines across 900px and make a dense, live thing feel abandoned. */
@media (min-width: 700px) {
  :root { --col: 360px; --col-page: 400px; }
}
