/* Fastify web pages: the "Ink & Blue" palette of the 1.9 design system as CSS variables.
 *
 * Source of truth: docs/DESIGN_SYSTEM.md and app/lib/ui/design/tokens.dart (AppColors.dark / AppColors.light); web_test.go
 * compares every value below with tokens.dart when the app is checked out next to the web folder.
 *
 * Dark ("Ink") is the default, exactly as in the app. Light ("Paper") applies when the visitor's system asks for it
 * (prefers-color-scheme: light) unless the page sets data-theme="dark" on <html>; data-theme="light" forces it.
 * Pages link this file AFTER their own <style> so that the tokens win: the older names (--bg, --surface, --text, --violet,
 * --teal ...) are aliases of the new tokens, which re-colours the existing rules without touching them. No script, no
 * external resource, no gradients (flat surfaces and 1 px hairlines, as in the app). Direction-neutral: no left/right
 * literals, the pages stay RTL-correct (the English lines carry dir="ltr").
 */

/* ---------------------------------------------------------------- the bundled Persian face (web/fonts, SIL OFL 1.1: fonts/OFL.txt)
 * The same Vazirmatn files as the app and the admin console; same-origin (the pages' CSP has font-src 'self'). A page without the
 * folder falls back to the system fonts of its font-family list. */
@font-face { font-family: 'Vazirmatn'; src: url('fonts/Vazirmatn-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Vazirmatn'; src: url('fonts/Vazirmatn-Medium.ttf') format('truetype'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Vazirmatn'; src: url('fonts/Vazirmatn-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; }

/* ---------------------------------------------------------------- tokens: dark (default) */
:root {
  color-scheme: dark;
  --fy-bg: #0B1220;
  --fy-surface: #111A2B;
  --fy-surface-high: #18243A;
  --fy-surface-highest: #1F2E48;
  --fy-outline: #2A3A55;
  --fy-outline-strong: #5F7190;
  --fy-text: #E8EEF8;
  --fy-text-secondary: #A9B6CB;
  --fy-text-tertiary: #8E9CB4;
  --fy-primary: #6FA8FF;
  --fy-fill: #2A66E0;
  --fy-fill-hover: #2560D6;
  --fy-fill-pressed: #1F55C4;
  --fy-on-fill: #FFFFFF;
  --fy-focus: #9CC2FF;
  --fy-success: #3DD6A3;
  --fy-success-fill: #0F7D5C;
  --fy-warning: #F5B546;
  --fy-danger: #FF7A7A;
  --fy-danger-fill: #C93C3C;
  --fy-info: #6FA8FF;
  --fy-ultra: #C4B5FF;
  --fy-ultra-fill: #6A4FE0;
  /* status tints: the accent at alpha 0.20 (dark) / 0.13 (light), the value the app ships */
  --fy-success-tint: rgba(61, 214, 163, .20);
  --fy-warning-tint: rgba(245, 181, 70, .20);
  --fy-danger-tint: rgba(255, 122, 122, .20);
  --fy-info-tint: rgba(111, 168, 255, .20);
  --fy-ultra-tint: rgba(196, 181, 255, .20);
  /* label on a solid status colour (web only: dark ink on the light dark-theme accents) */
  --fy-on-status: #0B1220;
  --fy-shadow: 0 8px 28px rgba(0, 0, 0, .3);
}

/* ---------------------------------------------------------------- tokens: light */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --fy-bg: #F4F6FA;
    --fy-surface: #FFFFFF;
    --fy-surface-high: #EBF0F7;
    --fy-surface-highest: #E1E8F2;
    --fy-outline: #CBD5E3;
    --fy-outline-strong: #74849D;
    --fy-text: #0F1B2D;
    --fy-text-secondary: #46566E;
    --fy-text-tertiary: #55657D;
    --fy-primary: #1D5FD0;
    --fy-fill: #1D5FD0;
    --fy-fill-hover: #164EB0;
    --fy-fill-pressed: #123F8F;
    --fy-on-fill: #FFFFFF;
    --fy-focus: #1D5FD0;
    --fy-success: #0A6F52;
    --fy-success-fill: #0A6F52;
    --fy-warning: #7F4E00;
    --fy-danger: #B42318;
    --fy-danger-fill: #B42318;
    --fy-info: #1A57BF;
    --fy-ultra: #8A2BB0;
    --fy-ultra-fill: #8A2BB0;
    --fy-success-tint: rgba(10, 111, 82, .13);
    --fy-warning-tint: rgba(127, 78, 0, .13);
    --fy-danger-tint: rgba(180, 35, 24, .13);
    --fy-info-tint: rgba(26, 87, 191, .13);
    --fy-ultra-tint: rgba(138, 43, 176, .13);
    --fy-on-status: #FFFFFF;
    --fy-shadow: 0 8px 28px rgba(15, 27, 45, .12);
  }
}
:root[data-theme="light"] {
  color-scheme: light;
  --fy-bg: #F4F6FA;
  --fy-surface: #FFFFFF;
  --fy-surface-high: #EBF0F7;
  --fy-surface-highest: #E1E8F2;
  --fy-outline: #CBD5E3;
  --fy-outline-strong: #74849D;
  --fy-text: #0F1B2D;
  --fy-text-secondary: #46566E;
  --fy-text-tertiary: #55657D;
  --fy-primary: #1D5FD0;
  --fy-fill: #1D5FD0;
  --fy-fill-hover: #164EB0;
  --fy-fill-pressed: #123F8F;
  --fy-on-fill: #FFFFFF;
  --fy-focus: #1D5FD0;
  --fy-success: #0A6F52;
  --fy-success-fill: #0A6F52;
  --fy-warning: #7F4E00;
  --fy-danger: #B42318;
  --fy-danger-fill: #B42318;
  --fy-info: #1A57BF;
  --fy-ultra: #8A2BB0;
  --fy-ultra-fill: #8A2BB0;
  --fy-success-tint: rgba(10, 111, 82, .13);
  --fy-warning-tint: rgba(127, 78, 0, .13);
  --fy-danger-tint: rgba(180, 35, 24, .13);
  --fy-info-tint: rgba(26, 87, 191, .13);
  --fy-ultra-tint: rgba(138, 43, 176, .13);
  --fy-on-status: #FFFFFF;
  --fy-shadow: 0 8px 28px rgba(15, 27, 45, .12);
}

/* ---------------------------------------------------------------- aliases of the older page variables */
:root {
  --bg: var(--fy-bg);
  --bg-2: var(--fy-surface-high);
  --surface: var(--fy-surface);
  --surface-2: var(--fy-surface-high);
  --line: var(--fy-outline);
  --text: var(--fy-text);
  --muted: var(--fy-text-secondary);
  --violet: var(--fy-fill);
  --violet-2: var(--fy-primary);
  --teal: var(--fy-fill);
  --teal-2: var(--fy-primary);
  --amber: var(--fy-warning);
  --red: var(--fy-danger);
  --green: var(--fy-success);
}

/* ---------------------------------------------------------------- focus: a visible 2 px ring on every page (never colour alone)
 * --fy-focus reaches 3:1 on every surface of both palettes. :where() keeps the specificity at zero, so a page can still style its
 * own ring; it must not remove it. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible { outline: 2px solid var(--fy-focus); outline-offset: 2px; }

/* ---------------------------------------------------------------- forms of the sign-in pages (login, register, trial)
 * A message under the field it belongs to (announced through the field's aria-describedby and the live region), the field marked
 * aria-invalid; the show-password button sits inside the field at its end and the field keeps room for it (the password is LTR,
 * so the wrapper is LTR too: the end is the right edge of both). */
.fy-field-error { display: block; margin-top: 6px; font-size: 13px; line-height: 1.6; color: var(--fy-danger); font-weight: 500; }
.fy-field-error:empty { display: none; }
.fy-field-error:not(:empty)::before { content: '! '; font-weight: 700; }
input[aria-invalid="true"] { border-color: var(--fy-danger) !important; }
.fy-pw { position: relative; direction: ltr; }
.fy-pw > input { padding-inline-end: 52px !important; }
.fy-pw > .fy-eye { position: absolute; inset-block: 0; inset-inline-end: 4px; margin-block: auto; width: 44px; height: 40px; display: grid; place-items: center;
  padding: 0; background: transparent; border: 0; border-radius: 8px; color: var(--fy-text-secondary); cursor: pointer; }
.fy-pw > .fy-eye:hover { color: var(--fy-text); background: var(--fy-surface-highest); }
.fy-eye svg { width: 22px; height: 22px; display: block; }
.fy-eye[aria-pressed="true"] .eye-open, .fy-eye[aria-pressed="false"] .eye-shut { display: none; }
.fy-brand-mark { width: 56px; height: 56px; margin: 0 auto 12px; border-radius: 14px; display: grid; place-items: center; font-weight: 700; font-size: 26px;
  background: var(--fy-fill); color: var(--fy-on-fill); }

/* ---------------------------------------------------------------- shared look of the user pages (flat, hairlines)
 * Scoped to <body class="fy-app"> (dashboard, pay, status): login, register, trial and payment-result style themselves
 * with the tokens above and must not inherit these generic class names. The extra class beats the pages' inline rules. */
body.fy-app { background: var(--fy-bg); color: var(--fy-text); }
.fy-app a { color: var(--fy-primary); }
.fy-app .card { background: var(--fy-surface); border: 1px solid var(--fy-outline); box-shadow: none; }
.fy-app .brand-mark, .fy-app .mark { background: var(--fy-fill); color: var(--fy-on-fill); }
.fy-app .btn { border-color: var(--fy-outline-strong); background: var(--fy-surface-high); color: var(--fy-text); }
.fy-app .btn:hover { border-color: var(--fy-primary); }
.fy-app .btn.primary, .fy-app .btn.teal { background: var(--fy-fill); border-color: transparent; color: var(--fy-on-fill); }
.fy-app .btn.primary:hover, .fy-app .btn.teal:hover { background: var(--fy-fill-hover); }
.fy-app .btn.primary:active, .fy-app .btn.teal:active { background: var(--fy-fill-pressed); }
.fy-app .btn.ghost { background: transparent; }
.fy-app .btn.danger { color: var(--fy-danger); }
.fy-app .link { color: var(--fy-primary); }
.fy-app input[type=text], .fy-app input[type=number], .fy-app input[type=email] { background: var(--fy-surface-high); border-color: var(--fy-outline-strong); color: var(--fy-text); }
.fy-app input:focus, .fy-app .btn:focus-visible, .fy-app .method:focus-visible, .fy-app .plan:focus-visible,
.fy-app button:focus-visible, .fy-app a:focus-visible { outline: 2px solid var(--fy-focus); outline-offset: 2px; }
.fy-app .alert.ok { background: var(--fy-success-tint); border-color: var(--fy-success); color: var(--fy-text); }
.fy-app .alert.warn { background: var(--fy-warning-tint); border-color: var(--fy-warning); color: var(--fy-text); }
.fy-app .alert.bad { background: var(--fy-danger-tint); border-color: var(--fy-danger); color: var(--fy-text); }
.fy-app .badge { border-color: var(--fy-outline-strong); background: var(--fy-surface-high); }
.fy-app .badge.ok { color: var(--fy-success); border-color: var(--fy-success); }
.fy-app .badge.warn { color: var(--fy-warning); border-color: var(--fy-warning); }
.fy-app .badge.bad { color: var(--fy-danger); border-color: var(--fy-danger); }
.fy-app .plan { background: var(--fy-surface-high); border-color: var(--fy-outline); }
.fy-app .plan:hover, .fy-app .plan.popular { border-color: var(--fy-primary); }
.fy-app .plan.gaming, .fy-app .plan.gaming:hover { border-color: var(--fy-ultra); }
.fy-app .plan .tag { background: var(--fy-fill); color: var(--fy-on-fill); }
.fy-app .plan .price, .fy-app .big, .fy-app .copyrow .amount { color: var(--fy-text); }
.fy-app .method { background: var(--fy-surface-high); border-color: var(--fy-outline); }
.fy-app .method.sel { border-color: var(--fy-primary); box-shadow: 0 0 0 1px var(--fy-primary) inset; }
.fy-app .copyrow { background: var(--fy-surface-high); border-color: var(--fy-outline); }
.fy-app .bar { background: var(--fy-surface-high); border-color: var(--fy-outline); }
.fy-app .bar i { background: var(--fy-primary); }
.fy-app .bar.ultra i { background: var(--fy-ultra); }
.fy-app .toast { background: var(--fy-surface-highest); border-color: var(--fy-outline); box-shadow: var(--fy-shadow); }
.fy-app .toast.bad { border-color: var(--fy-danger); color: var(--fy-text); }
.fy-app th, .fy-app td { border-bottom-color: var(--fy-outline); }
.fy-app .total { border-top-color: var(--fy-outline); }
.fy-app .timer { color: var(--fy-warning); }
/* status page */
.fy-app .banner { background: var(--fy-surface); border-color: var(--fy-outline); }
.fy-app .banner .icon { color: var(--fy-on-status); }
.fy-app .banner.operational { border-color: var(--fy-success); }
.fy-app .banner.degraded { border-color: var(--fy-warning); }
.fy-app .banner.outage { border-color: var(--fy-danger); }
.fy-app .banner.unknown .icon { background: var(--fy-outline-strong); color: var(--fy-on-fill); }
.fy-app .item { background: var(--fy-surface); border-color: var(--fy-outline); }
.fy-app .track { background: var(--fy-surface-high); }
.fy-app .track > i { background: var(--fy-primary); }
.fy-app .empty { background: transparent; }
.fy-app header button, .fy-app .foot button { background: var(--fy-surface-high); border-color: var(--fy-outline-strong); color: var(--fy-text); }
.fy-app header button:hover, .fy-app .foot button:hover { background: var(--fy-surface-highest); }


/* ---------------------------------------------------------------- the Ultra Gaming block (plan cards, checkout, dashboard)
 * Ultra is never told apart by colour alone: violet + the bolt glyph + the word "Ultra" in the label. The normal quota
 * and the Ultra quota are two separate labelled blocks. */
.quotas { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; margin: 8px 0; }
.quota-block { border: 1px solid var(--fy-outline); border-radius: 10px; background: var(--fy-surface); padding: 8px 10px; min-width: 0; }
.quota-block .q-label { display: block; color: var(--fy-text-secondary); font-size: 12.5px; }
.quota-block .q-value { display: block; width: fit-content; font-size: 18px; font-weight: 700; direction: ltr; unicode-bidi: isolate; }
.quota-block.ultra { border-color: var(--fy-ultra); background: var(--fy-ultra-tint); }
.quota-block.ultra .q-label { color: var(--fy-ultra); font-weight: 700; }
.ultra-bolt { display: inline-block; margin-inline-end: 4px; }
.ultra-block { display: block; }
.ultra-note { display: block; margin: 6px 0 0; font-size: 12.5px; color: var(--fy-text-secondary); line-height: 1.6; }
.ultra-note .en { display: block; direction: ltr; text-align: start; unicode-bidi: isolate; }
.ultra-note + .ultra-note { margin-top: 4px; }
.ultra-valid { display: block; margin: 2px 0 0; font-size: 12.5px; color: var(--fy-text-secondary); }
.plan.gaming { border-color: var(--fy-ultra); }
.plan .kind-badge { align-self: flex-start; display: inline-block; font-size: 12px; border-radius: 8px; padding: 0 8px; border: 1px solid var(--fy-ultra); color: var(--fy-ultra); }
.ultra-bar-label { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; margin: 6px 0 4px; }
.ultra-bar-label b { color: var(--fy-ultra); }
.ultra-pad { margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--fy-outline); }
