/* seed:managed sha256:{{SEED_SHA}} */
/* GENERATED by scripts/design/build_design.py from
   reference/design/tokens.yaml in the Cinova workspace.
   Do not edit. Change the canon and rebuild, or the surfaces drift
   apart again, which is the whole reason this file is generated. */


/* ─── CANVAS ─────────────────────────────────────────────── */
/* A CLASS BESIDE THE ROOT, so a single band, panel or figure can carry
   the other appearance without a second palette being written for it.
   Every name below is identical in both, so anything inside an inverted
   scope inherits the whole set and nothing downstream branches. */
:root,
.appearance-dark {
  --canvas: #060607;
  --canvas-raised: #101014;
  --canvas-sunk: #0a0a0c;
  --feature: #ffffff;
  --feature-on: #060607;
  --frame: #000000;
  --ink: #f6f6f8;
  --ink-muted: rgb(255 255 255 / 0.58);
  --ink-dim: rgb(255 255 255 / 0.34);
  --line: rgb(255 255 255 / 0.09);
  --line-strong: rgb(255 255 255 / 0.16);
  --up: #4ade80;
  --down: #f87171;

  /* [apple] The platform's own face, which is real San Francisco
     on Apple hardware and already ships optical sizing. */
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, "Segoe UI", Roboto, sans-serif;
  --font-display: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  --radius-xs: 6px;
  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 12px;
  --radius-xl: 18px;
  --radius-sheet: 20px;
  --radius-capsule: 980px;
  --radius-block: 8px;

  --material-sat: 180%;
  --material-chrome-blur: 20px;
  --material-chrome-bg: rgb(6 6 7 / 0.72);
  --material-chrome-edge: rgb(255 255 255 / 0.10);
  --material-menu-blur: 24px;
  --material-menu-bg: rgb(16 16 20 / 0.80);
  --material-menu-edge: rgb(255 255 255 / 0.14);
  --material-sheet-blur: 32px;
  --material-sheet-bg: rgb(16 16 20 / 0.86);
  --material-sheet-edge: rgb(255 255 255 / 0.12);
  --material-scrim-bg: rgb(0 0 0 / 0.55);

  --elevation-raised: 0 1px 2px rgb(0 0 0 / 0.28);
  --elevation-menu: 0 8px 24px -6px rgb(0 0 0 / 0.45), 0 2px 6px rgb(0 0 0 / 0.30);
  --elevation-sheet: 0 -12px 40px -8px rgb(0 0 0 / 0.55);
  --elevation-modal: 0 24px 64px -12px rgb(0 0 0 / 0.60);

  /* [skill] Apple kept two numbers, not the physics triplet:
     damping ratio, which is overshoot, and response, which is how fast
     it arrives in seconds. Response is NOT a duration; a spring has no
     fixed duration, its settle time emerges from the parameters.

     CSS cannot consume a spring, so these are the published source and
     a build's own src/lib/motion/tokens.ts mirrors them as literals.
     tests/unit/motion-tokens.test.ts parses THIS file and fails if the
     two ever disagree, so change both or change neither. */
  --spring-move-damping: 1.0;
  --spring-move-response: 0.4;
  --spring-rotate-damping: 0.8;
  --spring-rotate-response: 0.4;
  --spring-sheet-damping: 0.8;
  --spring-sheet-response: 0.3;
  --spring-default-damping: 1.0;
  --spring-default-response: 0.35;
  --projection-decel: 0.998;
  --rubberband-constant: 0.55;
  --gesture-hysteresis: 10px;
  --press-scale: 0.97;
  --dur-press: 120ms;
  --dur-fast: 160ms;
  --dur-menu: 200ms;
  --dur-modal: 240ms;
  --dur-sheet: 320ms;
  --dur-reduced: 160ms;
  --dur-shimmer: 1400ms;
  --dur-marquee: 60000ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-reverse: cubic-bezier(0.84, 0, 0.7, 0);
  --ease-sheet: cubic-bezier(0.32, 0.72, 0, 1);
  --motion-scale: 1;

  /* A tracked uppercase label is the one deliberate exception to the
     curve, because the tracking is doing the legibility work the size
     cannot at that scale. It was declared for paper only until
     2026-09-11, which left every screen inventing its own: one site had
     nine different values between 0.04 and 0.26em across a dozen labels
     that were all the same device. verify_galleries.py already accepted
     this value on screen; only the token was missing. */
  --tracking-label: 0.08em;

  /* Safe area. Reads 0 unless the viewport declares cover. */
  --sat: env(safe-area-inset-top, 0px);
  --sar: env(safe-area-inset-right, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px);
  --frame-w: 480px;
  --chrome-h-header: 60px;
  --chrome-h-tabbar: 56px;
  --chrome-edge-fade: 20px;
}

/* Light appearance keeps the same NAMES, so nothing downstream
   ever branches on which one is active. */
:root[data-theme="light"],
.appearance-light {
  --canvas: #ffffff;
  --canvas-raised: #fbfbfc;
  --canvas-sunk: #f4f4f5;
  --feature: #1a1c1e;
  --feature-on: #ffffff;
  --frame: #e7e7e7;
  --ink: #1a1c1e;
  --ink-muted: rgb(26 28 30 / 0.62);
  --ink-dim: rgb(26 28 30 / 0.40);
  --line: rgb(26 28 30 / 0.10);
  --line-strong: rgb(26 28 30 / 0.18);
  --up: #15803d;
  --down: #c1121f;
  --material-chrome-bg: rgb(255 255 255 / 0.72);
  --material-chrome-edge: rgb(255 255 255 / 0.90);
  --material-menu-bg: rgb(255 255 255 / 0.82);
  --material-menu-edge: rgb(255 255 255 / 0.95);
  --material-sheet-bg: rgb(255 255 255 / 0.88);
  --material-sheet-edge: rgb(255 255 255 / 0.95);
  --material-scrim-bg: rgb(26 28 30 / 0.28);
  --elevation-raised: 0 1px 2px rgb(0 0 0 / 0.06);
  --elevation-menu: 0 8px 24px -6px rgb(0 0 0 / 0.12), 0 2px 6px rgb(0 0 0 / 0.06);
  --elevation-sheet: 0 -12px 40px -8px rgb(0 0 0 / 0.14);
  --elevation-modal: 0 24px 64px -12px rgb(0 0 0 / 0.18);
}

/* ─── TYPE ───────────────────────────────────────────────────────
   [apple] The curve crosses zero TWICE, because the face changes at
   19px. Tracking is negative below it, POSITIVE from there to
   about 36px, and negative again past 40px. Tightening steadily as
   type grows is the usual reflex and the inverse of what Apple does.

   Weights are 400/500/600/700 only. WebKit buckets everything else
   to one of nine CoreText weights, so 560 is silently 600. */

/* :where() ON PURPOSE, so each of these carries ZERO specificity.

   These names are Tailwind's, and in a build that runs Tailwind the curve
   already reaches every utility through apple-tailwind.css, which makes
   this block a duplicate. A duplicate at normal specificity is not
   harmless: an unlayered .text-sm beats a `leading-none` utility, because
   an unlayered rule outranks every layer, so a stock component asking for
   flush leading silently got 1.286 instead. At zero specificity the block
   still dresses a plain HTML page, where nothing competes with it, and
   loses to any real class the moment something does. */
:where(.text-xs) { letter-spacing: -0.010em; line-height: 1.333; }  /* 12px, text */
:where(.text-sm) { letter-spacing: -0.016em; line-height: 1.286; }  /* 14px, text */
:where(.text-base) { letter-spacing: -0.020em; line-height: 1.250; }  /* 16px, text */
:where(.text-lg) { letter-spacing: -0.021em; line-height: 1.280; }  /* 18px, text */
:where(.text-xl) { letter-spacing:  0.011em; line-height: 1.305; }  /* 20px, display */
:where(.text-2xl) { letter-spacing:  0.009em; line-height: 1.167; }  /* 24px, display */
:where(.text-3xl) { letter-spacing:  0.005em; line-height: 1.134; }  /* 30px, display */
:where(.text-4xl) { letter-spacing:  0.002em; line-height: 1.113; }  /* 36px, display */
:where(.text-5xl) { letter-spacing: -0.003em; line-height: 1.083; }  /* 48px, display */
:where(.text-6xl) { letter-spacing: -0.007em; line-height: 1.067; }  /* 60px, display */
:where(.text-7xl) { letter-spacing: -0.012em; line-height: 1.056; }  /* 72px, display */
:where(.text-8xl) { letter-spacing: -0.015em; line-height: 1.042; }  /* 96px, display */


/* ─── BUTTONS ────────────────────────────────────────────────────────────
   [apple] Straight from Apple's own tokens. An inline button is a capsule.
   The moment it goes full width it becomes an 8px rectangle, which is what
   their sign-in page does. A full-width capsule is one of the loudest tells
   there is. Weight is 400, not 600. */
[data-slot="button"] {
  border-radius: 980px;
  font-weight: 400;
  padding: 9px 16px;
  touch-action: manipulation;
}
[data-slot="button"].w-full,
[data-slot="button"][data-block] { border-radius: 8px; }

/* §1 Response. Feedback on pointer DOWN, never on release. Travel is
   size specific for the same reason tracking is: 3% off a chip is invisible,
   3% off a full-width bar is a lurch. */
[data-slot="button"]:active { transform: scale(var(--press-scale)); }
[data-slot="button"][data-size="block"]:active { transform: scale(0.99); }
[data-slot="button"] {
  transition: transform calc(var(--dur-press) * var(--motion-scale)) var(--ease-out);
}


/* ─── ACCESSIBILITY ──────────────────────────────────────────────────────
   [skill §14] Three independent signals, not one. Reduced motion is a GENTLER
   EQUIVALENT and never the absence of feedback: the surface still arrives, it
   just does not travel. Killing every transition is the failure this replaces. */
@media (prefers-reduced-motion: reduce) {
  :root { --motion-scale: 0.5; }
  [data-slot="button"]:active { transform: none; opacity: 0.8; }
}
@media (prefers-reduced-transparency: reduce) {
  :root {
    --material-chrome-blur: 0px;
    --material-menu-blur: 0px;
    --material-sheet-blur: 0px;
    --material-chrome-bg: var(--canvas);
    --material-menu-bg: var(--canvas-raised);
    --material-sheet-bg: var(--canvas-raised);
  }
}
@media (prefers-contrast: more) {
  :root { --material-chrome-bg: var(--canvas); --material-menu-bg: var(--canvas-raised); }
}
/* In-app browsers inside Instagram and Facebook do not support backdrop-filter,
   and a translucent bar with no blur is an unreadable smear. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root {
    --material-chrome-bg: var(--canvas);
    --material-menu-bg: var(--canvas-raised);
    --material-sheet-bg: var(--canvas-raised);
  }
}

