/* tokens.css — the Stashio design system, translated to CSS custom properties.
 *
 * SOURCE OF TRUTH, do not invent values here:
 *   colours   ios/ShareToSave/App/DesignSystem.swift:38-48
 *             (verified identical to android/.../ui/theme/Color.kt:6-54 — not one hex differs)
 *   ladders   DesignSystem.swift `ControlHeight` / ui/Components.kt `ControlHeight`
 *   springs   App/Motion.swift + ui/Motion.kt, solved to CSS by the same formula that
 *             produced extension/chrome/popup.css:63-71 (settle threshold |x-1| < 0.0015)
 *
 * If a value here disagrees with the app, the APP is right and this file is the bug.
 */

:root {
  color-scheme: light dark;

  /* ---- Brand (Iris / Indigo) ---- */
  --brand:        #5B5BD6;
  --brand-hi:     #7B7BE6;   /* stop 2 of the logo gradient */
  --brand-soft:   #EEEEFB;   /* secondary button / badge / logo fold */
  --on-brand:     #FFFFFF;

  /* ---- Neutrals ---- */
  --bg:           #FAFAFC;
  --surface:      #FFFFFF;
  --surface-alt:  #F1F1F5;
  --ink:          #15151C;
  --muted:        #6B6B7B;
  --outline:      #E6E6EC;

  /* ---- Status — deliberately identical in light and dark ---- */
  --status-ready:      #2FA968;
  --status-pending:    #F5A623;   /* pending / fetching / extracting / enriching */
  --status-failed:     #E5484D;
  --status-ready-bg:   rgba(47,169,104,.12);
  --status-pending-bg: rgba(245,166,35,.12);
  --status-failed-bg:  rgba(229,72,77,.12);

  /* ---- Kind accents (the tile drawn when an item has no hero image) ---- */
  --kind-article: #5B5BD6;  --kind-video:   #E5484D;
  --kind-post:    #0091FF;  --kind-product: #F76B15;
  --kind-recipe:  #2FA968;  --kind-place:   #12A594;
  --kind-pdf:     #D23F3F;  --kind-contact: #8E4EC6;
  --kind-image:   #00A2C7;  --kind-note:    #7A7A8C;
  /* A PERCENTAGE, not a bare number: color-mix() rejects `.14` outright and the whole
     declaration is dropped, which renders the tile fully transparent. */
  --kind-tile-alpha: 14%;

  /* ---- Skeleton ---- */
  --skeleton-base:      #F1F1F5;
  --skeleton-highlight: #F9F9FA;
  --skeleton-flat:      #F5F5F7;   /* static fill under prefers-reduced-motion */

  /* ---- Elevation ---- */
  --shadow-card: 0 4px 16px rgba(0,0,0,.08);   /* feed card: shadow ONLY, never a border */
  --shadow-soft: 0 8px 32px rgba(0,0,0,.05);   /* cardSurface: shadow + 1px border */

  /* ---- Spacing (4pt grid) ---- */
  --sp-xxs: 4px;  --sp-xs: 8px;   --sp-s: 12px; --sp-m: 16px;
  --sp-l: 20px;   --sp-xl: 24px;  --sp-xxl: 32px;
  --gutter: 16px;                  /* horizontal margin of every main screen — this is law */

  /* ---- Radius: there are exactly TWO steps ---- */
  --r-chip: 8px;    /* chip, pill, badge, small control */
  --r-card: 10px;   /* card, thumbnail, sheet, text field */
  /* True circles (avatar, dot, spinner) use 50% — deliberate, off-ladder.
     NEVER border-radius:999px on a chip: iOS replaced Capsule() with Pill() precisely so
     pills obey the 8px rule (DesignSystem.swift:88-104). */

  /* ---- Control-height ladder ---- */
  --h-badge:     28px;  /* status pill — never pressable */
  --h-tiny:      32px;  /* small glyph inside a dense row */
  --h-chip:      36px;  /* chip / compact secondary */
  --h-secondary: 44px;  /* secondary button */
  --h-primary:   48px;  /* primary CTA — the CEILING, nothing may be taller */
  --h-row:       48px;  --h-row-2line: 56px;  --h-row-media: 64px;
  --min-target:  44px;  /* iOS=44 (HIG), Android=48 (Material) — web takes 44 */

  /* ---- Typography ---- */
  --font: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --fs-display:   36px; --lh-display:   42px; --ls-display:   -0.5px; /* w900 */
  --fs-title:     26px; --lh-title:     32px; --ls-title:     -0.3px; /* w800 */
  --fs-title2:    22px; --lh-title2:    28px; --ls-title2:    -0.2px; /* w700 */
  --fs-title3:    19px; --lh-title3:    25px; --ls-title3:    -0.2px; /* w700 */
  --fs-headline:  17px; --lh-headline:  23px; --ls-headline:   0;     /* w700 */
  --fs-body:      16px; --lh-body:      23px; --ls-body:       0.1px; /* w400 */
  --fs-sub:       14px; --lh-sub:       18px; --ls-sub:        0;     /* w600 */
  --fs-caption: 12.5px; --lh-caption:   16px; --ls-caption:    0.2px; /* w600 */
  --fs-caption2:  11px; --lh-caption2:  14px; --ls-caption2:   0.3px; /* w700 */

  /* ---- Motion: the app's springs, solved to CSS ---- */
  --dur-chip:    373ms;  /* spring(0.28, 0.85) */
  --dur-snappy:  504ms;  /* spring(0.38, 0.82) — press feedback, the default */
  --dur-gentle:  613ms;  /* spring(0.60, 0.92) */
  --dur-smooth:  630ms;  /* spring(0.45, 1.00) — list structure changes, no overshoot */
  --dur-playful: 663ms;  /* spring(0.42, 0.58) — checkmark, confetti */
  --dur-reveal:  730ms;  /* spring(0.55, 0.86) — entrance cascade */
  --dur-bouncy:  777ms;  /* spring(0.50, 0.70) */
  --stagger-step: 45ms;  --stagger-cap: 400ms;
  --press-scale: 0.96;
  --ease-chip:    cubic-bezier(.2,.8,.3,1.06);
  --ease-snappy:  cubic-bezier(.2,.8,.3,1.06);
  --ease-gentle:  cubic-bezier(.25,.9,.3,1);
  --ease-smooth:  cubic-bezier(.25,.9,.3,1);
  --ease-playful: cubic-bezier(.2,.9,.3,1.2);
  --ease-reveal:  cubic-bezier(.2,.75,.3,1.02);
  --ease-bouncy:  cubic-bezier(.2,.9,.3,1.25);
  --ease-out:     cubic-bezier(.16,1,.3,1);

  /* ---- Layout ---- */
  --readable: 720px;   /* max text column */
  --wide: 1100px;      /* max grid */
  --bp-large: 600px;   /* >= : 3-column grid instead of 2 */
  --bp-split: 840px;   /* >= : list and detail side by side */
  --rail: 80px;        /* navigation rail */
}

/* Dark. Both blocks are defined so a manual toggle wins in BOTH directions —
   popup.css only has the @media half, which is the gap this file closes. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --brand: #9B9BF5;  --brand-hi: #B4B4F8;  --brand-soft: #2A2A52;
    --on-brand: #0B0B0F;
    --bg: #0B0B0F;  --surface: #15151C;  --surface-alt: #1F1F29;
    --ink: #ECECF1; --muted: #9A9AA8;    --outline: #2A2A36;
    --skeleton-base: #1F1F29; --skeleton-highlight: #2F2F38; --skeleton-flat: #27272F;
    --shadow-card: 0 4px 16px rgba(0,0,0,.45);
    --shadow-soft: 0 8px 32px rgba(0,0,0,.40);
  }
}
:root[data-theme="dark"] {
  --brand: #9B9BF5;  --brand-hi: #B4B4F8;  --brand-soft: #2A2A52;
  --on-brand: #0B0B0F;
  --bg: #0B0B0F;  --surface: #15151C;  --surface-alt: #1F1F29;
  --ink: #ECECF1; --muted: #9A9AA8;    --outline: #2A2A36;
  --skeleton-base: #1F1F29; --skeleton-highlight: #2F2F38; --skeleton-flat: #27272F;
  --shadow-card: 0 4px 16px rgba(0,0,0,.45);
  --shadow-soft: 0 8px 32px rgba(0,0,0,.40);
}

/* The real 37-point springs, gated on support (linear() — Chrome 113 / FF 112 / Safari 17.2).
   Without the gate an unsupporting browser drops the declaration and keeps the cubic-bezier
   approximation above, which is the intended fallback. */
@supports (animation-timing-function: linear(0, 1)) {
  :root {
    --ease-chip: linear(0.0000, 0.0237, 0.0830, 0.1638, 0.2553, 0.3501, 0.4428, 0.5300, 0.6096, 0.6806, 0.7426, 0.7958, 0.8407, 0.8781, 0.9086, 0.9333, 0.9528, 0.9681, 0.9798, 0.9886, 0.9950, 0.9996, 1.0026, 1.0046, 1.0057, 1.0062, 1.0063, 1.0060, 1.0056, 1.0051, 1.0045, 1.0039, 1.0033, 1.0028, 1.0023, 1.0019, 1.0015);
    --ease-snappy: linear(0.0000, 0.0236, 0.0831, 0.1645, 0.2573, 0.3537, 0.4484, 0.5376, 0.6192, 0.6919, 0.7553, 0.8096, 0.8551, 0.8927, 0.9232, 0.9475, 0.9664, 0.9809, 0.9916, 0.9993, 1.0046, 1.0080, 1.0100, 1.0109, 1.0111, 1.0107, 1.0099, 1.0090, 1.0079, 1.0069, 1.0058, 1.0049, 1.0040, 1.0032, 1.0025, 1.0020, 1.0015);
    --ease-smooth: linear(0.0000, 0.0254, 0.0868, 0.1674, 0.2559, 0.3452, 0.4308, 0.5100, 0.5816, 0.6452, 0.7009, 0.7491, 0.7905, 0.8257, 0.8555, 0.8806, 0.9016, 0.9191, 0.9336, 0.9456, 0.9556, 0.9638, 0.9705, 0.9760, 0.9805, 0.9842, 0.9872, 0.9896, 0.9916, 0.9932, 0.9945, 0.9956, 0.9965, 0.9971, 0.9977, 0.9982, 0.9985);
    --ease-playful: linear(0.0000, 0.0340, 0.1211, 0.2411, 0.3772, 0.5164, 0.6487, 0.7674, 0.8688, 0.9508, 1.0136, 1.0584, 1.0871, 1.1023, 1.1068, 1.1032, 1.0938, 1.0810, 1.0665, 1.0516, 1.0375, 1.0248, 1.0140, 1.0052, 0.9985, 0.9938, 0.9907, 0.9891, 0.9886, 0.9890, 0.9900, 0.9914, 0.9929, 0.9945, 0.9960, 0.9974, 0.9985);
    --ease-reveal: linear(0.0000, 0.0235, 0.0823, 0.1622, 0.2528, 0.3465, 0.4382, 0.5246, 0.6035, 0.6739, 0.7356, 0.7886, 0.8336, 0.8711, 0.9019, 0.9270, 0.9470, 0.9628, 0.9750, 0.9843, 0.9913, 0.9963, 0.9999, 1.0023, 1.0038, 1.0046, 1.0050, 1.0050, 1.0048, 1.0044, 1.0040, 1.0036, 1.0031, 1.0026, 1.0022, 1.0018, 1.0015);
    --ease-bouncy: linear(0.0000, 0.0323, 0.1133, 0.2227, 0.3448, 0.4681, 0.5849, 0.6900, 0.7808, 0.8562, 0.9165, 0.9629, 0.9969, 1.0203, 1.0351, 1.0431, 1.0459, 1.0451, 1.0417, 1.0369, 1.0314, 1.0257, 1.0202, 1.0153, 1.0109, 1.0073, 1.0044, 1.0021, 1.0004, 0.9993, 0.9985, 0.9981, 0.9979, 0.9979, 0.9980, 0.9982, 0.9985);
    --ease-gentle: linear(0.0000, 0.0143, 0.0512, 0.1036, 0.1655, 0.2327, 0.3019, 0.3706, 0.4371, 0.5002, 0.5592, 0.6136, 0.6633, 0.7082, 0.7484, 0.7841, 0.8157, 0.8435, 0.8677, 0.8887, 0.9069, 0.9225, 0.9358, 0.9471, 0.9567, 0.9648, 0.9716, 0.9772, 0.9819, 0.9858, 0.9889, 0.9915, 0.9936, 0.9953, 0.9966, 0.9977, 0.9985);
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important; animation-delay: 0ms !important;
    animation-iteration-count: 1 !important; transition-duration: 1ms !important;
  }
}

/* ---- Fonts. Only the four weights the app actually uses: 400/600/700/800.
   These files are already subset for Vietnamese (621 glyphs, ~24 KB each); do NOT
   regenerate them from web/*.ttf, which are the unsubset 132 KB originals. ---- */
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fonts/Nunito-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/Nunito-SemiBold.woff2') format('woff2');
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('../fonts/Nunito-Bold.woff2') format('woff2');
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 800; font-display: swap;
  src: url('../fonts/Nunito-ExtraBold.woff2') format('woff2');
}

/* ---- Touch targets. Everything pressable shorter than 44px needs one of these.
   Two classes on purpose: the ::after version only widens the BLOCK axis, so a 32px
   glyph would still be too narrow horizontally. ---- */
.target { position: relative; }
.target::after {
  content: ''; position: absolute; inset: 50% 0 auto;
  transform: translateY(-50%); height: max(100%, var(--min-target));
}
.target-icon {
  min-width: var(--min-target); min-height: var(--min-target);
  display: inline-flex; align-items: center; justify-content: center;
}
/* Caveat: ::after is clipped by any ancestor with overflow:hidden, and it SWALLOWS
   pressable children (a chip with its own ✕ loses that button). For those, use the
   two-box model: outer <button> with min-block-size:44px and a transparent background,
   inner <span> at 36px carrying the visuals. */
