/* zerb.az — Design Tokens
   ------------------------------------------------------------------
   MIRRORED FROM THE PRODUCT, NOT INVENTED.
   Every value below is copied verbatim from the app's own
   /static/design-system.css (DL-215 palette, DL-098 type system).
   The site and the app must look like one family — so when a token
   changes in the app, it changes here too.

   Source of truth: ../../static/design-system.css
   Do not add a colour here that does not exist there. If the site
   genuinely needs a new value, add it to the app first.
   ------------------------------------------------------------------ */

/* IBM Plex Sans — the same three subset files the app self-hosts
   (DL-098). Latin covers AZ/EN, latin-ext covers ə/ı/ğ/ş/ç/ö/ü,
   cyrillic covers RU. Kept as three files so an AZ visitor on mobile
   data never downloads the Cyrillic subset. */
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/ibm-plex-sans-latin.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+2000-206F, U+20AC, U+2122;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/ibm-plex-sans-latin-ext.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1EFF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  src: url('../fonts/ibm-plex-sans-cyrillic.woff2') format('woff2');
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0400-04FF, U+2116;
}
/* The wordmark, and ONLY the wordmark.

   Zilla Slab SemiBold, SIL OFL 1.1, (c) 2017 The Mozilla Foundation —
   licence in ../fonts/OFL-zilla-slab.txt and inside the file's own name
   table. No Reserved Font Name, unlike IBM Plex ("Plex"), so the family
   keeps its real name.

   Subset to the four characters of "Zerb" plus kerning: 3 KB against the
   full face's 264 KB. That is also why the family is named for its JOB
   rather than for the typeface — anything but "Zerb" set in it would come
   out as fallback glyphs, and the name should say so at the call site.

   Deliberately carries NO unicode-range: this face must never be picked up
   by general text. It applies where .brand__name and .site-foot__mark ask
   for it, nowhere else. That also keeps it invisible to build-site.py's
   _unicode_ranges(), which reads the ibm-plex-sans-* blocks only. */
@font-face {
  font-family: 'Zerb Wordmark';
  src: url('../fonts/zilla-slab-semibold-wordmark.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* Metric-compatible fallback, same override values the app computed
   from this exact font file's OS/2 + hhea tables against Arial's
   published metrics. Minimises the reflow when the webfont swaps in. */
@font-face {
  font-family: 'IBM Plex Sans Fallback';
  src: local('Arial');
  size-adjust: 120.75%;
  ascent-override: 84.89%;
  descent-override: 22.77%;
  line-gap-override: 0%;
}

:root {
  /* ---- Brand (DL-215) ---------------------------------------- */
  --ds-brand: #0E6E5E;
  --ds-brand-hover: #0B5C4F;
  --ds-brand-tint: #EEF9F7;
  --ds-brand-tint-text: #0A5145;
  --ds-brand-tint-hover: #DFF4F0;

  /* The app's one sanctioned gradient (Home's hero card). Still used for
     section 8 and the Ödə button, so the site and the app keep a shared
     surface. White text clears WCAG AA against every sampled stop —
     measured in the app, 8.07–8.72:1 light. */
  --ds-gradient-hero-from: #0E6E5E;
  --ds-gradient-hero-to: #044339;
  --ds-gradient-hero: linear-gradient(135deg, var(--ds-gradient-hero-from) 0%, var(--ds-gradient-hero-to) 100%);
  --ds-text-on-gradient: #FFFFFF;
  --ds-text-on-gradient-secondary: rgba(255, 255, 255, .92);

  /* ================================================================
     THE HERO FIELD — site-only, and ALWAYS DARK
     ----------------------------------------------------------------
     Owner amendment (2026-07-27): the hero is the site's dramatic
     opening, not a theme state. It is a deep indigo field in both
     light and dark, and the pulse trace is the light source in it —
     which only reads if the field is genuinely dark, not merely
     saturated. The old brand gradient was too bright for the trace to
     light anything.

     These four values do NOT exist in the app, and that is a
     deliberate, named exception to this file's own "mirror, never
     invent" rule: the app has no dramatic opening to mirror. The hue
     is still the brand's own indigo, taken down in lightness rather
     than swapped for a different colour, so the family holds.
     ================================================================ */
  --hero-field-from: #0E2E28;
  --hero-field-to:   #061A17;
  --hero-field: radial-gradient(120% 90% at 22% 0%, #123F38 0%, rgba(18,63,56,0) 62%),
                linear-gradient(160deg, var(--hero-field-from) 0%, var(--hero-field-to) 100%);
  /* The glow the trace casts onto the field. Not decoration: it is what
     makes the line read as the source of the light rather than a shape
     drawn on top of it. */
  --hero-glow: rgba(80, 200, 175, .30);

  /* Text on the hero's white CTA. Pinned here — not a hero invention
     like the four values above, but the app's own light-theme
     --ds-brand-tint-text, held fixed. The CTA's fill is #fff in BOTH
     themes because the field it sits on is; a token that flips with
     the theme therefore put dark's light periwinkle (#62CBB9) on white
     at 1.7:1. This value is 9.4:1 on that same white. */
  --hero-btn-text: #0A5145;

  /* Text placed ON a solid --ds-brand fill. Light's brand is a deep
     violet so this is white; dark's brand is a light periwinkle, so the
     dark block below flips it to near-black. Same token, same pairing,
     same two values as the app's .ds-btn-primary. */
  --ds-text-on-brand: #FFFFFF;

  /* ---- Surfaces & text -------------------------------------- */
  --ds-surface: #FFFFFF;
  --ds-page-bg: #F0F6F5;
  --ds-text-primary: #0F1514;
  --ds-text-secondary: #3E4A48;
  --ds-text-tertiary: #56605E;
  --ds-text-quiet: #5C6866;
  --ds-text-faint: #656F6E;
  --ds-text-placeholder: #BDCCCA;
  --ds-border: #E6EEEC;
  --ds-border-strong: #D4E0DE;
  --ds-neutral-badge-bg: #ECF2F1;

  /* ---- Semantic ---------------------------------------------- */
  --ds-success: #077E13;
  --ds-success-tint: #EEF9EF;
  --ds-success-text: #0A5711;
  --ds-error: #B53C3C;
  --ds-error-tint: #FCEFEE;
  --ds-error-text: #8F2B2B;
  --ds-warning: #A96A16;
  --ds-warning-tint: #FAF1E3;
  --ds-warning-text: #7D5410;
  --ds-info: #0E6E5E;

  /* Module accents — the app's two named exceptions to the
     one-hue rule (Commerce, Documents). Used sparingly on the site
     for the same modules they represent in the product. */
  --ds-commerce: #14659E;
  --ds-commerce-tint: #EDF5FA;
  --ds-documents: #9E23BE;
  --ds-documents-tint: #F7EBFB;

  /* ---- Spacing ----------------------------------------------- */
  --ds-space-1: 4px;
  --ds-space-2: 8px;
  --ds-space-3: 12px;
  --ds-space-4: 16px;
  --ds-space-5: 20px;
  --ds-space-6: 24px;
  --ds-space-7: 28px;
  --ds-space-8: 32px;

  /* ---- Radii ------------------------------------------------- */
  --ds-radius-sm: 6px;
  --ds-radius-control: 8px;
  --ds-radius-md: 10px;
  --ds-radius-lg: 12px;
  --ds-radius-card: 16px;
  --ds-radius-pill: 999px;

  /* ---- Shadows (brand-tinted, layered — DL-215) -------------- */
  --ds-shadow-color: rgba(31, 27, 79, .08);
  --ds-shadow-card: 0 1px 2px rgba(31, 27, 79, .05), 0 4px 12px rgba(31, 27, 79, .07);
  --ds-shadow-hero: 0 2px 4px rgba(31, 27, 79, .07), 0 8px 28px rgba(31, 27, 79, .12);
  --ds-shadow-overlay: 0 16px 40px rgba(31, 27, 79, .14), 0 2px 8px rgba(31, 27, 79, .08);

  /* ---- Motion ------------------------------------------------ */
  --ds-duration-fast: 120ms;
  --ds-duration-base: 180ms;
  --ds-duration-slow: 250ms;
  --ds-ease-standard: cubic-bezier(.4, 0, .2, 1);
  --ds-ease-decelerate: cubic-bezier(.16, 1, .3, 1);
  --ds-ease-linear: linear;

  /* ================================================================
     THE PULSE SPINE — site-only, and deliberately ONE clock.
     ----------------------------------------------------------------
     Every looping animation on this site derives its timing from
     --pulse-period. Nothing on the site animates on its own private
     schedule. That is what makes the motion read as coherent rather
     than busy: the hero trace, the section reveals, the counters and
     the interaction ripples are all phases of the same beat.

     THE CYCLE (owner-chosen, 2026-07-26): the line DRAWS itself from
     zero, then ERASES from behind, forever. It is not a static graphic
     with a light moving over it — two earlier attempts did that and the
     owner read both as lifeless.

     8.4s total, split 70 / 30:
       0 → 70%   the head travels left→right, writing the day  (5.88s)
       70 → 100% the tail catches up, wiping it clean          (2.52s)

     The erase is deliberately faster than the draw. Writing is the
     content; wiping is just the reset, and lingering over it would
     leave the hero dead for the back half of every loop.

     The four beats sit at 15 / 40 / 65 / 90% of the band, which is
     where the QRS spikes actually are in the SVG path (x =
     180/480/780/1080 of a 1200-unit viewBox). A beat is lit the moment
     the head reaches it — at 0.7 × its band fraction, since the whole
     draw happens inside the first 70% of the cycle. That works out to
     one beat every 1.47s: the "orta" pace the owner picked.

     Every delay below is calc()'d off those fractions, never hand-typed
     as seconds — retiming the whole site is still a one-value edit.
     ================================================================ */
  --pulse-period: 8.4s;
  /* 0.7 × band fraction — see the derivation above. */
  --pulse-beat-1: calc(var(--pulse-period) * 0.105);
  --pulse-beat-2: calc(var(--pulse-period) * 0.280);
  --pulse-beat-3: calc(var(--pulse-period) * 0.455);
  --pulse-beat-4: calc(var(--pulse-period) * 0.630);
}

/* ================================================================
   DARK THEME
   ----------------------------------------------------------------
   Selected exactly the way the app selects it (static/theme.css):
   the system preference applies only while the visitor has made no
   explicit choice, and `data-theme` on <html> beats it in both
   directions. The inline script in <head> sets that attribute before
   first paint, so there is no flash of the wrong theme.

   The theme NEVER follows the visitor's clock or location. That would
   override a choice they already made, require guessing a timezone,
   and make every screenshot and test irreproducible. The day→night
   arc further down belongs to the SHOP's day, not to theirs.

   Every value below is copied verbatim from the app's own dark block
   (static/design-system.css) — nothing here is a site-local invention.
   The duplicate selector list is the standard way to say this without
   a preprocessor, and is what the app does too.

   The hero is absent from this block ON PURPOSE: it is a fixed dark
   field in both themes now (see --hero-field above), so there is no
   dark variant of it to declare.
   ================================================================ */
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]):not([data-theme="dark"]) {
    --ds-brand: #0DA58C;
    --ds-brand-hover: #3BBAA5;
    --ds-brand-tint: #1B3733;
    --ds-brand-tint-text: #62CBB9;
    --ds-brand-tint-hover: #24443F;

    --ds-surface: #171C1B;
    --ds-page-bg: #0D100F;

    --ds-text-primary: #EEF3F3;
    --ds-text-secondary: #BFCBC9;
    --ds-text-tertiary: #A6B2B0;
    --ds-text-quiet: #92A09D;
    --ds-text-faint: #8F9795;
    --ds-text-placeholder: #56605E;

    --ds-border: #252D2C;
    --ds-border-strong: #343C3B;
    --ds-neutral-badge-bg: #242B29;

    --ds-success: #6CD079;
    --ds-success-tint: #213D25;
    --ds-success-text: #6CD079;
    --ds-error: #E5766F;
    --ds-error-tint: #3A2422;
    --ds-error-text: #E5766F;
    --ds-warning: #D4A24C;
    --ds-warning-tint: #332818;
    --ds-warning-text: #D4A24C;
    --ds-info: #0DA58C;

    --ds-commerce: #54A7E3;
    --ds-commerce-tint: #1C3242;
    --ds-documents: #CA69E3;
    --ds-documents-tint: #331E38;

    /* Dark's brand is a light periwinkle meant to sit ON a dark surface,
       so text placed on a --ds-brand FILL must be dark, not white. The
       app's own --ds-text-on-brand, same reasoning, same value. */
    --ds-text-on-brand: #0F1514;

    --ds-shadow-color: rgba(0, 0, 0, .45);
    --ds-shadow-card: 0 1px 2px rgba(0, 0, 0, .35), 0 4px 14px rgba(0, 0, 0, .45);
    --ds-shadow-hero: 0 2px 4px rgba(0, 0, 0, .35), 0 8px 28px rgba(0, 0, 0, .5);
    --ds-shadow-overlay: 0 16px 40px rgba(0, 0, 0, .55), 0 2px 8px rgba(0, 0, 0, .4);
  }
}

/* The same values under an explicit choice. Kept as a literal copy
   rather than a shared class because a token file has no @extend and
   the alternative — a JS-applied class — would flash on first paint. */
html[data-theme="dark"] {
  --ds-brand: #0DA58C;
  --ds-brand-hover: #3BBAA5;
  --ds-brand-tint: #1B3733;
  --ds-brand-tint-text: #62CBB9;
  --ds-brand-tint-hover: #24443F;

  --ds-surface: #171C1B;
  --ds-page-bg: #0D100F;

  --ds-text-primary: #EEF3F3;
  --ds-text-secondary: #BFCBC9;
  --ds-text-tertiary: #A6B2B0;
  --ds-text-quiet: #92A09D;
  --ds-text-faint: #8F9795;
  --ds-text-placeholder: #56605E;

  --ds-border: #252D2C;
  --ds-border-strong: #343C3B;
  --ds-neutral-badge-bg: #242B29;

  --ds-success: #6CD079;
  --ds-success-tint: #213D25;
  --ds-success-text: #6CD079;
  --ds-error: #E5766F;
  --ds-error-tint: #3A2422;
  --ds-error-text: #E5766F;
  --ds-warning: #D4A24C;
  --ds-warning-tint: #332818;
  --ds-warning-text: #D4A24C;
  --ds-info: #0DA58C;

  --ds-commerce: #54A7E3;
  --ds-commerce-tint: #1C3242;
  --ds-documents: #CA69E3;
  --ds-documents-tint: #331E38;

  /* Dark's brand is a light periwinkle meant to sit ON a dark surface,
     so text placed on a --ds-brand FILL must be dark, not white. The
     app's own --ds-text-on-brand, same reasoning, same value. */
  --ds-text-on-brand: #0F1514;

  --ds-shadow-color: rgba(0, 0, 0, .45);
  --ds-shadow-card: 0 1px 2px rgba(0, 0, 0, .35), 0 4px 14px rgba(0, 0, 0, .45);
  --ds-shadow-hero: 0 2px 4px rgba(0, 0, 0, .35), 0 8px 28px rgba(0, 0, 0, .5);
  --ds-shadow-overlay: 0 16px 40px rgba(0, 0, 0, .55), 0 2px 8px rgba(0, 0, 0, .4);
}


/* ================================================================
   THE DAY→NIGHT ARC  (owner amendment to the motion spine, 2026-07-27)
   ----------------------------------------------------------------
   The «Kassanı aç» section carries the SHOP's day as light. Five
   stops, named after five real moments of that day:

     morning    kassa açılır       — first light, warm
     midday     satışlar           — flat bright, no drama
     afternoon  qaytarma           — the light goes amber
     evening    kassa bağlanır     — dusk, violet
     night      Z-hesabat          — the kəsir is the only lit thing

   WHAT DRIVES IT — and the one place this deviates from the brief.
   The brief says scroll-driven. The five beats above are produced by
   CLICKS, not by scrolling: a visitor stands still and works the till.
   Bound to scroll, the light would be at midnight while they ring up
   their first sale — the shift would stop describing the story it
   exists to tell. So POSITION in the arc is the simulation's own step,
   and SCROLL governs only whether the arc is engaged at all (it fades
   out at the section edges, which is also how the rest of the page
   gets its stable readable theme back). Nothing hijacks scrolling.

   WHY THE SKY AND THE FRAME BEHAVE DIFFERENTLY.
   Only --arc-sky-* animates. The frame's palette switches instantly.
   That is not laziness, it is the AA constraint: interpolating a light
   surface with dark text toward a dark surface with light text passes
   through a midpoint where both sit near the same lightness — measured
   at roughly 1.1:1, i.e. invisible text for half a second. An instant
   switch has no midpoint to fail. The sky carries the drama because
   the sky is the one surface with no text on it; the till reads like a
   screen changing mode, which is what it is.

   The frame's morning→evening surfaces are all within a few percent of
   each other, so switching them instantly is imperceptible anyway.
   ================================================================ */

/* Registered so the two sky stops can actually interpolate. Everything
   else about the arc is a discrete state, on purpose (see above). */
@property --arc-sky-from {
  syntax: '<color>'; inherits: true; initial-value: #F0F6F5;
}
@property --arc-sky-to {
  syntax: '<color>'; inherits: true; initial-value: #F0F6F5;
}

:root {
  --arc-duration: 1100ms;

  /* Light base theme. Text stays #0F1514 from morning through evening,
     so nothing crosses; only night flips, and night flips instantly. */
  --arc-morning-sky-from:   #FFF1DC;  --arc-morning-sky-to:   #F6EFF7;
  --arc-midday-sky-from:    #EDF5FF;  --arc-midday-sky-to:    #F0F6F5;
  --arc-afternoon-sky-from: #FFE9CB;  --arc-afternoon-sky-to: #F6EDF2;
  --arc-evening-sky-from:   #F0D5E2;  --arc-evening-sky-to:   #DCD2EC;
  --arc-night-sky-from:     #171043;  --arc-night-sky-to:     #08061A;

  --arc-morning-surface:   #FFFCF7;
  --arc-midday-surface:    #FFFFFF;
  --arc-afternoon-surface: #FFFAF2;
  --arc-evening-surface:   #FCF8FD;
}

@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]):not([data-theme="dark"]) {
    /* Dark base: every stop is already dark, so NOTHING crosses at any
       point of the arc — including night. The arc reads as the room
       around the till changing, not as the till changing. */
    --arc-morning-sky-from:   #241B26;  --arc-morning-sky-to:   #121017;
    --arc-midday-sky-from:    #161A24;  --arc-midday-sky-to:    #0D100F;
    --arc-afternoon-sky-from: #271B22;  --arc-afternoon-sky-to: #131015;
    --arc-evening-sky-from:   #1D1436;  --arc-evening-sky-to:   #0E0B1E;
    --arc-night-sky-from:     #120C33;  --arc-night-sky-to:     #060411;

    /* GREY, NOT GREEN — hue removed, lightness kept (owner call).
       DL-362 pushed these three toward the new brand so the simulated
       till would match the real one. Measured against the app it
       overshot: the app's own dark surface is #171C1B, whose green lead
       over red is +5; these carried +16, +13 and +29, and at that
       strength the reader sees a green box rather than a dark one. Each
       value below is the neutral grey with the SAME CIELAB L* as the
       colour it replaces (16.54 / 14.90 / 19.41), so only the hue is
       gone — every contrast ratio measured inside the till is
       unchanged. Midday is not in the list: it IS the app's surface,
       copied verbatim, and neutralising it would make the replica less
       faithful, not more. */
    --arc-morning-surface:   #292929;
    --arc-midday-surface:    #171C1B;
    --arc-afternoon-surface: #252525;
    --arc-evening-surface:   #2F2F2F;
  }
}
html[data-theme="dark"] {
  --arc-morning-sky-from:   #241B26;  --arc-morning-sky-to:   #121017;
  --arc-midday-sky-from:    #161A24;  --arc-midday-sky-to:    #0D100F;
  --arc-afternoon-sky-from: #271B22;  --arc-afternoon-sky-to: #131015;
  --arc-evening-sky-from:   #1D1436;  --arc-evening-sky-to:   #0E0B1E;
  --arc-night-sky-from:     #120C33;  --arc-night-sky-to:     #060411;

  /* Same three greys as the media-query block above — see the note there
     for why the hue came out and why midday keeps the app's own value. */
  --arc-morning-surface:   #292929;
  --arc-midday-surface:    #171C1B;
  --arc-afternoon-surface: #252525;
  --arc-evening-surface:   #2F2F2F;
}
