/* Shared across chekino_login.html, chekino_dashboard.html, chekino_admin.html.
   This file is the single source of truth for the design system: the brand
   font, the colour primitives, the semantic roles every page styles through,
   and the spacing / type / radius / motion scales. Page stylesheets add
   layout on top of these but never invent their own palette or sizes.

   The system follows two rules borrowed from Linear:

     1 · The data layer is flat. Tables, panels, filter bars and cards carry
         a 1px line and nothing else — no shadow. Depth is reserved for
         things that genuinely float above the page (modals, popovers,
         dropdowns, the command palette). That's why --shadow-1 is `none`:
         every data surface already asks for it, so flattening happens here
         instead of in three page stylesheets.

     2 · Hierarchy comes from weight, size and spacing — not from colour or
         ornament. Colour carries meaning only: the accent means "this is
         interactive", and the status colours mean state. Neither is ever
         decoration.

   Themes are resolved here too, for all three pages at once, in three states:
     · bare :root                      → light
     · prefers-color-scheme: dark      → dark, unless the user forced light
     · html[data-theme="dark"]         → dark, whatever the OS says
*/
@font-face {
  font-family: 'IRANYekanX';
  src: url('/fonts/IRANYekanXVFaNumVF.woff2') format('woff2'),
       url('/fonts/IRANYekanXVFaNumVF.ttf') format('truetype');
  font-weight: 100 1000;
  font-display: swap;
}

/* ════════════════════════════════════════════════════════════════
   1 · PRIMITIVES — raw scales. Components never reference these
   directly; they go through the semantic roles in section 2.
   The neutrals carry a slight blue bias so they sit with the brand
   blue instead of reading as flat, unconsidered grey.
   ════════════════════════════════════════════════════════════════ */
:root {
  --n-1:  #FBFCFD;  --n-2:  #F6F8FA;  --n-3:  #EDF0F4;  --n-4:  #E4E8EE;
  --n-5:  #D9DEE7;  --n-6:  #C7CEDA;  --n-7:  #A8B2C3;  --n-8:  #8792A6;
  --n-9:  #67728A;  --n-10: #4A5568;  --n-11: #2C3648;  --n-12: #0F1728;

  --blue-wash: #EEF4FF;  --blue-soft: #DCE8FF;  --blue-line: #A8C6FF;
  --blue-base: #0B5CFF;  --blue-deep: #0A4ED6;

  --green-wash: #E7F6EE;  --green-base: #12855A;
  --amber-wash: #FDF3E4;  --amber-base: #B26A08;
  --red-wash:   #FDECEC;  --red-base:   #C4342B;  --red-line: #F3C6C2;

  /* ── spacing: 4pt grid, seven steps, nothing off-scale ── */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px;

  /* ── radius, assigned by role ──
     Data surfaces and controls share one soft value. Floating things get
     slightly more, which is what makes them read as lifted even before the
     shadow registers. */
  --rad-ctl: 6px;    /* inputs, buttons, chips, table/panel surfaces */
  --rad-card: 6px;   /* panels, cards — same value, named by role */
  --rad-float: 8px;  /* modals, popovers, dropdowns, command palette */
  --rad-pill: 999px;

  /* ── type scale: seven steps, no half-pixels ── */
  --t-micro: 12px; --t-cap: 13px; --t-body: 14px; --t-value: 15px;
  --t-sub: 17px;   --t-title: 21px; --t-display: 28px;

  /* ── control + row heights ──
     --h-row is the list/table rhythm: roomy enough to scan comfortably,
     tighter than the old 56px so more cheques fit on one screen. */
  --h-sm: 32px; --h-md: 40px; --h-lg: 48px; --h-row: 44px;

  /* ── font weight axes (IRANYekanX is variable, 100–1000) ──
     Large text is deliberately not bold. The weight that reads as premium
     at display sizes is a medium one — linear.app sets its 64px headline at
     510 — and letting size carry the emphasis instead of weight is most of
     what separates an elegant heading from a shouty one. These sit a little
     above Inter's numbers because Persian script, being cursive and
     lower-contrast, thins out faster than Latin at the same weight. */
  --f-brand:  'wght' 700, 'dots' 2;
  --f-title:  'wght' 620, 'dots' 2;
  --f-label:  'wght' 600, 'dots' 2;
  --f-btn:    'wght' 600, 'dots' 2;
  --f-value:  'wght' 520, 'dots' 2;
  --f-num:    'wght' 560, 'dots' 2;
  --f-body:   'wght' 430, 'dots' 2;
  --f-hint:   'wght' 330, 'dots' 2;
  --f-micro:  'wght' 480, 'dots' 2;

  /* ── motion ──
     Everything the user causes lands inside 200ms; the common case is
     140ms. Only opacity, transform and colour are animated — never a
     property that forces layout. */
  --dur-1: 90ms;    /* instant feedback: hover, press */
  --dur-2: 140ms;   /* the default */
  --dur-3: 200ms;   /* entrances, state changes worth noticing */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);   /* overshoot-free entrances */
}

/* ════════════════════════════════════════════════════════════════
   2 · SEMANTIC ROLES — one token per purpose, so the "wrong blue"
   can't be picked by accident. The accent means exactly one thing:
   this is interactive. Status colours are reserved for state and
   are never used as decoration.
   ════════════════════════════════════════════════════════════════ */
:root {
  --bg: var(--n-2);
  --surface: #FFFFFF;
  --surface-2: var(--n-1);
  --surface-sunken: var(--n-3);

  /* Three border tiers. With shadows gone from the data layer, these lines
     carry all of the structure, so which tier a line uses is the difference
     between a panel reading as one object or as loose parts:
       subtle → row dividers, internal separators
       default → inputs, buttons, table headers
       strong → outer edges of a panel, sticky headers, filter bars */
  --border-subtle: var(--n-3);
  --border: var(--n-4);
  --border-strong: var(--n-6);

  --ink: var(--n-12);
  --ink-2: var(--n-10);
  --muted: var(--n-9);

  --accent: var(--blue-base);
  --accent-hover: var(--blue-deep);
  --accent-text: var(--blue-deep);
  --accent-wash: var(--blue-wash);
  --accent-line: var(--blue-line);

  --state-idle: var(--n-10);   --state-idle-bg: var(--n-3);      --state-idle-dot: var(--n-8);
  --state-ok: var(--green-base);   --state-ok-bg: var(--green-wash);
  --state-warn: var(--amber-base); --state-warn-bg: var(--amber-wash);
  --state-bad: var(--red-base);    --state-bad-bg: var(--red-wash);

  /* The data layer is flat: every panel, table and bar in the app asks for
     --shadow-1, and it resolves to nothing. Structure comes from the border
     tiers and from stepping the background between layers. */
  --shadow-1: none;
  /* Reserved for genuinely floating surfaces. Two stacked shadows: a tight
     dark one that reads as contact, and a wide soft one that reads as height. */
  --shadow-2: 0 1px 2px rgba(15, 23, 40, 0.10), 0 12px 32px -8px rgba(15, 23, 40, 0.18);
  --shadow-float: var(--shadow-2);
  /* On light there is no lit edge to simulate — the border already reads. */
  --inset-hairline: none;

  --skeleton-base: var(--n-3);
  --skeleton-sheen: var(--n-1);

  /* ── legacy aliases: the three page stylesheets were written against
     these names, so they keep resolving — now to system values. ── */
  --white: #FFFFFF;
  --blue-900: var(--accent-text);
  --blue-hover: var(--accent-hover);
  --blue-700: var(--accent);
  --blue-600: var(--accent-line);
  --blue-100: var(--accent-wash);
  --error: var(--state-bad);
  --error-bg: var(--state-bad-bg);
  --error-border: var(--red-line);
  --success: var(--state-ok);
  --success-bg: var(--state-ok-bg);
  --success-border: #9BDDBB;
  --card-bg: var(--surface);
}

/* The dark palette, defined once. Both selectors below load the same
   values so the OS setting and the in-app toggle can't drift apart. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* Near-black, neutral — not a blue-black. The surfaces above it are the
       same colour lifted by a few percent of white, which is how the site
       this is modelled on separates layers: by light, not by hue. */
    --bg: #08090A;
    --surface: #0F1011;        /* bg + 3% white */
    --surface-2: #141516;      /* bg + 5% white */
    --surface-sunken: #0B0C0D;

    /* Lines are translucent white rather than a lighter grey. On a near-black
       ground that reads as an edge catching light instead of a stroke drawn
       on top, and it stays correct over whatever surface sits beneath it. */
    --border-subtle: rgba(255, 255, 255, 0.05);
    --border: rgba(255, 255, 255, 0.08);
    --border-strong: rgba(255, 255, 255, 0.12);

    --ink: #F7F8F8;
    --ink-2: #D0D6E0;
    --muted: #8A8F98;

    --accent: #4C8DFF;
    --accent-hover: #6BA3FF;
    --accent-text: #8FBAFF;
    --accent-wash: rgba(76, 141, 255, 0.13);
    --accent-line: rgba(76, 141, 255, 0.38);

    --state-idle: #AEB8C8;   --state-idle-bg: rgba(255, 255, 255, 0.06); --state-idle-dot: #8A8F98;
    --state-ok: #4CC38A;     --state-ok-bg: rgba(76, 195, 138, 0.13);
    --state-warn: #E8A63F;   --state-warn-bg: rgba(232, 166, 63, 0.13);
    --state-bad: #FF8078;    --state-bad-bg: rgba(255, 128, 120, 0.13);

    --shadow-1: none;
    /* Four stacked shadows that tighten as they darken, the way the site does
       it. One big soft shadow reads as a drop shadow; this reads as an object
       resting on a surface. */
    --shadow-2:
      0 8px 2px rgba(0, 0, 0, 0),
      0 5px 2px rgba(0, 0, 0, 0.02),
      0 3px 2px rgba(0, 0, 0, 0.06),
      0 1px 1px rgba(0, 0, 0, 0.10),
      0 16px 40px -12px rgba(0, 0, 0, 0.7);
    /* An inner hairline of white — what makes a dark panel look lit from
       inside its own edge rather than cut out of the page. */
    --inset-hairline: inset 0 0 0 1px rgba(255, 255, 255, 0.05);

    --skeleton-base: rgba(255, 255, 255, 0.05);
    --skeleton-sheen: rgba(255, 255, 255, 0.10);

    --blue-600: var(--accent-line);
    --error-border: rgba(255, 128, 120, 0.32);
    --success-border: rgba(76, 195, 138, 0.32);
  }
}
:root[data-theme="dark"] {
  /* Near-black, neutral — not a blue-black. The surfaces above it are the
     same colour lifted by a few percent of white, which is how the site
     this is modelled on separates layers: by light, not by hue. */
  --bg: #08090A;
  --surface: #0F1011;        /* bg + 3% white */
  --surface-2: #141516;      /* bg + 5% white */
  --surface-sunken: #0B0C0D;

  /* Lines are translucent white rather than a lighter grey. On a near-black
     ground that reads as an edge catching light instead of a stroke drawn
     on top, and it stays correct over whatever surface sits beneath it. */
  --border-subtle: rgba(255, 255, 255, 0.05);
  --border: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.12);

  --ink: #F7F8F8;
  --ink-2: #D0D6E0;
  --muted: #8A8F98;

  --accent: #4C8DFF;
  --accent-hover: #6BA3FF;
  --accent-text: #8FBAFF;
  --accent-wash: rgba(76, 141, 255, 0.13);
  --accent-line: rgba(76, 141, 255, 0.38);

  --state-idle: #AEB8C8;   --state-idle-bg: rgba(255, 255, 255, 0.06); --state-idle-dot: #8A8F98;
  --state-ok: #4CC38A;     --state-ok-bg: rgba(76, 195, 138, 0.13);
  --state-warn: #E8A63F;   --state-warn-bg: rgba(232, 166, 63, 0.13);
  --state-bad: #FF8078;    --state-bad-bg: rgba(255, 128, 120, 0.13);

  --shadow-1: none;
  /* Four stacked shadows that tighten as they darken, the way the site does
     it. One big soft shadow reads as a drop shadow; this reads as an object
     resting on a surface. */
  --shadow-2:
    0 8px 2px rgba(0, 0, 0, 0),
    0 5px 2px rgba(0, 0, 0, 0.02),
    0 3px 2px rgba(0, 0, 0, 0.06),
    0 1px 1px rgba(0, 0, 0, 0.10),
    0 16px 40px -12px rgba(0, 0, 0, 0.7);
  /* An inner hairline of white — what makes a dark panel look lit from
     inside its own edge rather than cut out of the page. */
  --inset-hairline: inset 0 0 0 1px rgba(255, 255, 255, 0.05);

  --skeleton-base: rgba(255, 255, 255, 0.05);
  --skeleton-sheen: rgba(255, 255, 255, 0.10);

  --blue-600: var(--accent-line);
  --error-border: rgba(255, 128, 120, 0.32);
  --success-border: rgba(76, 195, 138, 0.32);
}

/* ════════════════════════════════════════════════════════════════
   3 · BASELINE — the few rules that belong to every page.
   ════════════════════════════════════════════════════════════════ */

/* Persian script is cursive and tall; the browser default (~1.2) crowds
   the ascenders and descenders together. */
body { line-height: 1.7; }

/* Keyboard users get a visible, branded ring; pointer users never see it.
   Inputs keep their own focus treatment and are left out. */
button:focus-visible,
a:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--rad-ctl);
}

::selection { background: var(--accent); color: #fff; }

/* Digits line up column-to-column instead of jittering by glyph width —
   it matters most anywhere amounts or dates stack vertically. */
.num, .amount, .fig { font-variant-numeric: tabular-nums; }

/* Serial numbers, sayad ids and national ids are machine values, not prose.
   Tabular figures plus a touch of tracking makes them read as data at a
   glance and makes a wrong digit easier to spot — the job a monospace font
   does in a Latin UI, done with the one font that has Persian numerals. */
.data-value {
  font-variant-numeric: tabular-nums;
  font-variation-settings: var(--f-num);
  letter-spacing: 0.02em;
}

/* A press should register before the network does. 90ms, transform only —
   never a property that forces layout. */
button:not(:disabled):active { transform: scale(0.97); }
button { transition: transform var(--dur-1) var(--ease); }

/* Thin, self-effacing scrollbars: the content is the subject, not the
   chrome around it. */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--rad-pill);
  border: 3px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: content-box; }

/* One central honouring of the OS setting, for all three pages. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ════════════════════════════════════════════════════════════════
   4 · SHARED COMPONENTS
   Things more than one page renders. They live here so the dashboard
   and the admin panel can't drift apart on them.
   ════════════════════════════════════════════════════════════════ */

/* ---- Command palette (⌘K) ----
   The one surface in the app that is deliberately theatrical: it arrives
   over a blurred page, because it is a mode, and the user needs to know
   the rest of the screen is inert while it's up. */
.cp-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 900;
  background: rgba(15, 23, 40, 0.38);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  padding: 12vh 16px 16px;
  justify-content: center;
  align-items: flex-start;
}
:root[data-theme="dark"] .cp-overlay { background: rgba(0, 0, 0, 0.55); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .cp-overlay { background: rgba(0, 0, 0, 0.55); }
}
.cp-overlay.show { display: flex; animation: cpFade var(--dur-2) var(--ease) both; }
.cp-overlay.show .cp-box { animation: cpRise var(--dur-3) var(--ease-out) both; }
@keyframes cpFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes cpRise {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.cp-box {
  width: 100%;
  max-width: 560px;
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--rad-float);
  box-shadow: var(--shadow-2);
  overflow: hidden;
  font-family: 'IRANYekanX', 'Tahoma', sans-serif;
}

.cp-search {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: 0 var(--s3);
  height: 52px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.cp-search-icon { width: 17px; height: 17px; color: var(--muted); flex-shrink: 0; }
.cp-search input {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: none;
  outline: none;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  font-size: var(--t-value);
  font-variation-settings: var(--f-body);
}
.cp-search input::placeholder { color: var(--muted); }

.cp-list { overflow-y: auto; padding: var(--s1) 0 var(--s2); }
.cp-group {
  padding: var(--s3) var(--s4) var(--s1);
  font-size: var(--t-micro);
  color: var(--muted);
  font-variation-settings: var(--f-label);
  letter-spacing: 0.04em;
}
.cp-item {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin: 0 var(--s2);
  padding: 0 var(--s2);
  height: var(--h-md);
  border-radius: var(--rad-ctl);
  cursor: pointer;
  color: var(--ink);
  font-size: var(--t-body);
}
.cp-item.is-active { background: var(--accent-wash); }
.cp-icon {
  width: 18px; height: 18px;
  display: grid; place-items: center;
  color: var(--muted);
  flex-shrink: 0;
}
.cp-item.is-active .cp-icon { color: var(--accent-text); }
.cp-icon svg { width: 16px; height: 16px; }
.cp-title { font-variation-settings: var(--f-value); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cp-hint {
  color: var(--muted);
  font-size: var(--t-cap);
  font-variation-settings: var(--f-hint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cp-keys { margin-inline-start: auto; display: flex; gap: var(--s1); flex-shrink: 0; }
.cp-empty {
  display: none;
  padding: var(--s6) var(--s4);
  text-align: center;
  color: var(--muted);
  font-size: var(--t-cap);
}
.cp-foot {
  display: flex;
  gap: var(--s4);
  padding: var(--s2) var(--s4);
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-2);
  color: var(--muted);
  font-size: var(--t-micro);
  flex-shrink: 0;
  flex-wrap: wrap;
}
.cp-foot span { display: inline-flex; align-items: center; gap: var(--s1); }

/* One key chip style, used by the palette footer, the command rows and
   anywhere else a shortcut is shown. */
kbd {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--rad-ctl);
  color: var(--ink-2);
  font-family: inherit;
  font-size: var(--t-micro);
  font-variation-settings: var(--f-micro);
  line-height: 1;
}
.cp-esc { flex-shrink: 0; }

@media (max-width: 560px) {
  .cp-overlay { padding: 8vh 12px 12px; }
  .cp-box { max-height: 78vh; }
  .cp-hint { display: none; }
  .cp-foot { display: none; }
}

/* ════════════════════════════════════════════════════════════════
   5 · THE SITE FINISH
   Four details carried over from linear.app itself. Each is small; the
   combination is most of why that page reads as expensive.
   ════════════════════════════════════════════════════════════════ */

/* ── Tracking tightens as type grows ──
   Letter-spacing on the site scales negatively with size: roughly -0.022em
   at display sizes, easing to normal by body copy. Large text set at default
   tracking is the single most common tell of an unconsidered interface. */
.brand h1,
.header-logo,
.topbar h1 { letter-spacing: -0.02em; }

/* ── Buttons are pills ──
   Eighty-two elements on that page carry a 9999px radius. It is the most
   recognisable thing about the design after the palette. Inputs and data
   surfaces keep the 6px from the system scale, so the shape itself tells you
   which things you press and which things you read. */
:root button.btn-primary,
:root button.btn-add,
:root button.submit,
:root .add-check-btn,
:root .btn-ghost,
:root .icon-action,
:root .filter-pill-btn,
:root .filter-clear-btn,
:root .ths-report-btn,
:root .tab-btn,
:root .cp-item,
:root .modal-actions button,
:root .confirm-actions button,
:root .btn-inline,
:root .status-btn,
:root .status-filter-chip,
:root .ths-count,
:root .badge,
:root .ms-chip,
:root .file-chip,
:root .ac-tag,
:root .due-alert-count,
:root .export-opt,
:root .st-opt { border-radius: var(--rad-pill); }

/* ── Panels are lit from inside their own edge ──
   A translucent white hairline set inside the border. On the light theme it
   resolves to nothing, because there is no darkness for an edge to catch. */
:root .table-wrap,
:root .filter-bar,
:root .due-alert-bar,
:root .card,
:root .login-card,
:root .modal-box,
:root .confirm-box,
:root .cp-box,
:root .filter-popover,
:root .cal-popup,
:root .status-menu,
:root .ac-list,
:root .ms-list { box-shadow: var(--shadow-1), var(--inset-hairline); }

/* The floating set keeps its own depth, with the hairline on top of it. */
:root .modal-box,
:root .confirm-box,
:root .cp-box,
:root .filter-popover,
:root .cal-popup,
:root .status-menu,
:root .ac-list,
:root .ms-list { box-shadow: var(--shadow-2), var(--inset-hairline); }

/* ── An ambient pool of light behind the page ──
   Not a gradient people should notice; a very slight lift at the top of the
   viewport so the page doesn't read as a flat sheet of black. Fixed, so it
   costs one paint and never moves. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(60% 50% at 50% 0%, rgba(255, 255, 255, 0.035) 0%, rgba(255, 255, 255, 0) 100%);
}
:root:not([data-theme="dark"]) body::before { background: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body::before {
    background: radial-gradient(60% 50% at 50% 0%, rgba(255, 255, 255, 0.035) 0%, rgba(255, 255, 255, 0) 100%);
  }
}
