/* ============================================================
   PANJGOOSHEH brand system

   Fonts: Medium (headers) · Space Grotesk (body) · Space Mono (footer)
   Colors: Void Black #0d1212 · Plaster White #fffef3 · Yellow Beam #ffc60b (VIP only)
   ============================================================ */

/* One face per weight, on purpose. The Farsi faces further down share these
   family names at every exact weight (100–900) with a Persian-only
   unicode-range. The browser picks a face by weight first and only then
   by character, so a Latin face must exist at exactly the same weights or
   a Farsi face wins the weight match and Latin text falls through to the
   next font in the stack. Same weights → one combined font per weight. */
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 100; font-style: normal; font-display: swap; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 200; font-style: normal; font-display: swap; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 800; font-style: normal; font-display: swap; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Medium.otf') format('opentype'); font-weight: 900; font-style: normal; font-display: swap; }
@font-face {
  font-family: 'Space Grotesk';
  src: url('/static/fonts/SpaceGrotesk-Light.ttf') format('truetype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('/static/fonts/SpaceGrotesk-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('/static/fonts/SpaceGrotesk-Medium.ttf') format('truetype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('/static/fonts/SpaceGrotesk-SemiBold.ttf') format('truetype');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Space Grotesk';
  src: url('/static/fonts/SpaceGrotesk-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Space Mono';
  src: url('/static/fonts/SpaceMono-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Space Mono';
  src: url('/static/fonts/SpaceMono-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ---- Persian text everywhere: Darvish ---------------------------------
   Declared under the site's own family names, but only for Persian/Arabic
   code points (unicode-range). Any Farsi on any page renders in Darvish,
   while Latin keeps Space Grotesk / Medium / Space Mono. Every weight is
   mapped explicitly (Darvish has Regular, Medium and Bold): body text
   300-400 Regular, 500 Medium, 600+ Bold; the heavy display face always
   pairs with Darvish Bold. Nothing is left for the browser to fake-bold. */
/* Latin faces at the weights the files above don't cover (see the note on 'Medium'). */
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/SpaceGrotesk-Light.ttf') format('truetype'); font-weight: 100; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/SpaceGrotesk-Light.ttf') format('truetype'); font-weight: 200; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/SpaceGrotesk-Bold.ttf') format('truetype'); font-weight: 800; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/SpaceGrotesk-Bold.ttf') format('truetype'); font-weight: 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/SpaceMono-Regular.ttf') format('truetype'); font-weight: 100; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/SpaceMono-Regular.ttf') format('truetype'); font-weight: 200; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/SpaceMono-Regular.ttf') format('truetype'); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/SpaceMono-Regular.ttf') format('truetype'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/SpaceMono-Bold.ttf') format('truetype'); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/SpaceMono-Bold.ttf') format('truetype'); font-weight: 800; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/SpaceMono-Bold.ttf') format('truetype'); font-weight: 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 100; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 200; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 300; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 400; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Medium.woff2') format('woff2'); font-weight: 500; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 600; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 700; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 800; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Grotesk'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 900; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 100; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 200; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 300; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 400; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Medium.woff2') format('woff2'); font-weight: 500; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 600; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 700; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 800; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Space Mono'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 900; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 112%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 100; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 200; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 300; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 400; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 500; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 600; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 700; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 800; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'Medium'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 900; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 100; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 200; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 300; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 400; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 500; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 600; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 700; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 800; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }
@font-face { font-family: 'DJName'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 900; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9; size-adjust: 104%; }

/* ---- Farsi pages: Darvish draws the spaces too ----
   The faces above leave the space character to the Latin fonts, whose wide
   spaces (Space Mono, the display face) pull Persian words apart. These two
   families cover Persian plus the space and are put first in the display
   and label stacks on Farsi pages only (see :root[lang="fa"] below). Body
   text keeps Space Grotesk's space, which already reads right. */
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 100; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 200; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 300; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 400; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 500; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 600; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 700; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 800; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Display'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 900; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 104%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 100; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 200; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 300; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Regular.woff2') format('woff2'); font-weight: 400; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Medium.woff2') format('woff2'); font-weight: 500; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 600; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 700; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 800; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }
@font-face { font-family: 'Fa Text'; src: url('/static/fonts/Darvish-Bold.woff2') format('woff2'); font-weight: 900; font-display: swap; unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+066B-066C, U+06F0-06F9, U+0020, U+00A0; size-adjust: 112%; }

/* ---- Darvish Farsi ---- */
@font-face {
  font-family: 'Darvish';
  src: url('/static/fonts/Darvish-Regular.woff2') format('woff2');
  font-weight: 100 450;
  font-style: normal;
  font-display: swap;
  /* Farsi letters only: digits and Latin fall through to the English fonts. */
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F;
}
@font-face {
  font-family: 'Darvish';
  src: url('/static/fonts/Darvish-Medium.woff2') format('woff2');
  font-weight: 451 550;
  font-style: normal;
  font-display: swap;
  /* Farsi letters only: digits and Latin fall through to the English fonts. */
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F;
}
@font-face {
  font-family: 'Darvish';
  src: url('/static/fonts/Darvish-Bold.woff2') format('woff2');
  font-weight: 551 1000;
  font-style: normal;
  font-display: swap;
  /* Farsi letters only: digits and Latin fall through to the English fonts. */
  unicode-range: U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200F;
}

/* ============================================================
   Theme tokens

   Dark is the default and lives on :root. Light — "inverted paper" —
   swaps the same two brand colours: Plaster White becomes the ground,
   Void Black the ink.

   The resolved scheme is stamped onto <html data-theme> by the inline
   script in base.html before first paint, so there is never a flash and
   the light rules only ever need one selector. Without JS the site
   stays dark, which is the brand's default face.
   ============================================================ */

:root {
  color-scheme: dark;

  --bg: #0d1212;
  --bg-raise: #121818;
  /* Warm off-black used by the About tiles' gold-leaning panels. */
  --bg-warm: #1a1510;
  --card-bg: rgba(255, 254, 243, 0.022);
  --text: #fffef3;
  --text-dim: #c8c6b8;
  --muted: #8a887c;
  --faint: #3e4240;

  --line: rgba(255, 254, 243, 0.12);
  --line-soft: rgba(255, 254, 243, 0.06);
  --line-strong: rgba(255, 254, 243, 0.32);

  --vip: #ffc60b;
  --red: #ff5a4d;
  --green: #48d18a;
  --blue: #6f9dff;

  /* --ink is whatever reads on a --text-coloured fill, so the pairing
     `background: var(--text); color: var(--ink)` inverts with the theme. */
  --ink: #000;
  /* Recessed panel — darker than the page in dark, lighter in light. */
  --well: #000;
  /* Translucent surfaces that sit over content. */
  --scrim: rgba(0, 0, 0, 0.72);
  --scrim-solid: rgba(0, 0, 0, 0.95);
  --shadow: rgba(0, 0, 0, 0.45);

  /* Four graded washes for hover states and panel tints. Flat white at
     low alpha vanishes on paper, so these flip to ink in light mode. */
  --wash-1: rgba(255, 255, 255, 0.025);
  --wash-2: rgba(255, 255, 255, 0.042);
  --wash-3: rgba(255, 255, 255, 0.065);
  --wash-4: rgba(255, 255, 255, 0.1);

  /* The fixed background stack: ruled grid, grain, vignette. */
  --bg-rule: rgba(255, 255, 255, 0.028);
  --bg-grain-opacity: 0.16;
  --bg-vignette: rgba(0, 0, 0, 0.75);
  /* Read by bg.js for the canvas matrix. */
  --bg-canvas-ink: 255, 255, 255;
  /* The page ground as bare channels, so overlays can compose their own
     alpha: rgba(var(--ground-rgb), 0.55). Used by the scrims that sit on
     photographs — flyers, product shots — which have to darken in dark
     mode and lighten in light mode to keep --text legible on top. */
  --ground-rgb: 13, 18, 18;

  --radius: 0px;
  --font-display: 'Medium', 'Space Grotesk', sans-serif;
  --font-body: 'Space Grotesk', sans-serif;
  --font-mono: 'Space Mono', ui-monospace, monospace;
  --font-fa: 'Darvish', 'Space Grotesk', sans-serif;
  --font-fa-text: 'Fa Text', 'Space Grotesk', sans-serif;

  --gut: clamp(18px, 4vw, 56px);   /* page gutter */
  --nav-h: 64px;   /* the site header on a computer (chrome.css); phones have none */
}

/* ---------- Light — inverted paper ---------- */
:root[data-theme="light"] {
  color-scheme: light;

  --bg: #fffef3;
  --bg-raise: #f6f4e4;
  --bg-warm: #f5eeda;
  --card-bg: rgba(13, 18, 18, 0.022);
  --text: #0d1212;
  --text-dim: #39413f;
  /* --muted carries the small mono labels, and many of them sit on --well
     rather than on the page, so it is tuned against the darker of the two:
     5.1:1 on --well, 5.8:1 on --bg. */
  --muted: #5f6662;
  /* Decorative hairline tone, never load-bearing text — deliberately at
     about the same 1.9:1 as its Void Black counterpart. */
  --faint: #b6bab3;

  --line: rgba(13, 18, 18, 0.16);
  --line-soft: rgba(13, 18, 18, 0.08);
  --line-strong: rgba(13, 18, 18, 0.4);

  /* Yellow Beam is a signal colour, not a legible one on paper — it drops
     to roughly 1.5:1 against #fffef3. These are the darkest versions that
     still read as the same hue. Small solid marks (dots, bars) keep their
     punch because they carry no text. */
  --vip: #8a6400;
  --red: #c1352a;
  --green: #157245;
  --blue: #2f5fd0;

  --ink: #fffef3;
  --well: #f1efdf;
  --scrim: rgba(255, 254, 243, 0.78);
  --scrim-solid: rgba(255, 254, 243, 0.97);
  --shadow: rgba(13, 18, 18, 0.16);

  --wash-1: rgba(13, 18, 18, 0.035);
  --wash-2: rgba(13, 18, 18, 0.055);
  --wash-3: rgba(13, 18, 18, 0.08);
  --wash-4: rgba(13, 18, 18, 0.13);

  --bg-rule: rgba(13, 18, 18, 0.045);
  --bg-grain-opacity: 0.07;
  --bg-vignette: rgba(13, 18, 18, 0.1);
  --bg-canvas-ink: 13, 18, 18;
  --ground-rgb: 255, 254, 243;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

/* The UA's `[hidden] { display: none }` loses to any author `display`
   rule of equal specificity, so `el.hidden = true` silently fails on
   anything styled as grid/flex — event cards, story buttons. Restate it
   here so hiding by attribute works everywhere. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* clip, not hidden: "hidden" on both <html> and <body> makes the body its
     own scroller, and the sticky header then scrolls away with the page */
  overflow-x: hidden;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
}

.vip-badge,
.vip-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--vip);
  font-family: var(--font-mono);
  font-size: 0.56rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.vip-name { color: var(--vip); }
.is-vip .nav-profile-name,
.is-vip .account-name { color: var(--vip); }

a { color: inherit; text-decoration: none; }
main { flex: 1; position: relative; z-index: 1; }
/* main is its own stacking layer (z-index 1), so a popup inside a page sat
   under the header (90) and the bottom bar (97) whatever its own z-index.
   While one is open, the whole page is lifted above them. */
main:has([aria-modal="true"]:not([hidden]):not([aria-hidden="true"])) { z-index: 3000; }
::selection { background: var(--text); color: var(--ink); }

.container {
  max-width: 1440px;
  width: 100%;
  margin: 0 auto;
  padding: clamp(16px, 2.4vw, 32px) var(--gut) 0;
}
/* Pages that look better edge to edge (the home pages, The History) set
   {% block body_class %}pg-wide{% endblock %}. */
body.pg-wide main.container { max-width: none; padding-inline: max(var(--gut, 16px), 2.6vw); }

/* ---------- Backgrounds — canvas matrix + grain + vignette ---------- */
.bg-grid {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}
/* Fine ruled grid — the Swiss substrate under everything. */
.bg-rules {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--bg-rule) 1px, transparent 1px),
    linear-gradient(to bottom, var(--bg-rule) 1px, transparent 1px);
  background-size: 96px 96px;
  mask-image: radial-gradient(120% 90% at 50% 30%, #000 25%, transparent 85%);
  -webkit-mask-image: radial-gradient(120% 90% at 50% 30%, #000 25%, transparent 85%);
}
/* Film grain — 1 tiny inline SVG, no network cost. */
.bg-grain {
  position: fixed;
  inset: -50%;
  z-index: 0;
  pointer-events: none;
  opacity: var(--bg-grain-opacity);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}
/* The grain only shifts on a desktop with a mouse: on phones it holds still and
   covers just the screen, so the page never repaints a layer four screens big. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .bg-grain { animation: grain 6s steps(6) infinite; }
}
@media (hover: none), (pointer: coarse) { .bg-grain { inset: 0; } }
@keyframes grain {
  0%, 100% { transform: translate(0, 0); }
  16% { transform: translate(-3%, -4%); }
  33% { transform: translate(2%, -2%); }
  50% { transform: translate(-2%, 3%); }
  66% { transform: translate(3%, 2%); }
  83% { transform: translate(-1%, -3%); }
}
.bg-vignette {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(115% 80% at 50% 40%, transparent 40%, var(--bg-vignette) 100%);
}

/* The site header, the full menu and the bottom sheet live in chrome.css. */
@keyframes live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
/* nav.js marks endless animations that are off the screen; they wait there. */
.pnj-off, .pnj-off *, .pnj-off::before, .pnj-off::after { animation-play-state: paused !important; }

/* Painted as a mask fill so the mark follows data-theme (currentColor /
   --text), not the OS preference baked into logo.svg for favicons. */
.logo {
  display: block;
  width: 22px;
  height: 22px;
  background: var(--text);
  opacity: 0.95;
  mask: var(--mark) center / contain no-repeat;
  -webkit-mask: var(--mark) center / contain no-repeat;
  transition: none;
  filter: none;
}
/* Safety net for pages that still load logo.svg as an <img>. The file
   answers to prefers-color-scheme; when the member has overridden the
   theme those two disagree and the mark vanishes — invert closes the gap.
   Mask-based .logo spans above, and logo-ink.svg (QR), are untouched. */
@media (prefers-color-scheme: light) {
  :root[data-theme="dark"] img[src*="logo.svg"]:not(.keep-scheme) {
    filter: invert(1);
  }
}
@media (prefers-color-scheme: dark) {
  :root[data-theme="light"] img[src*="logo.svg"]:not(.keep-scheme) {
    filter: invert(1);
  }
}
.hide-mobile { display: none !important; }
@media (min-width: 900px) { .hide-mobile { display: inline-flex !important; } }

/* ---------- Chips — small square buttons (the menu, admin pages) ---------- */
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 18px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-dim);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 0.2s, color 0.2s, background 0.2s;
}
.chip:hover { border-color: var(--text); color: var(--text); background: var(--wash-2); }
.chip-admin { border-color: var(--line-strong); color: var(--text); }

/* ---------- Buttons — sharp, flat, tracked ---------- */
.btn {
  position: relative;
  padding: 14px 28px;
  border-radius: 0;
  border: 1px solid transparent;
  cursor: pointer;
  font-weight: 700;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-family: inherit;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  overflow: hidden;
}
.btn:disabled { opacity: 0.35; cursor: not-allowed; }
.btn.small { padding: 9px 16px; font-size: 0.64rem; }

/* Primary: white block that inverts on hover. */
.btn-gold, .btn-red {
  background: var(--text);
  color: var(--ink);
  border-color: var(--text);
}
.btn-gold:hover:not(:disabled), .btn-red:hover:not(:disabled) { background: transparent; color: var(--text); }

.btn-ghost { background: transparent; border-color: var(--line); color: var(--text-dim); }
.btn-ghost:hover:not(:disabled) { border-color: var(--text); color: var(--text); }

.btn-green { background: transparent; border-color: rgba(72, 209, 138, 0.45); color: var(--green); }
.btn-green:hover:not(:disabled) { background: rgba(72, 209, 138, 0.1); }
.btn-danger { background: transparent; border-color: rgba(255, 90, 77, 0.45); color: var(--red); }
.btn-danger:hover:not(:disabled) { background: rgba(255, 90, 77, 0.1); }
.btn-primary { background: var(--text); color: var(--ink); border-color: var(--text); }
.btn-primary:hover:not(:disabled) { background: transparent; color: var(--text); }
.full-width { width: 100%; text-align: center; }

/* ---------- Cards — hairline panels, no rounding, no glow ---------- */
.card {
  position: relative;
  background: var(--card-bg);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  padding: 26px;
  border-radius: 0;
  margin-bottom: 18px;
  transition: border-color 0.25s, background 0.25s;
}
.card:hover { border-color: var(--line-strong); }
/* Corner ticks — a quiet technical flourish on hover. */
.card.spot::before,
.card.spot::after {
  content: "";
  position: absolute;
  width: 9px; height: 9px;
  border-color: var(--text);
  border-style: solid;
  opacity: 0;
  transition: opacity 0.28s;
  pointer-events: none;
}
.card.spot::before { top: -1px; left: -1px; border-width: 1px 0 0 1px; }
.card.spot::after { bottom: -1px; right: -1px; border-width: 0 1px 1px 0; }
.card.spot:hover::before, .card.spot:hover::after { opacity: 1; }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; margin-top: 20px; }

.section-title {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 64px 0 4px;
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.26em;
  color: var(--muted);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.section-title .count { margin-left: auto; color: var(--faint); }

/* ---------- Forms ---------- */
input, select, textarea {
  background: var(--wash-1);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 13px 15px;
  border-radius: 0;
  margin-bottom: 14px;
  width: 100%;
  font-family: inherit;
  font-size: 0.92rem;
  transition: border-color 0.2s, background 0.2s;
}
input::placeholder, textarea::placeholder { color: var(--faint); }
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--text);
  background: var(--wash-2);
}
label {
  display: block;
  margin-bottom: 7px;
  color: var(--muted);
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
}

/* ---------- Typography ---------- */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.26em;
  color: var(--muted);
  margin-bottom: 18px;
}
.eyebrow::after { content: ""; flex: 1; max-width: 90px; height: 1px; background: var(--line); }

.page-title {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 9vw, 6.5rem);
  line-height: 0.9;
  letter-spacing: -0.035em;
  margin: 0 0 18px;
  text-align: start;
  text-transform: uppercase;
}
.page-title .icon { display: none; }
.page-sub {
  color: var(--text-dim);
  font-size: clamp(0.95rem, 1.6vw, 1.05rem);
  line-height: 1.65;
  margin-bottom: 34px;
  max-width: 58ch;
}
.muted { color: var(--muted); }

h1, h2, h3, h4 { letter-spacing: -0.02em; }

code {
  font-family: var(--font-mono);
  background: var(--wash-3);
  border-radius: 0;
  padding: 2px 7px;
  font-size: 0.88em;
}

/* Page header block used across member pages. */
.page-head {
  padding-bottom: 40px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--line);
}

/* Label-over-value chips under the page subtitle (Wallet, Shop, Music…).
   Without column flex the <em> label and number smash into one word. */
.head-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 34px;
  margin-top: 8px;
  min-width: 0;
}
.head-meta span {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--font-display);
  font-size: clamp(1rem, 3.5vw, 1.3rem);
  font-variant-numeric: tabular-nums;
  min-width: 0;
  max-width: 100%;
}
.head-meta em {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 0.58rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--muted);
}

/* ---------- Badges ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 0;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  border: 1px solid var(--line);
  color: var(--text-dim);
}
.badge.green { color: var(--green); border-color: rgba(72, 209, 138, 0.4); }
.badge.red { color: var(--red); border-color: rgba(255, 90, 77, 0.4); }
.badge.blue { color: var(--blue); border-color: rgba(111, 157, 255, 0.4); }
.badge.gold { color: var(--text); border-color: var(--line-strong); }

/* ---------- Codes / QR ---------- */
.code-row { display: flex; align-items: center; gap: 8px; margin: 14px 0 0; flex-wrap: wrap; }
.code-label {
  font-family: var(--font-mono);
  font-size: 0.58rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--muted);
  flex-basis: 100%;
}
.ticket-code {
  font-family: var(--font-mono);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  background: var(--wash-2);
  border: 1px dashed var(--line-strong);
  border-radius: 0;
  padding: 9px 14px;
  color: var(--text);
  user-select: all;
}
.copy-btn {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--text-dim);
  border-radius: 0;
  padding: 9px 14px;
  cursor: pointer;
  font-weight: 700;
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-family: inherit;
  transition: border-color 0.2s, color 0.2s;
}
.copy-btn:hover { border-color: var(--text); color: var(--text); }
/* Stays white in both themes — scanners need dark modules on a light
   quiet zone, so this one surface does not follow the palette. The
   hairline keeps it from dissolving into the paper background. */
.qr-box { position: relative; background: #fff; padding: 12px; width: fit-content; margin: 18px 0 4px; border: 1px solid var(--line-soft); }
/* The mark sits in a white keep-out square so it never eats QR modules
   the decoder needs; level H absorbs the rest. */
.qr-mark {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 21%; height: auto;
  /* No filter: the source is logo-ink.svg, which is Void Black by
     definition. logo.svg follows the viewer's colour scheme, so inverting
     it here would hand back a white mark on the white keep-out square
     whenever the device is in light mode. */
  padding: 5px; background: #fff;
}

/* ---------- Ticket ----------
   Body + tear-off stub, split by a real perforation with punched notches.
   `.is-torn` pulls the two halves apart — the door scanner plays it when a
   code is accepted. */
.tkt {
  display: grid;
  grid-template-columns: 1fr auto auto;
  /* A ticket that spans a desktop column stops reading as a ticket. */
  max-width: 640px;
  border: 1px solid var(--line);
  background: linear-gradient(135deg, var(--wash-2), var(--wash-1));
  position: relative;
  overflow: hidden;
}
.tkt-main { padding: 22px 24px; min-width: 0; }
.tkt-brand {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--font-mono); font-size: 0.58rem;
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--text);
  padding-bottom: 14px; border-bottom: 1px solid var(--line-soft); margin-bottom: 16px;
}
.tkt-brand img { height: 15px; opacity: 0.9; }
.tkt-serial { margin-left: auto; color: var(--muted); letter-spacing: 0.12em; }

.tkt-event {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 3vw, 1.6rem);
  line-height: 1.02; letter-spacing: -0.03em;
  text-transform: uppercase; margin: 0 0 18px;
}

.tkt-rows { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 14px 18px; margin: 0 0 18px; }
.tkt-rows dt { font-family: var(--font-mono); font-size: 0.52rem; text-transform: uppercase; letter-spacing: 0.2em; color: var(--muted); margin-bottom: 5px; }
.tkt-rows dd { margin: 0; font-size: 0.86rem; font-weight: 600; overflow-wrap: anywhere; }

/* Decorative barcode — texture, not data. The QR on the stub is the data. */
.tkt-strip { display: flex; align-items: flex-end; gap: 2px; height: 26px; opacity: 0.5; }
.tkt-strip span { flex: 1; background: var(--text); height: 100%; }
.tkt-strip span:nth-child(3n) { height: 62%; }
.tkt-strip span:nth-child(4n) { height: 84%; opacity: 0.6; }
.tkt-strip span:nth-child(5n) { height: 45%; }
.tkt-strip span:nth-child(7n) { flex: 2; }

/* Perforation */
.tkt-perf { position: relative; width: 1px; background-image: linear-gradient(to bottom, var(--line-strong) 50%, transparent 0); background-size: 1px 9px; }
.tkt-notch {
  position: absolute; left: 50%; width: 15px; height: 15px;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: 50%; transform: translate(-50%, -50%);
}
.tkt-notch.top { top: 0; }
.tkt-notch.bottom { top: 100%; }

/* Stub */
.tkt-stub {
  width: 172px; flex-shrink: 0;
  padding: 20px 18px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  background: var(--wash-1);
  text-align: center;
}
.tkt-stub .qr-box { margin: 0; padding: 9px; }
.tkt-code { font-family: var(--font-mono); font-size: 0.78rem; letter-spacing: 0.1em; background: none; padding: 0; color: var(--text); user-select: all; }
.tkt-copy {
  background: none; border: 1px solid var(--line); color: var(--muted);
  font-family: inherit; font-size: 0.54rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.16em; padding: 6px 12px; cursor: pointer;
  transition: border-color 0.2s, color 0.2s;
}
.tkt-copy:hover { border-color: var(--text); color: var(--text); }
.tkt-stub-label {
  font-family: var(--font-mono); font-size: 0.5rem;
  text-transform: uppercase; letter-spacing: 0.22em; color: var(--muted);
  margin-top: 2px;
}
.tkt-note { display: flex; flex-direction: column; align-items: center; gap: 12px; font-family: var(--font-mono); font-size: 0.56rem; text-transform: uppercase; letter-spacing: 0.16em; color: var(--muted); line-height: 1.7; }
.tkt-spin { width: 22px; height: 22px; border: 1px solid var(--line-strong); border-top-color: var(--text); border-radius: 50%; animation: tkt-spin 1.1s linear infinite; }
@keyframes tkt-spin { to { transform: rotate(360deg); } }
.tkt-await { width: 22px; height: 22px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--red); color: var(--red); font-size: 0.7rem; }
.tkt-badge-mark { width: 26px; opacity: 0.6; }

/* State accents */
.tkt-paid { border-left: 2px solid var(--green); }
.tkt-pending { border-left: 2px solid var(--text); }
.tkt-awaiting { border-left: 2px solid var(--red); }
.tkt-badge { border-left: 2px solid var(--line-strong); }

/* The tear */
.tkt.is-torn .tkt-main,
.tkt.is-torn .tkt-stub,
.tkt.is-torn .tkt-perf { transition: transform 0.75s cubic-bezier(0.34, 1.3, 0.5, 1), opacity 0.5s ease; }
.tkt.is-torn { overflow: visible; border-color: transparent; background: none; }
.tkt.is-torn .tkt-main { transform: translateX(-13px) rotate(-1.1deg); }
.tkt.is-torn .tkt-stub { transform: translateX(15px) rotate(2.2deg); }
.tkt.is-torn .tkt-perf { opacity: 0; }

@media (max-width: 560px) {
  .tkt { grid-template-columns: 1fr; }
  .tkt-perf { width: auto; height: 1px; background-image: linear-gradient(to right, var(--line-strong) 50%, transparent 0); background-size: 9px 1px; }
  .tkt-notch { left: 0; top: 50%; }
  .tkt-notch.bottom { left: 100%; top: 50%; }
  .tkt-stub { width: auto; }
  .tkt.is-torn .tkt-main { transform: translateY(-10px) rotate(-0.6deg); }
  .tkt.is-torn .tkt-stub { transform: translateY(12px) rotate(1.2deg); }
}

@media (prefers-reduced-motion: reduce) {
  .tkt.is-torn .tkt-main, .tkt.is-torn .tkt-stub { transform: none; }
  .tkt-spin { animation: none; }
}

/* Marks a state the page is actively watching for a change. */
.live-dot {
  display: inline-block; width: 6px; height: 6px; margin-right: 7px;
  background: var(--text); vertical-align: middle;
  animation: live-pulse 1.8s ease-in-out infinite;
}

/* ---------- Stats ---------- */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  border: 1px solid var(--line);
  margin-bottom: 26px;
}
.stat {
  padding: 18px 16px;
  border-left: 1px solid var(--line);
  text-align: start;
  min-width: 0;           /* let the grid shrink cells instead of blowing out */
  overflow: hidden;
}
.stat:first-child { border-left: none; }
.stat .num {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 4.2vw, 1.9rem);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.stat .lbl {
  font-family: var(--font-mono);
  font-size: 0.56rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  margin-top: 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Money / IDs / long labels — never push a card wider than its column. */
.fit-num,
.wal-num,
.hub-bal-amount,
.hub-tx-amt,
.hub-order-amt,
.wal-order-amt,
.wal-row-amt {
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
  word-break: break-word;
  min-width: 0;
}
.page-title,
.hub-next-title,
.next-title,
.tier-name {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* ---------- Sticky player ----------
   Floating glass strip above the bottom nav (mobile) / page edge (desktop).
   On phones it only rises while audio is actually playing, so idle sessions
   keep the full viewport. */
:root { --player-h: 0px; --bnav-h: 0px; }

.pl {
  position: fixed;
  left: 10px; right: 10px;
  bottom: calc(var(--bnav-h) + 10px);
  z-index: 96;
  overflow: hidden;
  background: color-mix(in srgb, var(--bg) 52%, transparent);
  backdrop-filter: blur(22px) saturate(1.35);
  -webkit-backdrop-filter: blur(22px) saturate(1.35);
  border: 1px solid var(--line);
  box-shadow:
    0 12px 40px var(--shadow),
    inset 0 1px 0 color-mix(in srgb, var(--text) 8%, transparent);
  transform: translateY(calc(100% + 24px));
  transition:
    transform 0.45s cubic-bezier(0.22, 1, 0.36, 1),
    border-color 0.3s,
    box-shadow 0.3s;
}
.pl.open { transform: none; }
.pl.is-playing {
  border-color: color-mix(in srgb, var(--vip) 28%, var(--line));
  box-shadow:
    0 14px 44px var(--shadow),
    0 0 0 1px color-mix(in srgb, var(--vip) 10%, transparent),
    inset 0 1px 0 color-mix(in srgb, var(--text) 10%, transparent);
}

/* Ambient bars under the glass — sit behind the controls. */
.pl-viz {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 28px;
  display: flex;
  align-items: flex-end;
  justify-content: stretch;
  gap: 2px;
  padding: 0 8px 2px;
  opacity: 0.22;
  pointer-events: none;
  z-index: 0;
  mask-image: linear-gradient(to top, #000 20%, transparent 100%);
  -webkit-mask-image: linear-gradient(to top, #000 20%, transparent 100%);
}
.pl-viz i {
  flex: 1;
  min-width: 0;
  height: 20%;
  background: var(--text);
  transform-origin: bottom center;
  animation: pl-viz-idle 2.8s ease-in-out infinite;
}
.pl.is-playing .pl-viz { opacity: 0.38; }
.pl.is-playing .pl-viz i {
  background: var(--vip);
  animation-name: pl-viz-beat;
  animation-duration: 0.85s;
}
.pl-viz i:nth-child(3n)   { animation-delay: -0.15s; height: 35%; }
.pl-viz i:nth-child(3n+1) { animation-delay: -0.4s;  height: 55%; }
.pl-viz i:nth-child(3n+2) { animation-delay: -0.65s; height: 25%; }
.pl-viz i:nth-child(5n)   { animation-delay: -0.28s; }
.pl-viz i:nth-child(7n)   { animation-delay: -0.52s; }
@keyframes pl-viz-idle {
  0%, 100% { transform: scaleY(0.35); opacity: 0.5; }
  50%      { transform: scaleY(0.7);  opacity: 0.85; }
}
@keyframes pl-viz-beat {
  0%, 100% { transform: scaleY(0.3); }
  35%      { transform: scaleY(1); }
  60%      { transform: scaleY(0.55); }
}

.pl-seek {
  position: relative;
  height: 2px;
  background: var(--line-soft);
  cursor: pointer;
  z-index: 1;
}
.pl-seek:hover { height: 4px; }
.pl-seek-fill {
  height: 100%; width: 0;
  background: linear-gradient(90deg, var(--vip), var(--text));
  pointer-events: none;
}
.pl-seek-head {
  position: absolute; top: 50%; left: 0; width: 8px; height: 8px;
  background: var(--text); transform: translate(-50%, -50%) scale(0);
  transition: transform 0.2s; pointer-events: none;
}
.pl-seek:hover .pl-seek-head { transform: translate(-50%, -50%) scale(1); }
/* A stream has no scrub position to show. */
.pl.is-live .pl-seek { pointer-events: none; }
.pl.is-live .pl-seek-fill { width: 100%; opacity: 0.2; background: var(--vip); }

.pl-body {
  position: relative;
  z-index: 1;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 16px;
  padding: 10px 14px;
  max-width: 1440px; margin: 0 auto;
}
.pl-now {
  display: flex; align-items: center; gap: 12px; min-width: 0;
  background: none; border: none; color: inherit; font: inherit; text-align: start;
  cursor: pointer; padding: 0;
}
.pl-art {
  position: relative; width: 36px; height: 36px; flex-shrink: 0;
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg) 40%, transparent);
  display: flex; align-items: center; justify-content: center;
}
.pl-art-mark {
  display: block; width: 18px; height: 18px; opacity: 0.9;
  background: var(--text);
  mask: var(--mark) center / contain no-repeat;
  -webkit-mask: var(--mark) center / contain no-repeat;
}
.pl-eq { position: absolute; inset: 0; display: none; align-items: flex-end; justify-content: center; gap: 2px; padding: 8px; }
.pl.is-playing .pl-eq { display: flex; }
.pl.is-playing .pl-art-mark { opacity: 0.12; }
.pl-eq i { width: 2px; background: var(--vip); animation: eq 0.9s ease-in-out infinite; }
.pl-eq i:nth-child(1) { height: 40%; animation-delay: -0.1s; }
.pl-eq i:nth-child(2) { height: 85%; animation-delay: -0.4s; }
.pl-eq i:nth-child(3) { height: 55%; animation-delay: -0.7s; }
.pl-eq i:nth-child(4) { height: 70%; animation-delay: -0.25s; }
@keyframes eq { 0%, 100% { transform: scaleY(0.35); } 50% { transform: scaleY(1); } }

.pl-meta { min-width: 0; }
.pl-title { font-weight: 700; font-size: 0.84rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-artist { font-family: var(--font-mono); font-size: 0.5rem; text-transform: uppercase; letter-spacing: 0.16em; color: var(--muted); margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.pl-controls { display: flex; align-items: center; gap: 4px; }
.pl-btn {
  width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
  background: none; border: 1px solid transparent; color: var(--text-dim);
  cursor: pointer; transition: color 0.2s, border-color 0.2s, background 0.2s;
}
.pl-btn:hover { color: var(--text); }
.pl-main {
  border-color: color-mix(in srgb, var(--text) 35%, transparent);
  background: color-mix(in srgb, var(--text) 92%, transparent);
  color: var(--ink);
  width: 40px; height: 40px;
}
.pl-main:hover { background: transparent; color: var(--text); border-color: var(--text); }
.i-pause, .pl .i-off, .pb .i-off { display: none; }
.pl.is-playing .i-play, .pb.is-playing .i-play { display: none; }
.pl.is-playing .i-pause, .pb.is-playing .i-pause { display: flex; }
.pl.is-muted .i-on, .pb.is-muted .i-on { display: none; }
.pl.is-muted .i-off, .pb.is-muted .i-off { display: flex; }

.pl-right { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.pl-time { font-family: var(--font-mono); font-size: 0.54rem; letter-spacing: 0.1em; color: var(--muted); white-space: nowrap; }
.pl-time b { color: var(--text); font-weight: 400; }
.pl-time i { font-style: normal; }
.pl-live { font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.2em; color: var(--red); white-space: nowrap; }
.pl-vol-range { width: 80px; margin: 0; padding: 0; background: none; border: none; accent-color: var(--text); }

/* ---------- Player-Black fullscreen ---------- */
.pb {
  position: fixed; inset: 0; z-index: 200;
  display: grid;
  grid-template-columns: 1fr minmax(240px, 320px);
  grid-template-rows: auto 1fr;
  background: var(--bg);
  color: var(--text);
  opacity: 0; pointer-events: none;
  transition: opacity 0.35s ease;
}
.pb.open { opacity: 1; pointer-events: auto; }
.pb[hidden] { display: none !important; }
body.pb-open { overflow: hidden; }

.pb-bg {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(80% 60% at 30% 20%, var(--wash-3), transparent 60%),
    radial-gradient(70% 50% at 80% 80%, rgba(255,198,11,0.04), transparent 55%),
    var(--bg);
  transition: opacity 0.5s;
}
.pb.open .pb-bg {
  animation: pbHue 14s ease-in-out infinite alternate;
}
@keyframes pbHue {
  from { filter: hue-rotate(0deg); }
  to { filter: hue-rotate(18deg); }
}
.pb-viz {
  position: absolute; left: 0; right: 320px; bottom: 0; height: 40%;
  z-index: 1; width: calc(100% - 320px); pointer-events: none; opacity: 0.85;
  transition: opacity 0.4s ease;
}

/* Pages wrapper: on wide screens this is just a transparent passthrough —
   .pb-page-now / .pb-page-viz / .pb-page-queue take the same grid cells the
   unwrapped elements used to occupy. Below 860px it becomes a horizontal,
   swipeable, scroll-snapped strip (see the max-width media query). */
.pb-pages { display: contents; }
.pb-page-now {
  position: relative; grid-column: 1; grid-row: 2; min-height: 0;
}
.pb-page-viz {
  position: relative; grid-column: 1; grid-row: 2; min-height: 0;
  pointer-events: none;
}
.pb-page-viz > * { pointer-events: auto; }
.pb-viz-label { display: none; }
.pb-page-viz .pb-viz-bar {
  position: absolute; left: 50%; bottom: 28px; transform: translateX(-50%);
}
.pb-page-queue {
  grid-column: 2; grid-row: 2; min-height: 0; display: flex;
}
.pb-page-queue .pb-queue { flex: 1; min-height: 0; }

.pb-dots { display: none; }

.pb-top {
  position: relative; z-index: 2;
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 16px;
  padding: 18px var(--gut);
  border-bottom: 1px solid var(--line);
}
.pb-brand {
  font-family: var(--font-display);
  font-size: 1.05rem; letter-spacing: 0.04em; text-transform: uppercase;
}
.pb-mode {
  margin-left: auto;
  font-family: var(--font-mono); font-size: 0.56rem;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted);
}
.pb-stage {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 28px; padding: 40px var(--gut) 60px; text-align: center;
}
.pb-mark {
  position: relative; width: min(42vw, 220px); height: min(42vw, 220px);
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
}
.pb-mark-glyph {
  display: block; width: 42%; height: 42%; opacity: 0.9; transition: opacity 0.3s;
  background: var(--text);
  mask: var(--mark) center / contain no-repeat;
  -webkit-mask: var(--mark) center / contain no-repeat;
}
.pb-eq { position: absolute; inset: 18%; display: none; align-items: flex-end; justify-content: center; gap: 5px; }
.pb.is-playing .pb-eq { display: flex; }
.pb.is-playing .pb-mark-glyph { opacity: 0.1; }
.pb-eq i { width: 4px; background: var(--text); animation: eq 0.9s ease-in-out infinite; }
.pb-eq i:nth-child(1) { height: 35%; animation-delay: -0.1s; }
.pb-eq i:nth-child(2) { height: 70%; animation-delay: -0.35s; }
.pb-eq i:nth-child(3) { height: 95%; animation-delay: -0.55s; }
.pb-eq i:nth-child(4) { height: 55%; animation-delay: -0.2s; }
.pb-eq i:nth-child(5) { height: 80%; animation-delay: -0.7s; }

.pb-meta { max-width: 36rem; }
.pb-live { font-family: var(--font-mono); font-size: 0.6rem; letter-spacing: 0.22em; color: var(--red); margin-bottom: 10px; }
.pb-title {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 5vw, 3.4rem);
  letter-spacing: -0.03em; line-height: 1.05; margin: 0 0 12px;
  text-transform: uppercase;
}
.pb-artist {
  font-family: var(--font-mono); font-size: 0.72rem;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted); margin: 0;
}
.pb-seek-wrap { width: min(520px, 100%); }
.pb-seek { height: 6px; }
.pb-times {
  display: flex; justify-content: space-between; margin-top: 10px;
  font-family: var(--font-mono); font-size: 0.58rem; letter-spacing: 0.12em; color: var(--muted);
}
.pb-controls { display: flex; align-items: center; gap: 14px; }
.pb-main { width: 64px; height: 64px; }
.pb-controls .pl-btn.on { color: var(--text); border-color: var(--line-strong); }
.pb-vol-row { display: flex; align-items: center; gap: 12px; width: min(360px, 100%); }
.pb-vol { flex: 1; width: auto; }
.pb-sleep {
  background: transparent; border: 1px solid var(--line); color: var(--muted);
  font-family: var(--font-mono); font-size: 0.52rem; letter-spacing: 0.12em;
  text-transform: uppercase; padding: 8px 10px; cursor: pointer;
  transition: color 0.2s, border-color 0.2s, background 0.2s;
}
.pb-sleep:hover { color: var(--text); border-color: var(--line-strong); }
.pb-sleep:focus { outline: 1px solid var(--line-strong); color: var(--text); }
.pb-sleep.on {
  color: var(--bg); background: var(--text); border-color: var(--text);
}

.pb-viz-bar {
  display: flex; flex-wrap: wrap; gap: 14px 22px; justify-content: center;
  width: min(560px, 100%); margin-top: 4px;
}
.pb-viz-group { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.pb-chip {
  background: none; border: 1px solid var(--line); color: var(--muted);
  font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.14em;
  text-transform: uppercase; padding: 8px 11px; cursor: pointer;
  transition: color 0.2s, border-color 0.2s, background 0.2s, transform 0.2s;
}
.pb-chip:hover { color: var(--text); border-color: var(--line-strong); }
.pb-chip.on {
  color: var(--bg); background: var(--pb-viz, var(--text)); border-color: var(--pb-viz, var(--text));
}
.pb-swatch {
  width: 22px; height: 22px; border: 1px solid var(--line); cursor: pointer;
  background: var(--sw); padding: 0; transition: transform 0.2s, box-shadow 0.2s;
}
.pb-swatch:hover { transform: scale(1.08); }
.pb-swatch.on { box-shadow: 0 0 0 2px var(--bg), 0 0 0 3px var(--sw); }

.pb-title.pb-pop { animation: pbPop 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
@keyframes pbPop {
  from { opacity: 0; transform: translateY(12px); filter: blur(4px); }
  to { opacity: 1; transform: none; filter: none; }
}
.pb.is-playing .pb-mark {
  animation: pbPulse 2.8s ease-in-out infinite;
}
@keyframes pbPulse {
  0%, 100% { transform: scale(1); border-color: var(--line); }
  50% { transform: scale(1.03); border-color: var(--pb-viz, var(--line-strong)); }
}

.pb-queue {
  position: relative; z-index: 2;
  border-left: 1px solid var(--line);
  display: flex; flex-direction: column;
  background: var(--scrim-solid);
  overflow: hidden;
}
.pb-q-tabs { display: flex; border-bottom: 1px solid var(--line); }
.pb-q-tab {
  flex: 1; padding: 14px 10px; background: none; border: none;
  color: var(--muted); cursor: pointer; font-family: var(--font-mono);
  font-size: 0.56rem; letter-spacing: 0.18em; text-transform: uppercase;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.pb-q-tab .c {
  font-size: 0.5rem; opacity: 0.7; min-width: 1.2em;
}
.pb-q-tab.on { color: var(--text); box-shadow: inset 0 -2px 0 var(--text); }
.pb-filters {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 12px;
  border-bottom: 1px solid var(--line-soft);
}
.pb-filters .pb-chip { padding: 6px 9px; }
.pb-q-list { overflow-y: auto; flex: 1; padding: 8px 0; }
.pb-q-item {
  display: grid; grid-template-columns: 36px 1fr auto; gap: 2px 10px;
  width: 100%; padding: 12px 16px; background: none; border: none;
  color: inherit; text-align: start; cursor: pointer; font: inherit;
  transition: background 0.2s, transform 0.2s;
}
.pb-q-item:hover { background: var(--wash-2); }
.pb-q-item.on { background: var(--wash-3); }
.pb-q-item .n { grid-row: span 2; font-family: var(--font-mono); font-size: 0.58rem; color: var(--muted); align-self: center; }
.pb-q-item .t { font-size: 0.88rem; font-weight: 600; grid-column: 2; }
.pb-q-item .a { font-family: var(--font-mono); font-size: 0.52rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); grid-column: 2; }
.pb-q-item .tag {
  grid-row: span 2; align-self: center;
  font-family: var(--font-mono); font-size: 0.48rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--muted); border: 1px solid var(--line); padding: 4px 6px;
}
.pb-q-item.playing .n { color: var(--pb-viz, var(--text)); }
.pb-q-empty { padding: 24px 16px; color: var(--muted); font-size: 0.85rem; line-height: 1.6; }
.pb-q-empty a { color: var(--text); border-bottom: 1px solid var(--line); }
.pb.is-live .pb-seek { pointer-events: none; }
.pb.is-live .pb-seek .pl-seek-fill { width: 100%; opacity: 0.16; }

@media (max-width: 860px) {
  .pb {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr auto;
    height: 100dvh;
  }

  /* Canvas becomes a full-bleed backdrop behind every page — dim by
     default, and turned up bright by JS while the Visuals page is active. */
  .pb-viz { left: 0; right: 0; width: 100%; height: 100%; opacity: 0.28; }
  .pb.pb-viz-active .pb-viz { opacity: 0.95; }

  /* The three pages become a horizontal, snap-scrolling strip. */
  .pb-pages {
    display: flex;
    grid-column: 1; grid-row: 2;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none; min-height: 0;
  }
  .pb-pages::-webkit-scrollbar { display: none; }

  .pb-page-now, .pb-page-viz, .pb-page-queue {
    grid-column: auto; grid-row: auto;
    flex: 0 0 100%; width: 100%; min-height: 0;
    scroll-snap-align: start; scroll-snap-stop: always;
    display: flex; flex-direction: column;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    opacity: 0.45; transform: scale(0.96);
    transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  }
  .pb-page.in-view, .pb-page-now.in-view, .pb-page-viz.in-view, .pb-page-queue.in-view {
    opacity: 1; transform: none;
  }

  .pb-page-now {
    justify-content: center; align-items: center;
    padding: 6px var(--gut) 22px;
  }
  .pb-stage { padding: 0; gap: 20px; width: 100%; }
  .pb-mark { width: min(56vw, 260px); height: min(56vw, 260px); }

  .pb-page-viz {
    pointer-events: auto;
    justify-content: space-between; align-items: center;
    padding: 20px var(--gut) calc(28px + env(safe-area-inset-bottom, 0px));
  }
  .pb-viz-label {
    display: block; width: 100%; text-align: center;
    font-family: var(--font-mono); font-size: 0.6rem;
    letter-spacing: 0.28em; text-transform: uppercase; color: var(--muted);
    padding-top: 6px;
  }
  .pb-page-viz .pb-viz-bar { position: static; transform: none; }

  .pb-page-queue { padding: 0; }
  .pb-queue {
    border-left: none; border-top: none; background: var(--bg);
    width: 100%; flex: 1;
  }

  /* Page dots */
  .pb-dots {
    grid-column: 1; grid-row: 3;
    display: flex; justify-content: center; align-items: center; gap: 9px;
    padding: 14px 0 calc(14px + env(safe-area-inset-bottom, 0px));
    position: relative; z-index: 2;
  }
  .pb-dot {
    width: 6px; height: 6px; border-radius: 50%; padding: 0; border: none;
    background: var(--line-strong); cursor: pointer;
    transition: width 0.3s cubic-bezier(0.22, 1, 0.36, 1), background 0.3s;
  }
  .pb-dot.on { width: 22px; border-radius: 3px; background: var(--text); }

  /* One-time swipe hint on the now-playing page. */
  .pb-page-now::after {
    content: '‹ swipe for visuals & queue ›';
    position: absolute; bottom: 4px; left: 0; right: 0; text-align: center;
    font-family: var(--font-mono); font-size: 0.5rem; letter-spacing: 0.14em;
    text-transform: uppercase; color: var(--muted); opacity: 0;
    animation: pbSwipeHint 4s ease 1.2s 2;
    pointer-events: none;
  }
  .pb.pb-swiped .pb-page-now::after { display: none; }
  @keyframes pbSwipeHint {
    0%, 100% { opacity: 0; transform: translateY(2px); }
    15%, 40% { opacity: 0.8; transform: translateY(0); }
  }
}
@media (max-width: 860px) and (prefers-reduced-motion: reduce) {
  .pb-page-now, .pb-page-viz, .pb-page-queue { transition: none; opacity: 1; transform: none; }
  .pb-page-now::after { animation: none; display: none; }
}

/* ---------- Bottom nav — mobile and the Telegram mini app ---------- */
.bnav {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 97;
  display: none;
  align-items: stretch;
  background: var(--scrim-solid);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-top: 1px solid var(--line);
  /* Clear the iOS home indicator and Telegram's own bottom chrome. */
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.bnav-i {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  padding: 10px 4px;
  background: none; border: none; cursor: pointer;
  font-family: inherit; color: var(--muted);
  transition: color 0.2s;
}
.bnav-i span {
  font-family: var(--font-mono); font-size: 0.5rem;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.bnav-i:hover, .bnav-i.on { color: var(--text); }
.bnav-i.on { box-shadow: inset 0 2px 0 var(--text); }

/* The mark, raised out of the bar and centred. */
/* No plate behind it any more: the bare mark, coloured exactly like the
   icons either side, so the bar reads as one row of five glyphs rather
   than a white tile with navigation around it. */
.bnav-mark {
  position: relative;
  flex: 0 0 auto;
  width: 54px; height: 54px;
  margin: -8px 6px 0;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; cursor: pointer;
  color: var(--muted);
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), color 0.2s;
}
/* The mark is painted as a mask fill, which is what lets it inherit
   `currentColor` and follow the theme without a second asset. */
.bnav-mark-glyph {
  display: block;
  /* Sibling icons are 19px; 6% larger would be invisible at that scale, so
     the mark sits ~58% above them (30px) — same muted colour, more presence. */
  width: 30px; height: 30px;
  background: currentColor;
  mask: var(--mark) center / contain no-repeat;
  -webkit-mask: var(--mark) center / contain no-repeat;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.bnav-mark:hover, .bnav-mark.on { color: var(--text); }
.bnav-mark.on { filter: drop-shadow(0 0 10px var(--wash-4)); }
.bnav-mark:active { transform: scale(0.94); }

/* Locked, for visitors who have not been approved. Deliberately still
   visible and still the same shape — it is a door, not an absence. */
.bnav-mark.is-locked {
  color: var(--faint);
  cursor: not-allowed;
  opacity: 1;
}
.bnav-mark.is-locked .bnav-mark-glyph { transform: scale(0.92); }
.bnav-mark.is-locked:active { transform: none; }
.bnav-lock {
  position: absolute;
  right: 6px; bottom: 6px;
  display: flex; align-items: center; justify-content: center;
  width: 17px; height: 17px;
  color: var(--bg);
  background: var(--muted);
  border-radius: 50%;
}
@media (prefers-reduced-motion: reduce) {
  .bnav-mark, .bnav-mark-glyph { transition: none; }
}

@media (max-width: 900px) {
  .bnav { display: flex; }
  :root { --bnav-h: 62px; }
  /* Keep the footer and page tail clear of the fixed furniture. */
  body { padding-bottom: calc(var(--bnav-h) + env(safe-area-inset-bottom, 0px)); }
  /* Compact floating strip only while audio is live — idle stays clear. */
  body.has-player { padding-bottom: calc(var(--bnav-h) + env(safe-area-inset-bottom, 0px)); }
  body:has(.pl.open.is-playing) {
    padding-bottom: calc(var(--bnav-h) + 68px + env(safe-area-inset-bottom, 0px));
  }
  .pl {
    left: 8px; right: 8px;
    bottom: calc(var(--bnav-h) + env(safe-area-inset-bottom, 0px) + 8px);
  }
  /* Hide when cued but not playing — reclaim the screen. */
  .pl.open:not(.is-playing) {
    transform: translateY(calc(100% + 28px));
    pointer-events: none;
  }
  .pl.open.is-playing { transform: none; pointer-events: auto; }

  .pl-body {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 8px;
    padding: 8px 10px 10px;
  }
  .pl-controls { gap: 0; }
  .pl-controls #plPrev,
  .pl-controls #plNext { display: none; }
  .pl-right {
    display: none;
  }
  /* Fullscreen still reachable by tapping the now-playing row. */
  .pl-main { width: 38px; height: 38px; }
  .pl-art { width: 32px; height: 32px; }
  .pl-art-mark { width: 16px; height: 16px; }
  .pl-title { font-size: 0.78rem; }
  .pl-viz { height: 22px; opacity: 0.28; }
  .pl.is-playing .pl-viz { opacity: 0.45; }
}
@media (min-width: 901px) {
  body.has-player { padding-bottom: 86px; }
  .pl {
    left: 18px; right: 18px;
    bottom: 16px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .pl { transition: none; }
  .pl-eq i, .pl-viz i { animation: none !important; }
}

/* ---------- Toasts ---------- */
.toasts {
  position: fixed;
  top: calc(var(--nav-h) + 14px);
  right: var(--gut);
  /* Top of the stack: the player and the menu both raise toasts, so they
     have to clear the fullscreen player (200) and the menu (150). */
  z-index: 260;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 240px;
  max-width: 360px;
  padding: 14px 16px;
  border-radius: 0;
  background: var(--well);
  border: 1px solid var(--line);
  border-left: 2px solid var(--text);
  font-size: 0.84rem;
  font-weight: 500;
  animation: toast-in 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}
.toast.success { border-left-color: var(--green); }
.toast.error { border-left-color: var(--red); }
.toast.accent { border-left-color: var(--text); }
.toast.leaving { animation: toast-out 0.25s ease forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateX(20px); } }
.flash { display: none; }

/* ---------- Tables ---------- */
table { border-collapse: collapse; width: 100%; }
th {
  text-align: start;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--muted);
  padding: 12px;
  border-bottom: 1px solid var(--line);
  font-weight: 600;
}
td { padding: 13px 12px; border-bottom: 1px solid var(--line-soft); font-size: 0.88rem; }
tr:hover td { background: var(--wash-1); }

/* ---------- Marquee ticker ---------- */
.ticker {
  position: relative;
  overflow: hidden;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 12px 0;
  user-select: none;
}
.ticker-track {
  display: flex;
  gap: 40px;
  width: max-content;
  animation: ticker 38s linear infinite;
}
.ticker:hover .ticker-track { animation-play-state: paused; }
.ticker span {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.26em;
  color: var(--muted);
  white-space: nowrap;
}
.ticker span::after { content: "◆"; margin-left: 40px; color: var(--faint); }
@keyframes ticker { to { transform: translateX(-50%); } }

/* ---------- Reveal / split text ----------
   Scoped to .js so content is visible by default. Without this gate a
   failed script — or an observer that never fires because the page was
   opened at an anchor mid-document — leaves the page permanently blank. */
.reveal { transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1), transform 0.8s cubic-bezier(0.22, 1, 0.36, 1); }
.js .reveal { opacity: 0; transform: translateY(22px); }
.js .reveal.in { opacity: 1; transform: none; }
.reveal.d1 { transition-delay: 0.07s; }
.reveal.d2 { transition-delay: 0.14s; }
.reveal.d3 { transition-delay: 0.21s; }

[data-split] .ch {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.5em);
  filter: blur(5px);
  animation: ch-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  animation-delay: calc(var(--i) * 45ms + 120ms);
}
@keyframes ch-in { to { opacity: 1; transform: none; filter: blur(0); } }

.blur-in { opacity: 0; filter: blur(8px); animation: blur-in 1s cubic-bezier(0.22, 1, 0.36, 1) forwards; }
.blur-in.late { animation-delay: 0.5s; }
.blur-in.later { animation-delay: 0.9s; }
@keyframes blur-in { to { opacity: 1; filter: blur(0); } }

/* ---------- Site footer ---------- */
.site-footer {
  position: relative;
  z-index: 1;
  margin-top: 120px;
  border-top: 1px solid var(--line);
  padding: 56px var(--gut) 0;
  /* Pin the mega wordmark to the bottom of the viewport on tall desktops. */
  display: flex;
  flex-direction: column;
  min-height: min(72vh, 820px);
}
.footer-inner {
  max-width: 1440px;
  margin: 0 auto;
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: 40px;
}
.footer-brand .logo { width: 26px; height: 26px; margin-bottom: 16px; }
.footer-brand p { color: var(--muted); font-size: 0.85rem; max-width: 34ch; margin: 0; }
.footer-col h4 {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--muted);
  margin: 0 0 14px;
}
.footer-col a {
  display: block;
  font-size: 0.85rem;
  color: var(--text-dim);
  padding: 5px 0;
  transition: color 0.2s, padding-left 0.25s;
}
.footer-col a:hover { color: var(--text); padding-left: 6px; }

/* Oversized outlined wordmark at the foot of the page. A script in base.html
   (panjMegaFit) sizes it to fill the width exactly, in English or Farsi; the
   size below only holds until it runs. Every letter shows whole. */
.mega-footer {
  position: relative;
  overflow: hidden;
  padding: 10vh var(--gut) clamp(8px, 1.4vw, 20px);
  margin-top: auto;
  user-select: none;
  pointer-events: none;
  container-type: inline-size;
}
.mega-text {
  display: block;
  width: max-content;
  margin: 0 auto;
  font-family: var(--font-display);
  font-size: min(calc(100cqi / 10.6), 280px);
  line-height: 0.9;
  letter-spacing: -0.03em;
  white-space: nowrap;
  /* A quiet solid fill, not an outline, and opaque: outlined or see-through
     Persian letters show a seam at every join, where the shapes overlap. */
  color: color-mix(in srgb, var(--text) 13%, var(--bg));
}
/* The Persian word keeps its dots and the tall kaf inside the box. */
:root[lang="fa"] .mega-text { line-height: 1.45; letter-spacing: 0; }
.footer-legal {
  position: relative;
  z-index: 1;
  max-width: 1440px;
  margin: 0 auto;
  width: 100%;
  padding: 18px var(--gut) 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.footer-legal a { color: var(--muted); transition: color 0.2s; }
.footer-legal a:hover { color: var(--text); }

/* Soft page transitions — chrome (player, bnav, nav) never leave. While
   the next page loads, the one on screen dims but stays: the screen is
   never blank, whatever the network does (nav.js). */
main.container {
  transition: opacity 0.2s ease;
}
main.container.page-leave {
  opacity: 0.45;
  pointer-events: none;
}
main.container.page-enter {
  animation: page-enter 0.32s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes page-enter {
  from { opacity: 0.45; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
body.is-navigating { cursor: progress; }
@media (prefers-reduced-motion: reduce) {
  main.container { transition: none; }
  main.container.page-enter { animation: none; transform: none; opacity: 1; }
}

/* ---------- Modal ---------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--scrim);
  opacity: 0;
  pointer-events: none;
  /* A closed modal must be genuinely gone, not merely transparent.
     `visibility` takes it out of the accessibility tree and lets the
     browser stop compositing it — left visible, the blur below was a
     full-viewport filter layer live on every page, which is what made
     opening it stutter on phones. Delayed on the way out so the fade
     still plays. */
  visibility: hidden;
  transition: opacity 0.25s, visibility 0s linear 0.25s;
  padding: 20px;
}
.modal-backdrop.open {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: opacity 0.25s, visibility 0s;
  /* Only blur while it is actually up. */
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.modal-card {
  position: relative;
  background: var(--well);
  border: 1px solid var(--line);
  border-radius: 0;
  padding: 40px 34px 30px;
  width: 100%;
  max-width: 380px;
  text-align: start;
  /* Tall sheets have to scroll rather than run off the top and bottom of a
     short viewport — on a phone in landscape the install steps were simply
     unreachable. */
  max-height: calc(100dvh - 40px);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform: translateY(12px);
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.modal-backdrop.open .modal-card { transform: none; }
.modal-close {
  position: absolute;
  top: 14px; right: 16px;
  z-index: 2;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 1.5rem;
  cursor: pointer;
  line-height: 1;
  transition: color 0.2s, transform 0.3s;
}
.modal-close:hover { color: var(--text); transform: rotate(90deg); }
.modal-card .full-width { width: 100%; }

/* Get-app modal — brand-led install sheet */
.app-modal {
  max-width: 400px;
  padding: 0 0 22px;
  overflow: hidden;
  background:
    radial-gradient(120% 80% at 50% -10%, var(--wash-3), transparent 55%),
    linear-gradient(180deg, var(--bg-raise) 0%, var(--well) 42%);
}
.app-modal-stage {
  position: relative;
  height: 168px;
  margin-bottom: 22px;
  border-bottom: 1px solid var(--line);
  display: grid;
  place-items: center;
  overflow: hidden;
  background:
    linear-gradient(var(--bg-rule) 1px, transparent 1px),
    linear-gradient(90deg, var(--bg-rule) 1px, transparent 1px);
  background-size: 28px 28px;
}
.app-modal-scan {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    var(--wash-3) 50%,
    transparent 100%
  );
  background-size: 100% 40%;
  animation: app-scan 3.6s ease-in-out infinite;
}
.app-modal-phone {
  position: relative;
  z-index: 1;
  width: 92px;
  height: 118px;
  border: 1px solid var(--line-strong);
  background: var(--well);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  box-shadow: 0 18px 40px var(--shadow);
  animation: app-phone-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.app-modal-phone::before {
  content: '';
  position: absolute;
  top: 8px;
  width: 28px;
  height: 3px;
  background: var(--line);
}
.app-modal-phone img {
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
}
.app-modal-mark {
  font-family: var(--font-mono);
  font-size: 0.48rem;
  letter-spacing: 0.22em;
  color: var(--text-dim);
}
.app-modal-corners {
  position: absolute;
  inset: 14px;
  pointer-events: none;
}
.app-modal-corners i {
  position: absolute;
  width: 10px;
  height: 10px;
  border-color: var(--text-dim);
  border-style: solid;
  opacity: 0.55;
}
.app-modal-corners .tl { top: 0; left: 0; border-width: 1px 0 0 1px; }
.app-modal-corners .tr { top: 0; right: 0; border-width: 1px 1px 0 0; }
.app-modal-corners .bl { bottom: 0; left: 0; border-width: 0 0 1px 1px; }
.app-modal-corners .br { bottom: 0; right: 0; border-width: 0 1px 1px 0; }

.app-modal-eyebrow,
.app-modal h3,
.app-modal-lede,
.app-modal-access,
.app-modal #installBtn,
.app-modal .install-steps,
.app-modal-foot {
  margin-left: 28px;
  margin-right: 28px;
}
.app-modal-eyebrow {
  margin-top: 0;
  margin-bottom: 10px;
  font-family: var(--font-mono);
  font-size: 0.56rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  animation: app-rise 0.45s 0.08s both;
}
.app-modal h3 {
  margin: 0 0 12px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.7rem, 6vw, 2.05rem);
  line-height: 0.95;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--text);
  animation: app-rise 0.5s 0.14s both;
}
.app-modal h3 em {
  display: block;
  font-style: normal;
  color: transparent;
  -webkit-text-stroke: 1px var(--line-strong);
}
.app-modal-lede {
  margin: 0 0 20px;
  font-size: 0.88rem;
  line-height: 1.65;
  color: var(--text-dim);
  max-width: 34ch;
  animation: app-rise 0.5s 0.2s both;
}
.app-modal-access {
  list-style: none;
  margin: 0 28px 22px;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--line);
  animation: app-rise 0.5s 0.26s both;
}
.app-modal-access li {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 10px;
  font-family: var(--font-display);
  font-size: 0.78rem;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  color: var(--text);
  border-right: 1px solid var(--line-soft);
}
.app-modal-access li:last-child { border-right: none; }
.app-modal-access span {
  font-family: var(--font-mono);
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  color: var(--muted);
}
.app-modal #installBtn {
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
  animation: app-rise 0.5s 0.3s both;
}
.app-modal #installBtn i {
  font-style: normal;
  transition: transform 0.25s;
}
.app-modal #installBtn:hover i { transform: translateX(3px); }

/* Update sheet — same card as Get App; phone glyph spins to signal a new build
   (only while the sheet is open: see .modal-backdrop.open below). */
@keyframes update-mark-spin {
  to { transform: rotate(360deg); }
}
.update-modal #updateBtn {
  justify-content: space-between;
  gap: 12px;
  margin-left: 28px;
  margin-right: 28px;
  margin-bottom: 8px;
  animation: none;
}
.update-modal #updateBtn i {
  font-style: normal;
  transition: transform 0.25s;
}
.update-modal #updateBtn:hover i { transform: translateX(3px); }
.modal-backdrop.open .update-modal #updateBtn { animation: app-rise 0.5s 0.3s both; }

/* The PANJGOOSHEH mark filling up over grey (the update veil in white, the page loader in gold). */
.pnj-fill {
  position: relative;
  display: block;
  width: 56px;
  aspect-ratio: 535 / 510;
  --fill: #fffef3;
  --empty: #3b4040;
}
.pnj-fill::before,
.pnj-fill > i {
  content: "";
  position: absolute;
  inset: 0;
  mask: var(--mark) center / contain no-repeat;
  -webkit-mask: var(--mark) center / contain no-repeat;
}
.pnj-fill::before { background: var(--empty); }
.pnj-fill > i {
  background:
    linear-gradient(to bottom, color-mix(in srgb, var(--fill) 70%, #9fe8ff) 0 3%, var(--fill) 3%);
  clip-path: inset(calc((1 - var(--p, 0)) * 100%) 0 0 0);
  transition: clip-path 0.32s cubic-bezier(0.22, 1, 0.36, 1);
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--fill) 40%, transparent));
}
.pnj-fill-lg { width: min(38vw, 156px); }

/* Page loading: the mark fills up gold in a small black badge that floats
   over the middle of the page. There is no curtain behind it and it never
   takes a tap, so the app stays in reach while the next page comes in. */
.page-loader {
  position: fixed;
  left: 50%;
  top: 50%;
  z-index: 9990;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.86);
  transition: opacity 0.18s ease, transform 0.26s cubic-bezier(0.22, 1, 0.36, 1);
}
.page-loader.is-on { opacity: 1; transform: translate(-50%, -50%); }
.page-loader.no-in, .page-loader.no-in .pnj-fill > i { transition: none; }
.page-loader.is-done { opacity: 0; transform: translate(-50%, -50%) scale(1.06); transition-delay: 0.12s; }
.pl-badge {
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: 26px;
  background: #0b0b0b;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45), inset 0 0 0 1px rgba(255, 254, 243, 0.08);
}
.page-loader .pnj-fill { width: 46px; --fill: #ffc60b; --empty: #2a2f2f; }
.page-loader .pnj-fill > i { filter: none; }

/* Full-screen apply veil — between Update tap and the same-URL reload. */
.update-veil {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #090c0c;
  color: #fffef3;
  overflow: hidden;
  animation: update-veil-in 0.35s ease both;
}
@keyframes update-veil-in { from { opacity: 0; } }
.update-veil[hidden] { display: none !important; }
html.is-updating, html.is-updating body { overflow: hidden; }
.update-veil-glow {
  position: absolute;
  left: 50%;
  top: 44%;
  width: min(90vw, 620px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, rgba(255, 254, 243, 0.10), transparent 70%);
  animation: update-glow 2.4s ease-in-out infinite;
}
@keyframes update-glow { 50% { transform: translate(-50%, -50%) scale(1.12); opacity: 0.6; } }
.update-veil-core {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 0 16px;
  text-align: center;
}
.update-veil-core .pnj-fill { margin-bottom: 10px; animation: app-rise 0.5s both; }
.update-veil-pct {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.18em;
  color: rgba(255, 254, 243, 0.55);
}
.update-veil-pct b { color: #fffef3; font-weight: 500; font-variant-numeric: tabular-nums; display: inline-block; min-width: 3ch; text-align: end; }
.update-veil-word {
  display: flex;
  gap: 0.04em;
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 6vw, 2.1rem);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #fffef3;
}
.update-veil-word i {
  font-style: normal;
  opacity: 0;
  transform: translateY(0.4em);
  filter: blur(6px);
  animation: update-letter-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  animation-delay: calc(0.08s + var(--i) * 0.05s);
}
@keyframes update-letter-in {
  to { opacity: 1; transform: none; filter: none; }
}
.update-veil-step {
  margin: 0;
  min-height: 1.3em;
  font-size: 0.86rem;
  color: rgba(255, 254, 243, 0.7);
  animation: app-rise 0.45s 0.3s both;
}
.update-veil-foot {
  margin: 10px 0 0;
  font-family: var(--font-mono);
  font-size: 0.52rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 254, 243, 0.4);
  animation: app-rise 0.45s 0.4s both;
}

.install-steps {
  text-align: start;
  margin-top: 4px;
  margin-bottom: 4px;
  animation: app-rise 0.5s 0.3s both;
}
.install-steps[hidden] { display: none !important; }
.install-steps .step {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line-soft);
  color: var(--muted);
  font-size: 0.84rem;
}
.install-steps .step:last-child { border-bottom: none; }
.install-steps .step span {
  width: 24px; height: 24px;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--line);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 0.68rem;
}
.install-steps .step strong { color: var(--text); font-weight: 600; }

.app-modal-foot {
  margin-top: 18px;
  margin-bottom: 0;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  font-family: var(--font-mono);
  font-size: 0.52rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  animation: app-rise 0.5s 0.34s both;
}

@keyframes app-scan {
  0%, 100% { transform: translateY(-70%); opacity: 0.35; }
  50% { transform: translateY(70%); opacity: 0.9; }
}
@keyframes app-phone-in {
  from { opacity: 0; transform: translateY(18px) scale(0.96); }
  to { opacity: 1; transform: none; }
}
@keyframes app-rise {
  from { opacity: 0; transform: translateY(10px); filter: blur(4px); }
  to { opacity: 1; transform: none; filter: none; }
}

@media (prefers-reduced-motion: reduce) {
  .app-modal-scan,
  .app-modal-phone,
  .app-modal-eyebrow,
  .app-modal h3,
  .app-modal-lede,
  .app-modal-access,
  .app-modal #installBtn,
  .app-modal .install-steps,
  .app-modal-foot,
  .update-modal #updateBtn,
  .app-modal-phone.is-update img,
  .update-veil,
  .update-veil-glow,
  .update-veil-core .pnj-fill,
  .update-veil-word i,
  .update-veil-step,
  .update-veil-foot {
    animation: none !important;
  }
  .update-veil-word i { opacity: 1; transform: none; filter: none; }
  .pnj-fill > i, .page-loader, .page-loader .pnj-fill > i { transition: none !important; }
}

[dir="rtl"] { direction: rtl; }
[dir="ltr"] { direction: ltr; }

@media (max-width: 900px) {
  .footer-inner { grid-template-columns: 1fr; gap: 20px; }
  .footer-brand { grid-column: 1 / -1; }
  /* App-like: drop the link columns on phones — bottom nav owns navigation. */
  .footer-col { display: none; }
  /* ...except the public pages: two short columns of links. */
  .footer-col.footer-explore { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 2px 16px; }
  .footer-explore h4 { grid-column: 1 / -1; margin-bottom: 6px; }
  .footer-explore a { padding: 7px 0; font-size: .86rem; }
  .site-footer {
    min-height: 0;
    margin-top: 64px;
    padding-top: 28px;
  }
  .footer-brand p { display: none; }
  .footer-brand .logo { margin-bottom: 0; opacity: 0.55; }
  .mega-footer { padding-top: 4vh; margin-top: 20px; }
  /* Mobile: wordmark only — copyright lives elsewhere / is redundant. */
  .footer-legal { display: none; }
}
@media (max-width: 640px) {
  body { font-size: 14.5px; }
  .toasts { left: var(--gut); right: var(--gut); }
  .toast { max-width: none; width: 100%; }
  .grid { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .reveal, [data-split] .ch, .blur-in {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    animation: none !important;
    transition: none !important;
  }
  .ticker-track, .bg-grain { animation: none !important; }
}

/* ---------- Get-app modal: open-scoped motion and small screens ----------
   The entrance animations above are declared on the elements themselves,
   so they ran once at page load — while the modal was still invisible —
   and had long finished by the time anyone opened it. Opening therefore
   snapped straight to the final frame, and the infinite scan line ran
   behind a closed sheet for the life of the page.

   Gating animation-name on `.open` fixes both: `none` while closed means
   the name changes on open, which is what makes an animation restart. */
.app-modal-scan,
.app-modal-phone,
.app-modal-eyebrow,
.app-modal h3,
.app-modal-lede,
.app-modal-access,
.app-modal #installBtn,
.app-modal .install-steps,
.app-modal-foot,
.update-modal #updateBtn {
  animation: none;
}
.modal-backdrop.open .app-modal-scan   { animation: app-scan 3.6s ease-in-out infinite; }
.modal-backdrop.open .app-modal-phone  { animation: app-phone-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) both; }
.modal-backdrop.open .app-modal-eyebrow{ animation: app-rise 0.45s 0.08s both; }
.modal-backdrop.open .app-modal h3     { animation: app-rise 0.5s 0.14s both; }
.modal-backdrop.open .app-modal-lede   { animation: app-rise 0.5s 0.2s both; }
.modal-backdrop.open .app-modal-access { animation: app-rise 0.5s 0.26s both; }
.modal-backdrop.open .app-modal #installBtn    { animation: app-rise 0.5s 0.3s both; }
.modal-backdrop.open .app-modal .install-steps { animation: app-rise 0.5s 0.3s both; }
.modal-backdrop.open .app-modal-foot   { animation: app-rise 0.5s 0.34s both; }
.modal-backdrop.open .update-modal #updateBtn  { animation: app-rise 0.5s 0.3s both; }
.modal-backdrop.open .app-modal-phone.is-update img {
  animation: update-mark-spin 2.8s linear infinite;
}

/* The 6-second auto-dismiss, made visible. A sheet that vanishes on its
   own with no warning reads as a glitch; a countdown reads as intent. */
.app-modal-timer {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--line-soft);
  overflow: hidden;
}
.app-modal-timer span {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--text);
  transform-origin: right center;
  transform: scaleX(0);
}
.modal-backdrop.open .app-modal-timer span {
  animation: app-timer 6s linear forwards;
}
/* Paused while the member is actually reading it. */
.modal-backdrop.is-held .app-modal-timer span { animation-play-state: paused; }
@keyframes app-timer {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0); }
}

/* ---- Small screens ----
   The sheet was laid out for 400px and hard-coded 28px side margins, which
   on a 360px phone left the three-column feature grid about 30px per cell
   and pushed the card wider than the viewport. */
@media (max-width: 420px) {
  .app-modal { max-width: 100%; }
  .app-modal-eyebrow,
  .app-modal h3,
  .app-modal-lede,
  .app-modal #installBtn,
  .app-modal .install-steps,
  .app-modal-foot,
  .update-modal #updateBtn {
    margin-left: 18px;
    margin-right: 18px;
  }
  .app-modal-access { margin-left: 18px; margin-right: 18px; }
  .app-modal-stage { height: 132px; margin-bottom: 18px; }
  .app-modal-phone { width: 76px; height: 98px; }
  .app-modal-phone img { width: 36px; height: 36px; }
  .app-modal-lede { max-width: none; }
}
/* Short viewports — a phone in landscape, or a small window. The stage is
   the first thing to go: it is decoration, and the install steps are not. */
@media (max-height: 640px) {
  .app-modal-stage { height: 96px; }
  .app-modal h3 { font-size: 1.4rem; }
  .app-modal-lede { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .modal-backdrop.open .app-modal-timer span { animation: none; transform: scaleX(0); }
}

/* =====================================================================
   Admin shell (templates/_admin_nav.html). One copy for every /admin
   page. Desktop ≥1100px: a fixed sidebar under the site nav and the page
   shifted right. Below that: a slim sticky bar (menu, where you are,
   quick links) and the sidebar becomes a full-screen menu with search.
   ===================================================================== */
:root { --ax-w: 248px; }
.ax-bar {
  position: sticky; top: var(--nav-h); z-index: 80;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px;
  margin: 0 calc(-1 * var(--gut)) 18px;
  padding: 8px var(--gut);
  background: var(--bg); border-bottom: 1px solid var(--line);
}
.ax-open { position: relative; flex: none; width: 40px; height: 40px; display: grid; place-items: center;
  background: var(--well); border: 1px solid var(--line-strong); color: var(--text); cursor: pointer; }
.ax-dot-n { position: absolute; top: 6px; right: 6px; width: 7px; height: 7px; border-radius: 50%; background: var(--red); }
.ax-crumb { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.15; }
.ax-crumb span { font: .5rem var(--font-mono, monospace); letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }
.ax-crumb b { font: 800 .9rem var(--font-display, system-ui); text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ax-quick { flex: 1 1 100%; order: 3; min-width: 0; display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; margin: 0 calc(-1 * var(--gut)); padding-left: var(--gut) !important; padding-right: var(--gut) !important;
  -webkit-mask: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 22px), transparent); mask: linear-gradient(90deg, transparent 0, #000 14px, #000 calc(100% - 22px), transparent);
  }
.ax-quick::-webkit-scrollbar { display: none; }
.ax-quick a { flex: none; display: inline-flex; align-items: center; gap: 6px; padding: 8px 11px; border: 1px solid var(--line);
  color: var(--text-dim); text-decoration: none; font: 700 .62rem var(--font-mono, monospace); letter-spacing: .1em; text-transform: uppercase; }
.ax-quick a.on { background: var(--text); color: var(--ink); border-color: var(--text); }
.ax-quick b, .ax-badge { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--red); color: #fff; font: 700 .6rem var(--font-body, system-ui); letter-spacing: 0; }

.ax-scrim { position: fixed; inset: 0; z-index: 420; background: rgba(var(--ground-rgb), .6); backdrop-filter: blur(3px); }
.ax-scrim[hidden] { display: none; }
html.ax-locked, html.ax-locked body { overflow: hidden; }
/* <main> is its own stacking layer (z-index 1), under the site nav and the
   bottom bar; lift it while the admin menu is open so the menu covers both. */
html.ax-locked main { z-index: 430; }
.ax-side {
  position: fixed; z-index: 421; top: 0; bottom: 0; left: 0; width: min(88vw, 340px);
  display: flex; flex-direction: column; gap: 12px;
  padding: max(14px, env(safe-area-inset-top, 0px)) 14px calc(14px + env(safe-area-inset-bottom, 0px));
  background: var(--bg); border-right: 1px solid var(--line-strong); box-shadow: 20px 0 60px var(--shadow);
  transform: translateX(-104%); transition: transform .28s cubic-bezier(.22, 1, .36, 1); visibility: hidden;
}
.ax.is-open .ax-side { transform: none; visibility: visible; }
.ax-side-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ax-brand { display: inline-flex; align-items: center; gap: 8px; color: var(--text); text-decoration: none;
  font: 800 .66rem var(--font-mono, monospace); letter-spacing: .18em; text-transform: uppercase; }
.ax-led { width: 8px; height: 8px; border-radius: 50%; background: var(--green, #4ade80); box-shadow: 0 0 10px var(--green, #4ade80); }
.ax-close { width: 38px; height: 38px; display: grid; place-items: center; background: none; border: 1px solid var(--line); color: var(--text); cursor: pointer; }
.ax-search { display: flex; align-items: center; gap: 8px; padding: 0 10px; height: 42px; border: 1px solid var(--line-strong); background: var(--well); color: var(--muted); }
.ax-search input { flex: 1; min-width: 0; height: 100%; padding: 0; border: 0; background: none; color: var(--text); font: 600 .9rem var(--font-body, system-ui); outline: none; }
.ax-search input::-webkit-search-cancel-button { -webkit-appearance: none; }
.ax-search kbd { font: .62rem var(--font-mono, monospace); padding: 2px 6px; border: 1px solid var(--line); color: var(--muted); }
.ax-search:focus-within { border-color: var(--text); }
.ax-nav { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; margin: 0 -6px; padding: 0 6px; }
.ax-group { margin-bottom: 14px; }
.ax-group[hidden] { display: none; }
.ax-group-label { margin: 0 0 4px; padding: 0 10px; font: 700 .54rem var(--font-mono, monospace); letter-spacing: .2em; text-transform: uppercase; color: var(--muted); }
.ax-link { display: flex; align-items: center; gap: 11px; padding: 9px 10px; color: var(--text-dim); text-decoration: none;
  font: 600 .88rem var(--font-body, system-ui); border-left: 2px solid transparent; }
.ax-link[hidden] { display: none; }
.ax-link .icon { flex: none; opacity: .75; }
.ax-link span { flex: 1; min-width: 0; }
.ax-link:hover { background: var(--wash-2); color: var(--text); }
.ax-link.on { background: var(--wash-3); color: var(--text); border-left-color: var(--vip, #ffc60b); }
.ax-link.on .icon { opacity: 1; color: var(--vip, #ffc60b); }
.ax-empty { padding: 10px; font-size: .84rem; color: var(--muted); }
.ax-side-foot { padding-top: 10px; border-top: 1px solid var(--line); }
.ax-side-foot a { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); text-decoration: none; font-size: .78rem; }

@media (min-width: 1100px) {
  .ax-bar, .ax-scrim, .ax-close { display: none !important; }
  .ax-side { top: var(--nav-h); width: var(--ax-w); transform: none; visibility: visible; box-shadow: none; z-index: 70;
    padding-top: 18px; border-right-color: var(--line); }
  body:has(.ax) main.container { padding-left: calc(var(--ax-w) + clamp(24px, 3vw, 44px)); max-width: none; }
  body:has(.ax) .site-footer { padding-left: var(--ax-w); }
}

/* ---- Every admin page: built for a phone first ----------------------- */
/* The scroll-reveal fade is for marketing pages; in admin it only ever hid
   data (a whole grid sat invisible until it was scrolled past). */
body:has(.ax) .reveal { opacity: 1 !important; transform: none !important; filter: none !important; }
body:has(.ax) main.container { padding-top: 0; }
@media (min-width: 1100px) { body:has(.ax) main.container { padding-top: 28px; } }
body:has(.ax) main.container table { font-size: .84rem; }
@media (max-width: 760px) {
  body:has(.ax) main.container { padding-left: 14px; padding-right: 14px; }
  body:has(.ax) .ax-bar { margin-left: -14px; margin-right: -14px; padding-left: 14px; padding-right: 14px; }
  /* Tables never push the page sideways: they scroll inside their own box. */
  body:has(.ax) main.container table { display: block; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; white-space: nowrap; }
  body:has(.ax) main.container td, body:has(.ax) main.container th { padding: 9px 10px; }
  /* Forms stack; inputs fill the row and are big enough to tap. */
  body:has(.ax) main.container input:not([type=checkbox]):not([type=radio]):not([type=range]),
  body:has(.ax) main.container select, body:has(.ax) main.container textarea { max-width: 100%; font-size: 16px; }
  body:has(.ax) .inline-form, body:has(.ax) .toolbar, body:has(.ax) .fin-row, body:has(.ax) .tk-filter { flex-wrap: wrap; }
  /* Long single words (ANNOUNCEMENTS, CONVERSATIONS) must fit on one line
     rather than break mid-word. */
  body:has(.ax) .page-title, body:has(.ax) .admin-page-title, body:has(.ax) main.container h1 {
    font-size: clamp(1.45rem, 7vw, 2.2rem) !important; line-height: 1.02; overflow-wrap: normal; word-break: normal; hyphens: none; text-wrap: balance; }
  body:has(.ax) main.container img, body:has(.ax) main.container video, body:has(.ax) main.container canvas { max-width: 100%; height: auto; }
  body:has(.ax) pre, body:has(.ax) code { white-space: pre-wrap; overflow-wrap: anywhere; }
}
/* Text never spills out of an admin card: long handles, ids and notes wrap,
   buttons keep their label on one line, wide tables scroll inside the card. */
body:has(.ax) main.container { overflow-wrap: anywhere; }
body:has(.ax) main.container table { overflow-wrap: normal; }
body:has(.ax) main.container .card:has(> table), body:has(.ax) main.container .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
body:has(.ax) .dh-feed-r code { white-space: nowrap; overflow-wrap: normal; }
@media (max-width: 760px) { body:has(.ax) .ax-quick { margin: 0 -14px; padding-left: 14px !important; padding-right: 14px !important; } }
/* Page-specific layouts that were desktop-only grids. */
@media (max-width: 760px) {
  body:has(.ax) .visuals-hub-nav { flex-wrap: wrap; gap: 6px 14px; margin-bottom: 24px; }
  body:has(.ax) .an-grid, body:has(.ax) .an-add { grid-template-columns: minmax(0, 1fr) !important; }
  body:has(.ax) .an-compose { padding: 16px; }
  body:has(.ax) .card { padding-left: 14px; padding-right: 14px; }
}


/* ---- Admin on a phone: one bar on top, admin tabs at the bottom ---------
   The site header and the member bottom bar are for members; in the control
   room they only stacked three bars of navigation above the content. */
@media (max-width: 1099px) {
  body:has(.ax) > .nav, body:has(.ax) .nav-spacer { display: none !important; }
  body:has(.ax) { --nav-h: 0px; }
  body:has(.ax) .ax-bar { top: 0; padding-top: calc(8px + env(safe-area-inset-top)); }
  body:has(.ax) main.container { padding-bottom: calc(84px + env(safe-area-inset-bottom)); }
}
/* Stats wrap two to a row instead of cutting numbers off. */
@media (max-width: 520px) {
  body:has(.ax) .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body:has(.ax) .stat { border-left: 0; border-top: 1px solid var(--line); }
  body:has(.ax) .stat:nth-child(even) { border-left: 1px solid var(--line); }
  body:has(.ax) .stat:nth-child(-n+2) { border-top: 0; }
}
/* Big money figures shrink to the width of their box rather than being cut. */
body:has(.ax) .stat { container-type: inline-size; }
body:has(.ax) .stat .num { text-overflow: clip; font-size: min(clamp(1.15rem, 4.2vw, 1.9rem), 10.5cqi); }
body:has(.ax) .stat .lbl { white-space: normal; }

.bnav-admin .bnav-i { position: relative; }
.bnav-n { position: absolute; top: 4px; left: calc(50% + 6px); min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
  background: var(--red); color: #fff; font: 700 .58rem/16px var(--font-body); text-align: center; }
.bnav-scan { width: 54px; height: 54px; margin: -14px 6px 0; border-radius: 50%; display: grid; place-items: center; flex: 0 0 auto;
  background: var(--text); color: var(--ink); box-shadow: 0 6px 20px rgba(0,0,0,.4); }
.bnav-scan.on { background: var(--vip, #ffc60b); color: #000; }

/* ---- Utilities ---- */
.font-darvish { font-family: var(--font-fa); }
.font-fa-text { font-family: var(--font-fa-text); }
.font-fa-display { font-family: var(--font-display); }

/* The wordmark is Latin: it always reads left to right. */
.brand, .brand-word, .mm-brand { direction: ltr; }


/* ---- Farsi pages (lang="fa", dir="rtl") --------------------------------
   Letter-spacing pulls Persian letters apart and breaks their joins, and the
   tight display leading clips the taller Persian forms. */
:root[lang="fa"] body, :root[lang="fa"] body *, :root[lang="fa"] body *::before, :root[lang="fa"] body *::after {
  letter-spacing: 0 !important; word-spacing: normal !important; font-synthesis: none; }
/* Space Mono's wide spaces leave gaps between Persian words in small labels:
   on Farsi pages the mono labels are set in Darvish; codes keep Space Mono. */
:root[lang="fa"] {
  --font-display: 'Fa Display', 'Medium', 'Space Grotesk', sans-serif;
  --font-mono: 'Fa Text', 'Space Mono', ui-monospace, monospace;
}
:root[lang="fa"] code, :root[lang="fa"] kbd, :root[lang="fa"] .tkt-code, :root[lang="fa"] .ticket-code { font-family: 'Space Mono', ui-monospace, monospace; }
:root[lang="fa"] h1, :root[lang="fa"] h2, :root[lang="fa"] h3, :root[lang="fa"] h4,
:root[lang="fa"] .page-title, :root[lang="fa"] .u-h1, :root[lang="fa"] .gx-h, :root[lang="fa"] .wf-h,
:root[lang="fa"] .hm-title, :root[lang="fa"] .soon-h, :root[lang="fa"] .apm-h, :root[lang="fa"] .wf-m-h,
:root[lang="fa"] .dv-word, :root[lang="fa"] .mobile-menu-list a { line-height: 1.35 !important; }
:root[lang="fa"] body { line-height: 1.8; }
/* Codes, card numbers, amounts and URLs read left to right inside RTL text. */
:root[lang="fa"] code, :root[lang="fa"] .t-num, :root[lang="fa"] .paysheet-digits, :root[lang="fa"] input[type="number"],
:root[lang="fa"] input[inputmode="numeric"], :root[lang="fa"] .ticket-code { direction: ltr; unicode-bidi: isolate; }
/* Icons that point somewhere point the other way. */
:root[dir="rtl"] .icon-arrow-left, :root[dir="rtl"] .icon-arrow-right, :root[dir="rtl"] .icon-chevron-right,
:root[dir="rtl"] .icon-chevron-left, :root[dir="rtl"] .icon-log-in, :root[dir="rtl"] .icon-send { transform: scaleX(-1); }

/* ---- RTL: the control room mirrors ------------------------------------ */
:root[dir="rtl"] .ax-side { left: auto; right: 0; border-right: 0; border-left: 1px solid var(--line-strong);
  box-shadow: -20px 0 60px var(--shadow); transform: translateX(104%); }
:root[dir="rtl"] .ax.is-open .ax-side { transform: none; }
:root[dir="rtl"] .ax-link { border-left: 0; border-right: 2px solid transparent; }
:root[dir="rtl"] .ax-link.on { border-right-color: var(--vip, #ffc60b); }
@media (min-width: 1100px) {
  :root[dir="rtl"] .ax-side { transform: none; }
  :root[dir="rtl"] body:has(.ax) main.container { padding-left: clamp(24px, 3vw, 44px); padding-right: calc(var(--ax-w) + clamp(24px, 3vw, 44px)); }
  :root[dir="rtl"] body:has(.ax) .site-footer { padding-left: 0; padding-right: var(--ax-w); }
}
/* Long-scroll chapters and big display lines must not clip at the start edge. */
:root[dir="rtl"] .ab-line { overflow-wrap: anywhere; }
/* Horizontal pagers keep their scroll maths left to right (the about
   chapters, the shop rails); only the text inside each page reads RTL. */
:root[dir="rtl"] .ab-track { direction: ltr; }
:root[dir="rtl"] .ab-track > * { direction: rtl; }

/* Update sheet: what the new build brings, and a quiet "Later". */
.update-later { display: block; width: 100%; margin-top: 10px; padding: 12px; background: none; border: 1px solid var(--line); color: var(--text-dim);
  font: 600 .7rem var(--font-mono); letter-spacing: .16em; text-transform: uppercase; cursor: pointer; }
.update-later:hover { color: var(--text); border-color: var(--line-strong); }

/* "How to get your ticket" spotlight tour (static/tour.js) */
.tt { position: fixed; inset: 0; z-index: 2147483000; display: none; pointer-events: none; }
.tt.open { display: block; }
.tt-hole { position: fixed; border-radius: 10px; pointer-events: none;
  box-shadow: 0 0 0 200vmax rgba(4, 2, 8, .74), 0 0 0 2px var(--vip, #ffc60b), 0 0 26px 3px rgba(242, 184, 38, .45);
  transition: left .35s cubic-bezier(.2, .8, .2, 1), top .35s cubic-bezier(.2, .8, .2, 1), width .35s, height .35s, opacity .25s; }
.tt-card { position: fixed; max-width: calc(100vw - 24px); padding: 18px 18px 14px; pointer-events: auto; text-align: start;
  background: rgba(20, 11, 26, .98); border: 1px solid var(--vip, #ffc60b); box-shadow: 0 24px 70px rgba(0, 0, 0, .7);
  color: #fffef3; transition: left .35s cubic-bezier(.2, .8, .2, 1), top .35s cubic-bezier(.2, .8, .2, 1); animation: tt-in .3s both; }
@keyframes tt-in { from { opacity: 0; transform: translateY(8px); } }
.tt-kick { font: 600 .62rem var(--font-mono, monospace); letter-spacing: .16em; text-transform: uppercase; color: var(--vip, #ffc60b); }
.tt-t { margin: 8px 0 6px; font: 800 1.2rem/1.2 var(--font-body, system-ui); letter-spacing: -.01em; }
.tt-b { margin: 0; font-size: .92rem; line-height: 1.55; color: rgba(255, 254, 243, .82); }
.tt-wait { margin: 10px 0 0; font: 600 .68rem var(--font-mono, monospace); letter-spacing: .1em; text-transform: uppercase; color: #4ade80; animation: tt-blink 1.2s steps(2) infinite; }
@keyframes tt-blink { 50% { opacity: .45; } }
.tt-nav { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
.tt-dots { display: flex; gap: 4px; margin-inline-end: auto; }
.tt-dots i { width: 6px; height: 6px; background: rgba(255, 255, 255, .2); }
.tt-dots i.past { background: rgba(255, 198, 11, .5); } .tt-dots i.on { background: var(--vip, #ffc60b); width: 14px; }
.tt-btn { min-height: 40px; padding: 0 16px; border: 2px solid #000; background: var(--vip, #ffc60b); color: #1a1000; cursor: pointer;
  font: 700 .74rem var(--font-mono, monospace); letter-spacing: .08em; text-transform: uppercase; box-shadow: 3px 3px 0 #000; }
.tt-btn.ghost { background: transparent; color: #fffef3; border-color: rgba(255, 255, 255, .25); box-shadow: none; }
.tt-skip { display: block; margin: 10px 0 0 auto; padding: 4px 0; background: none; border: 0; color: rgba(255, 254, 243, .5); cursor: pointer;
  font: 600 .66rem var(--font-mono, monospace); letter-spacing: .12em; text-transform: uppercase; }
[dir="rtl"] .tt-skip { margin: 10px auto 0 0; }
:root[lang="fa"] .tt-t, :root[lang="fa"] .tt-kick, :root[lang="fa"] .tt-btn, :root[lang="fa"] .tt-skip, :root[lang="fa"] .tt-wait { letter-spacing: 0; text-transform: none; }
@media (prefers-reduced-motion: reduce) { .tt-hole, .tt-card { transition: none; animation: none; } .tt-wait { animation: none; } }
/* the button that starts it */
.tt-start { display: inline-flex; align-items: center; gap: 8px; padding: 0; background: none; border: 0; cursor: pointer; color: inherit;
  font: 600 .72rem var(--font-mono, monospace); letter-spacing: .12em; text-transform: uppercase; text-decoration: underline; text-underline-offset: 4px; opacity: .85; }
.tt-start:hover { opacity: 1; }
.pass-actions .tt-start, .pt-actions + .tt-start { margin-top: 16px; }

/* The welcome tour for new members (static/welcome.js): the same spotlight,
   but the page under it is blocked, and the card is a little grander. */
.wt-block { position: fixed; inset: 0; pointer-events: auto; background: transparent; cursor: not-allowed; touch-action: none; }
.wt .wt-hole { border-radius: 16px; box-shadow: 0 0 0 200vmax rgba(4, 2, 8, .8), 0 0 0 2px var(--vip, #ffc60b), 0 0 34px 6px rgba(242, 184, 38, .5);
  animation: wt-glow 2.2s ease-in-out infinite; }
@keyframes wt-glow { 50% { box-shadow: 0 0 0 200vmax rgba(4, 2, 8, .8), 0 0 0 3px var(--vip, #ffc60b), 0 0 48px 10px rgba(242, 184, 38, .62); } }
.wt.wt-solo .wt-hole { box-shadow: 0 0 0 200vmax rgba(4, 2, 8, .86); animation: none; }
.wt .wt-card { border-radius: 20px; padding: 16px 18px 14px; border: 1px solid rgba(255, 198, 11, .7); overflow: hidden;
  background: radial-gradient(120% 90% at 0% 0%, rgba(255, 198, 11, .16), transparent 55%), radial-gradient(90% 80% at 100% 100%, rgba(255, 60, 140, .14), transparent 60%), rgba(18, 10, 24, .98);
  box-shadow: 0 28px 80px rgba(0, 0, 0, .75), inset 0 1px 0 rgba(255, 255, 255, .08); }
.wt .wt-card.wt-in { animation: wt-in .38s cubic-bezier(.2, .9, .25, 1.2) both; }
@keyframes wt-in { from { opacity: 0; transform: translateY(10px) scale(.96); } }
.wt .wt-card.wt-nudge { animation: wt-nudge .4s ease; }
@keyframes wt-nudge { 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } }
.wt.wt-leave .wt-card { opacity: 0; transform: translateY(-8px); transition: opacity .18s, transform .18s; }
.wt-stages { display: flex; gap: 4px; margin: 0 0 12px; }
.wt-stages i { flex: 1; height: 4px; border-radius: 4px; background: rgba(255, 255, 255, .14); overflow: hidden; position: relative; }
.wt-stages i.past { background: rgba(255, 198, 11, .6); }
.wt-stages i.on::after { content: ""; position: absolute; inset: 0; width: var(--p, 0%); background: linear-gradient(90deg, #ffc60b, #ff7ab8); border-radius: inherit; transition: width .35s; }
[dir="rtl"] .wt-stages i.on::after { inset: 0 0 0 auto; }
.wt-head { display: flex; align-items: center; gap: 10px; }
.wt-ic { width: 40px; height: 40px; flex: none; display: grid; place-items: center; border-radius: 12px; color: #1a1000;
  background: linear-gradient(145deg, #ffe17a, #ffc60b 55%, #e09a00); box-shadow: 0 6px 18px rgba(255, 198, 11, .35), inset 0 1px 0 rgba(255, 255, 255, .6); }
.wt .tt-t { margin: 12px 0 6px; font-size: 1.3rem; }
.wt .tt-nav { margin-top: 16px; }
.wt-sp { margin-inline-end: auto; }
.wt .tt-btn { border-radius: 12px; border: 0; box-shadow: 0 6px 18px rgba(255, 198, 11, .3); min-height: 42px; }
.wt .tt-btn.ghost { border: 1px solid rgba(255, 255, 255, .25); box-shadow: none; }
@media (prefers-reduced-motion: reduce) { .wt .wt-hole, .wt .wt-card.wt-in, .wt .wt-card.wt-nudge { animation: none; } }

/* Update / install sheets: everything stays inside the card.
   The primary buttons are .full-width (100%) *and* have 28px side margins,
   which made them 56px wider than the card; the three-step strip used 1fr
   columns, which won't shrink below their content on small phones. Words
   are never broken: the title and the step labels scale with the screen. */
.app-modal #installBtn, .update-modal #updateBtn { display: flex; box-sizing: border-box; width: calc(100% - 56px); }
.update-modal .update-later { margin-left: 28px; margin-right: 28px; width: calc(100% - 56px); box-sizing: border-box; }
.app-modal h3 { font-size: min(1.65rem, 5.6vw); }   /* PANJGOOSHEH (~13em wide) fits 400 - 56px */
.app-modal h3, .app-modal-lede { margin-left: 28px; margin-right: 28px; }   /* their own rules had reset the gutter to 0 */
.app-modal-access { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.app-modal-access li { min-width: 0; font-size: min(.78rem, 3vw); }
.app-modal-eyebrow, .app-modal-lede, .app-modal-foot { overflow-wrap: break-word; }
@media (max-width: 420px) {   /* the same breakpoint as the sheet's own 18px margins */
  .app-modal-eyebrow, .app-modal h3, .app-modal-lede, .app-modal-access, .app-modal-foot,
  .update-modal .update-later { margin-left: 18px; margin-right: 18px; }
  .app-modal #installBtn, .update-modal #updateBtn { margin-left: 18px; margin-right: 18px; width: calc(100% - 36px); }
  .update-modal .update-later { width: calc(100% - 36px); }
  .app-modal-access li { padding: 10px 6px; }
}

/* ---- A page's hero, edge to edge however wide the screen ------------- */
/* Its content lines up with the page body (main.container: 1440px, --gut
   each side), via --bleed-pad. Inner parts that should also reach the edges
   use margin-inline: calc(-1 * var(--bleed-pad)). */
.bleed, .bleed-bare { --bleed-pad: max(var(--gut), calc((100vw - 1440px) / 2 + var(--gut)));
  width: 100vw; max-width: none !important; box-sizing: border-box; border-radius: 0 !important;
  margin-left: calc(50% - 50vw) !important; margin-right: calc(50% - 50vw) !important; }
.bleed { padding-left: var(--bleed-pad) !important; padding-right: var(--bleed-pad) !important; }
.bleed:not(.bleed-tight) { padding-top: clamp(24px, 4.5vw, 64px) !important; padding-bottom: clamp(22px, 4vw, 56px) !important; }

/* ---- Bottom bar: seven slots, the mark in the middle opens the sheet --- */
.bnav .bnav-i { min-width: 0; padding-left: 2px; padding-right: 2px; }
.bnav .bnav-i span { font-size: .46rem; letter-spacing: .1em; }
.bnav-moon { display: block; width: 18px; height: 18px; border-radius: 50%; box-shadow: inset -5px -2px 0 0 currentColor; transform: rotate(-20deg); }
.bnav-yalda { color: #e0203f; } .bnav-yalda.on, .bnav-yalda:hover { color: #ff3b55; }
button.bnav-mark { font: inherit; }

/* ---- Pages that open with a full-width hero: no gap above it ---------- */
/* The hero starts right under the header on a computer, and at the very top
   of the screen on a phone, which has no header (--nav-h is the notch there);
   its own padding keeps the words clear of it. */
main.container:has(.page-top) { padding-top: 0 !important; }
.page-top { margin-top: 0 !important; }
@media (max-width: 900px) {
  .page-top.page-top.page-top { padding-top: calc(var(--nav-h, 0px) + 18px) !important; }
}

/* The human check (static/captcha.js): a quiet line above a log-in button. */
.pcap { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; padding: 8px 12px; box-sizing: border-box;
  border: 1px solid var(--line-strong, rgba(255, 255, 255, .2)); background: rgba(var(--ground-rgb, 0, 0, 0), .35); color: var(--text, #fff); font-size: .8rem; text-align: start; }
.pcap-box { display: grid; place-items: center; flex: none; width: 22px; height: 22px; border: 2px solid var(--line-strong, rgba(255, 255, 255, .3)); border-radius: 4px; }
.pcap[data-state="work"] .pcap-box i { width: 11px; height: 11px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: pcap-spin .8s linear infinite; }
.pcap[data-state="ok"] .pcap-box { background: #22c55e; border-color: #22c55e; }
.pcap[data-state="ok"] .pcap-box i { width: 6px; height: 11px; margin-top: -2px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }
.pcap[data-state="err"] { cursor: pointer; border-color: #ff7a7a; }
.pcap[data-state="err"] .pcap-box { border-color: #ff7a7a; }
.pcap[data-state="err"] .pcap-box i::before { content: "!"; color: #ff7a7a; font: 800 .8rem/1 var(--font-body, system-ui); font-style: normal; }
.pcap-t { flex: 1; min-width: 0; }
.pcap-k { flex: none; font: .5rem var(--font-mono, monospace); letter-spacing: .14em; color: var(--muted, rgba(255, 255, 255, .55)); }
@keyframes pcap-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .pcap[data-state="work"] .pcap-box i { animation-duration: 2.4s; } }

/* ---- footer: a banner, app-like shortcuts on phones, folding columns ---- */
.ft-banner { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 14px 26px; max-width: 1440px; width: 100%; margin: 0 auto 36px;
  min-height: 150px; padding: 22px 28px; border-radius: 22px; overflow: hidden; background: #e0203f; color: #0b0b0b; text-decoration: none; transition: transform .14s cubic-bezier(.22, 1, .36, 1); }
.ft-banner:active { transform: scale(.99); }
.ft-banner-txt { display: grid; gap: 6px; max-width: 560px; }
.ft-banner-txt b { font: 400 clamp(1.4rem, 4vw, 2.2rem)/1 var(--font-display, system-ui); text-transform: uppercase; }
.ft-banner-txt > span:last-child { font-size: .9rem; line-height: 1.5; color: rgba(11, 11, 11, .78); }
.ft-nk { display: inline-flex; align-items: center; gap: 14px; } .ft-nk img { height: 60px; width: auto; } .ft-nk i { font-style: normal; font-weight: 800; font-size: 1.3rem; }
.ft-banner-go { display: inline-flex; align-items: center; gap: 6px; min-height: 46px; padding: 0 20px; border-radius: 999px; background: #0b0b0b; color: #fff; font-weight: 800; font-size: .9rem; }
[dir="rtl"] .ft-banner-go svg { transform: scaleX(-1); }
.ft-apps { display: none; }
.ft-col summary { list-style: none; cursor: default; }
.ft-col summary::-webkit-details-marker { display: none; }
.ft-col summary h4 { display: inline; }
.ft-social { display: flex; gap: 8px; margin-top: 16px; }
.ft-social a { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--line); color: var(--text-dim); }
.ft-social a:hover { color: var(--text); border-color: var(--text-dim); }
.footer-inner.ft-cols { grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr)); }
@media (max-width: 900px) {
  .ft-banner { min-height: 120px; padding: 18px; margin-bottom: 20px; grid-template-columns: minmax(0, 1fr); }
  .ft-nk { order: -1; } .ft-nk img { height: 40px; }
  .ft-banner-go { justify-self: start; }
  .ft-apps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin: 0 auto 18px; width: 100%; }
  .ft-apps a { display: grid; justify-items: center; gap: 6px; padding: 10px 2px; border-radius: 16px; color: var(--text); text-decoration: none; font-size: .68rem; text-align: center; }
  .ft-apps i { display: grid; place-items: center; width: 52px; height: 52px; border-radius: 16px; font-style: normal;
    background: linear-gradient(160deg, rgba(255, 255, 255, .1), rgba(255, 255, 255, .03)); border: 1px solid var(--line); box-shadow: 0 8px 20px rgba(0, 0, 0, .25); }
  .ft-apps a:active i { transform: scale(.94); }
  .footer-inner.ft-cols { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .footer-brand { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 6px 2px 12px; }
  .ft-social { margin-top: 0; }
  .footer-col.ft-col { display: block; border-top: 1px solid var(--line); padding: 0 2px; }
  .ft-col summary { display: flex; justify-content: space-between; align-items: center; padding: 14px 0; cursor: pointer; }
  .ft-col summary::after { content: "+"; font-size: 1.1rem; color: var(--muted); }
  .ft-col[open] summary::after { content: "–"; }
  .ft-col summary h4 { margin: 0; }
  .footer-col.ft-col a { display: block; padding: 9px 0; }
  .footer-col.footer-explore.ft-col { display: block; }
  .footer-col.footer-explore.ft-col a { display: block; }
  .site-footer.ft { padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 96px); }
}
