/* mochi-ds tokens.css: "Washi Kisetsu" design tokens.
   Custom properties and @font-face only. URLs are relative to this file, so it
   works when linked cross-origin from /ds/. Contrast numbers: DESIGN.md
   (generated by assets-src/contrast.py from this file). */

/* ===== Fonts ===================================================== */
@font-face {
  font-family: "Mochi Serif";
  src: url("fonts/source-serif-4-display.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Mochi Mincho";
  src: url("fonts/shippori-mincho-b1-jp.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+3000-30FF, U+4E00-9FFF, U+FF00-FFEF;
}

/* ===== Primitives (never change with theme or season) =============== */
:root {
  /* washi: paper */
  --m-paper-50: #FFFCF7;
  --m-paper-100: #FBF7F0;
  --m-paper-200: #F3EDE2;
  --m-paper-300: #EAE1D2;

  /* sumi: ink, warm-tinted greys */
  --m-sumi-50: #F5F1EC;
  --m-sumi-100: #E8E2DA;
  --m-sumi-200: #D3CABF;
  --m-sumi-300: #B6AA9C;
  --m-sumi-400: #978A7B;
  --m-sumi-500: #7A6D60;
  --m-sumi-600: #5F544A;
  --m-sumi-700: #4B423A;
  --m-sumi-800: #342D27;
  --m-sumi-900: #1F1A16;
  --m-sumi-950: #120F0C;

  /* yoru: night washi (sumi-black paper) */
  --m-yoru-700: #2C241D;
  --m-yoru-800: #211B16;
  --m-yoru-900: #16120E;
  --m-yoru-950: #0F0C09;

  /* shu: vermilion. 400 is the night-washi fill (see DESIGN.md: #D2463A
     nudged to pass 4.5:1 under white labels). */
  --m-shu-50: #FBEDEA;
  --m-shu-100: #F5D6D1;
  --m-shu-400: #CF4338;
  --m-shu-500: #C8322B;
  --m-shu-600: #A9271F;
  --m-shu-700: #8A1F19;

  /* kin: gold */
  --m-kin-300: #E6C688;
  --m-kin-400: #D8A852;
  --m-kin-500: #B8893A;
  --m-kin-600: #8A6522;
  --m-kin-700: #6B4E1A;

  /* seasons */
  --m-spring-sakura: #E8A0B4;
  --m-spring-sakura-deep: #C25B78;
  --m-spring-matcha: #7E9A5B;
  --m-summer-ai: #2E4B7C;
  --m-summer-hydrangea: #7488C8;
  --m-summer-hanabi: #D9A441;
  --m-autumn-momiji: #C8432B;
  --m-autumn-ginkgo: #D9A21B;
  --m-autumn-persimmon: #E0702A;
  --m-winter-tsubaki: #B32839;
  --m-winter-snow: #EEF1F3;
  --m-winter-pine: #3F5A4A;
}

/* ===== Semantic: light (washi) ====================================== */
:root, html[data-theme="light"] {
  --m-bg: #F3EDE2;
  --m-bg-grain: url("assets/paper.webp"); /* mochi.js rewrites to an absolute URL */
  --m-grain-opacity: .55;
  --m-surface: #FBF7F0;
  --m-surface-2: #F7F1E7;
  --m-surface-sunken: #EAE1D2;
  --m-hairline: rgba(70, 50, 30, .12);
  --m-card-border: rgba(70, 50, 30, .08);

  --m-text: #1F1A16;
  --m-text-2: #5F544A;
  --m-text-3: #6A5E52;
  --m-text-on-accent: #FFFFFF;

  --m-accent: #C8322B;
  --m-accent-pressed: #A9271F;
  --m-accent-tint: rgba(200, 50, 43, .10);
  --m-accent-text: #A9271F;
  --m-gold: #8A6522;
  --m-gold-tint: rgba(184, 137, 58, .14);

  --m-success: #3D6B44;
  --m-success-tint: rgba(61, 107, 68, .12);
  --m-warning: #85570F;
  --m-warning-tint: rgba(196, 138, 40, .16);
  --m-danger: #A3302A;
  --m-danger-tint: rgba(163, 48, 42, .10);
  --m-info: #36557F;
  --m-info-tint: rgba(54, 85, 127, .10);

  --m-focus: #2E5A9C;
  --m-focus-ring: 0 0 0 2px var(--m-bg), 0 0 0 4px var(--m-focus);
  --m-tabbar-bg: rgba(251, 247, 240, .82);
  --m-tabbar-blur: saturate(1.4) blur(18px);
  --m-scrim: rgba(31, 26, 22, .38);
  --m-skeleton: #EAE2D5;
  --m-skeleton-shine: rgba(255, 252, 246, .7);

  /* Telegram chrome: hex only, read by Mochi.tg.paint() */
  --m-tg-header: #F3EDE2;
  --m-tg-bg: #F3EDE2;

  /* elevation: warm brown paper shadows, never black */
  --m-elev-0: none;
  --m-elev-1: 0 1px 1px rgba(70, 46, 24, .04), 0 2px 8px rgba(70, 46, 24, .05);
  --m-elev-2: 0 1px 2px rgba(70, 46, 24, .05), 0 6px 18px rgba(70, 46, 24, .07);
  --m-elev-3: 0 2px 4px rgba(70, 46, 24, .06), 0 12px 32px rgba(70, 46, 24, .10);
  --m-elev-4: 0 4px 8px rgba(70, 46, 24, .07), 0 24px 56px rgba(70, 46, 24, .14);
  --m-elev-press: 0 1px 1px rgba(70, 46, 24, .05), inset 0 1px 2px rgba(70, 46, 24, .06);
}

/* ===== Semantic: dark (night washi) ================================= */
html[data-theme="dark"] {
  --m-bg: #16120E;
  --m-grain-opacity: .18;
  --m-surface: #211B16;
  --m-surface-2: #2A231C;
  --m-surface-sunken: #0F0C09;
  --m-hairline: rgba(214, 170, 90, .14);
  --m-card-border: rgba(214, 170, 90, .22);

  --m-text: #F2E9DB;
  --m-text-2: #C9BBA7;
  --m-text-3: #A99B88;
  --m-text-on-accent: #FFFFFF;

  --m-accent: #CF4338;
  --m-accent-pressed: #B3352B;
  --m-accent-tint: rgba(210, 70, 58, .16);
  --m-accent-text: #F08C7F;
  --m-gold: #D8A852;
  --m-gold-tint: rgba(216, 168, 82, .14);

  --m-success: #94C38E;
  --m-success-tint: rgba(148, 195, 142, .14);
  --m-warning: #E2B463;
  --m-warning-tint: rgba(226, 180, 99, .14);
  --m-danger: #EE8B7F;
  --m-danger-tint: rgba(238, 139, 127, .14);
  --m-info: #98B0DA;
  --m-info-tint: rgba(152, 176, 218, .14);

  --m-focus: #E6C688;
  --m-tabbar-bg: rgba(33, 27, 22, .82);
  --m-scrim: rgba(8, 6, 4, .6);
  --m-skeleton: #2A231C;
  --m-skeleton-shine: rgba(242, 233, 219, .06);

  --m-tg-header: #16120E;
  --m-tg-bg: #16120E;

  /* deeper shadows plus a faint gold top edge */
  --m-elev-1: inset 0 1px 0 rgba(214, 170, 90, .06), 0 2px 8px rgba(0, 0, 0, .32);
  --m-elev-2: inset 0 1px 0 rgba(214, 170, 90, .07), 0 6px 18px rgba(0, 0, 0, .40);
  --m-elev-3: inset 0 1px 0 rgba(214, 170, 90, .08), 0 12px 32px rgba(0, 0, 0, .48);
  --m-elev-4: inset 0 1px 0 rgba(214, 170, 90, .09), 0 24px 56px rgba(0, 0, 0, .56);
  --m-elev-press: inset 0 1px 3px rgba(0, 0, 0, .35);
}

/* ===== Season layer (accents only; base washi/sumi never changes) ====
   season-1 primary accent, -2/-3 supporting decoration, -tint wash,
   -ink the AA-safe text variant. Label text lives in Mochi.season.meta;
   mochi.js mirrors it into --m-season-label (a CSS string) on <html>.
   Default (no attribute) = autumn. */
:root, html[data-season="autumn"] {
  --m-season-1: var(--m-autumn-momiji);
  --m-season-2: var(--m-autumn-ginkgo);
  --m-season-3: var(--m-autumn-persimmon);
  --m-season-tint: rgba(200, 67, 43, .10);
  --m-season-ink: #A3361F;
}
html[data-season="spring"] {
  --m-season-1: var(--m-spring-sakura);
  --m-season-2: var(--m-spring-sakura-deep);
  --m-season-3: var(--m-spring-matcha);
  --m-season-tint: rgba(232, 160, 180, .20);
  --m-season-ink: #A13F5D;
}
html[data-season="summer"] {
  --m-season-1: var(--m-summer-ai);
  --m-season-2: var(--m-summer-hydrangea);
  --m-season-3: var(--m-summer-hanabi);
  --m-season-tint: rgba(116, 136, 200, .16);
  --m-season-ink: #2E4B7C;
}
html[data-season="winter"] {
  --m-season-1: var(--m-winter-tsubaki);
  --m-season-2: var(--m-winter-pine);
  --m-season-3: var(--m-winter-snow);
  --m-season-tint: rgba(179, 40, 57, .09);
  --m-season-ink: #9C2434;
}
html[data-theme="dark"], html[data-theme="dark"][data-season="autumn"] {
  --m-season-1: #DE5A3F;
  --m-season-tint: rgba(222, 90, 63, .14);
  --m-season-ink: #EE9070;
}
html[data-theme="dark"][data-season="spring"] {
  --m-season-1: var(--m-spring-sakura);
  --m-season-tint: rgba(232, 160, 180, .14);
  --m-season-ink: #EFAEC0;
}
html[data-theme="dark"][data-season="summer"] {
  --m-season-1: var(--m-summer-hydrangea);
  --m-season-2: #4F6FA8;
  --m-season-tint: rgba(116, 136, 200, .16);
  --m-season-ink: #A6B6E6;
}
html[data-theme="dark"][data-season="winter"] {
  --m-season-1: #D24A5A;
  --m-season-2: #7FA08C;
  --m-season-tint: rgba(210, 74, 90, .14);
  --m-season-ink: #EE98A1;
}

/* ===== Telegram mapping ================================================
   The brand colours win: we do NOT consume --tg-theme-bg-color,
   -secondary-bg-color, -text-color, -hint-color, -link-color,
   -button-color, -button-text-color, -header-bg-color, -bottom-bar-bg-color,
   -accent-text-color, -section-bg-color, -section-header-text-color,
   -section-separator-color, -subtitle-text-color, -destructive-text-color.
   Telegram's colorScheme only decides light vs dark. Instead we push our
   paper colour to Telegram: Mochi.tg.paint() reads --m-tg-header / --m-tg-bg
   and calls setHeaderColor / setBackgroundColor / setBottomBarColor.
   We DO consume Telegram's safe-area vars (below). */

/* ===== Type ============================================================ */
:root {
  --m-font-display: "Mochi Serif", "Mochi Mincho", ui-serif, "New York", Georgia, serif;
  --m-font-jp: "Mochi Mincho", "Hiragino Mincho ProN", "Yu Mincho", serif;
  --m-font-ui: system-ui, -apple-system, "SF Pro Text", "Helvetica Neue", sans-serif;
  --m-font-mono: ui-monospace, "SF Mono", Menlo, monospace;

  --m-weight-regular: 400;
  --m-weight-medium: 500;
  --m-weight-semibold: 600;
  --m-weight-bold: 700;

  /* iOS-like scale: size / line-height */
  --m-fs-hero: 40px;        --m-lh-hero: 44px;
  --m-fs-large-title: 34px; --m-lh-large-title: 41px;
  --m-fs-title-1: 28px;     --m-lh-title-1: 34px;
  --m-fs-title-2: 22px;     --m-lh-title-2: 28px;
  --m-fs-title-3: 20px;     --m-lh-title-3: 25px;
  --m-fs-headline: 17px;    --m-lh-headline: 22px;
  --m-fs-body: 17px;        --m-lh-body: 22px;
  --m-fs-callout: 16px;     --m-lh-callout: 21px;
  --m-fs-subhead: 15px;     --m-lh-subhead: 20px;
  --m-fs-footnote: 13px;    --m-lh-footnote: 18px;
  --m-fs-caption: 12px;     --m-lh-caption: 16px;
  --m-fs-caption-2: 11px;   --m-lh-caption-2: 13px;

  /* font shorthands */
  --m-type-hero: var(--m-weight-bold) var(--m-fs-hero)/var(--m-lh-hero) var(--m-font-display);
  --m-type-large-title: var(--m-weight-bold) var(--m-fs-large-title)/var(--m-lh-large-title) var(--m-font-display);
  --m-type-title-1: var(--m-weight-semibold) var(--m-fs-title-1)/var(--m-lh-title-1) var(--m-font-display);
  --m-type-title-2: var(--m-weight-semibold) var(--m-fs-title-2)/var(--m-lh-title-2) var(--m-font-display);
  --m-type-title-3: var(--m-weight-semibold) var(--m-fs-title-3)/var(--m-lh-title-3) var(--m-font-ui);
  --m-type-headline: var(--m-weight-semibold) var(--m-fs-headline)/var(--m-lh-headline) var(--m-font-ui);
  --m-type-body: var(--m-weight-regular) var(--m-fs-body)/var(--m-lh-body) var(--m-font-ui);
  --m-type-callout: var(--m-weight-regular) var(--m-fs-callout)/var(--m-lh-callout) var(--m-font-ui);
  --m-type-subhead: var(--m-weight-regular) var(--m-fs-subhead)/var(--m-lh-subhead) var(--m-font-ui);
  --m-type-footnote: var(--m-weight-regular) var(--m-fs-footnote)/var(--m-lh-footnote) var(--m-font-ui);
  --m-type-caption: var(--m-weight-medium) var(--m-fs-caption)/var(--m-lh-caption) var(--m-font-ui);
  --m-type-caption-2: var(--m-weight-medium) var(--m-fs-caption-2)/var(--m-lh-caption-2) var(--m-font-ui);

  --m-tracking-display: -0.02em;
  --m-tracking-title: -0.01em;
  --m-tracking-body: 0;
  --m-tracking-caption: 0.01em;
  --m-tracking-jp: 0.04em;
  --m-numeric: tabular-nums; /* font-variant-numeric */
}

/* ===== Space, layout, safe areas ======================================
   4pt grid. The number is the multiple of 4px: --m-space-6 = 24px. */
:root {
  --m-space-0: 0;
  --m-space-0-5: 2px;
  --m-space-1: 4px;
  --m-space-2: 8px;
  --m-space-3: 12px;
  --m-space-4: 16px;
  --m-space-5: 20px;
  --m-space-6: 24px;
  --m-space-7: 28px;
  --m-space-8: 32px;
  --m-space-10: 40px;
  --m-space-12: 48px;
  --m-space-14: 56px;
  --m-space-16: 64px;
  --m-space-20: 80px;
  --m-space-24: 96px;

  --m-gutter: 16px;

  /* device inset (env or Telegram's safe area, whichever is larger)
     plus Telegram's own fullscreen chrome (content safe area) */
  --m-safe-top-device: max(env(safe-area-inset-top, 0px), var(--tg-safe-area-inset-top, 0px));
  --m-safe-top-tg: var(--tg-content-safe-area-inset-top, 0px); /* Telegram's Close / ⋯ row in fullscreen */
  --m-safe-top: calc(var(--m-safe-top-device) + var(--m-safe-top-tg));
  --m-safe-right: calc(max(env(safe-area-inset-right, 0px), var(--tg-safe-area-inset-right, 0px)) + var(--tg-content-safe-area-inset-right, 0px));
  --m-safe-bottom: calc(max(env(safe-area-inset-bottom, 0px), var(--tg-safe-area-inset-bottom, 0px)) + var(--tg-content-safe-area-inset-bottom, 0px));
  --m-safe-left: calc(max(env(safe-area-inset-left, 0px), var(--tg-safe-area-inset-left, 0px)) + var(--tg-content-safe-area-inset-left, 0px));

  --m-touch: 44px;
  --m-navbar-h: 44px;
  /* sticky bar incl. insets; in Telegram fullscreen the compact title sits in Telegram's
     button row (between Close and ⋯) instead of stacking a second 44pt row under it */
  --m-navbar-total: calc(var(--m-safe-top-device) + max(var(--m-navbar-h), var(--m-safe-top-tg)));
  --m-tabbar-base: 56px;
  --m-tabbar-h: calc(var(--m-tabbar-base) + var(--m-safe-bottom));

  /* radius */
  --m-radius-xs: 6px;
  --m-radius-sm: 10px;
  --m-radius-md: 14px;
  --m-radius-lg: 20px;
  --m-radius-xl: 28px;
  --m-radius-pill: 999px;
}
@media (min-width: 414px) {
  :root { --m-gutter: 20px; }
}

/* ===== Motion =========================================================
   Spring curves come from assets-src/spring_gen.py (12 points, peak 1.063
   and 1.015); assets-src/check_motion.py verifies them. */
:root {
  --m-dur-instant: 80ms;
  --m-dur-fast: 140ms;
  --m-dur-base: 220ms;
  --m-dur-slow: 360ms;
  --m-dur-slower: 520ms;

  --m-ease-out: cubic-bezier(.22, 1, .36, 1);
  --m-ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --m-ease-in: cubic-bezier(.4, 0, 1, 1);
  --m-ease-spring: linear(0, 0.108 5%, 0.386 11%, 0.707 18%, 0.926 25%, 1.041 33%, 1.063 41%, 1.041 50%, 1.013 60%, 0.998 71%, 0.996 84%, 1);
  --m-ease-spring-soft: linear(0, 0.079 5%, 0.287 11%, 0.544 18%, 0.749 25%, 0.898 33%, 0.976 41%, 1.009 50%, 1.015 60%, 1.01 71%, 1.004 84%, 1);

  --m-press-scale: .97;
  --m-press-darken: brightness(.94);
}
@media (prefers-reduced-motion: reduce) {
  :root {
    --m-dur-instant: 1ms;
    --m-dur-fast: 1ms;
    --m-dur-base: 1ms;
    --m-dur-slow: 1ms;
    --m-dur-slower: 1ms;
    --m-press-scale: 1;
  }
}

/* ===== Z-index ======================================================== */
:root {
  --m-z-base: 0;
  --m-z-raised: 1;
  --m-z-sticky: 10;
  --m-z-navbar: 20;
  --m-z-tabbar: 30;
  --m-z-overlay: 40;
  --m-z-sheet: 50;
  --m-z-toast: 60;
  --m-z-popover: 70;
  --m-z-max: 100;
}

/* ===== Component state (set inline or by mochi.js) =================== */
:root { --m-collapse: 0; --m-value: 0; }
