/* frontend/shared/tokens.css | Diaco Studio design system
 * ============================================================================
 *
 * Style        Data-Dense Dashboard
 * Product      clinical CAD/CAM workstation (practitioner, not patient facing)
 * Type         IBM Plex Sans + IBM Plex Mono
 * Density      dense: 8px grid, 12px card padding, 36px rows, 13px base
 * Motion       subtle: 120-180ms, reduced-motion honoured
 *
 * Three modules used to define three separate palettes -- navy glass, surgical
 * teal, and a GitHub blue -- so the product looked like three products. They
 * now share this file, and their old variable names are kept as aliases at the
 * bottom, which is why one palette change lands everywhere without editing
 * three stylesheets.
 *
 * Every foreground/background pair below is verified: the lowest is muted
 * labels at 4.39:1 against a 3:1 requirement, and every text pair clears 4.5:1
 * in both themes.
 *
 * The style match is a deliberate override. The generator proposed
 * "Exaggerated Minimalism" -- 12rem type, massive whitespace -- which belongs
 * on a fashion portfolio, not on a workstation where a prosthetist reads
 * fifty numeric parameters at once.
 */

/* ---------------------------------------------------------------- scale --- */
:root {
  /* Dense dashboard spacing: an 8px grid with 2 and 4 for control interiors. */
  --space-1: 2px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 12px;
  --space-6: 16px;
  --space-7: 24px;
  --space-8: 32px;

  /* Type: 13px base. Nothing below 12px carries meaning. */
  --text-xs: 11px;    /* uppercase eyebrows and units only, never a sentence */
  --text-sm: 12px;
  --text-base: 13px;
  --text-md: 15px;
  --text-lg: 18px;
  --text-xl: 22px;
  --leading-tight: 1.35;
  --leading: 1.5;

  --font-sans: "IBM Plex Sans", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;

  /* Small radii: a clinical instrument, not a consumer app. */
  --radius-sm: 4px;
  --radius: 6px;
  --radius-lg: 10px;

  /* Sizes that keep the interface predictable across modules. */
  --shell-h: 44px;
  --control-h: 32px;      /* the minimum interactive target in a dense UI */
  --row-h: 36px;
  --sidebar-w: 264px;

  --dur-fast: 120ms;
  --dur: 160ms;
  --ease: cubic-bezier(.2, 0, 0, 1);
}

/* ------------------------------------------------------- light palette --- */
:root {
  --surface: #FFFFFF;
  --canvas: #F4F6F9;
  --sunken: #EAEEF3;
  --line: #D3DAE3;
  --line-soft: #E4E9EF;

  --ink: #141A21;
  --ink-2: #4A5766;
  --ink-3: #637083;   /* 5.03:1 on surface, 4.64:1 on canvas */

  --accent: #1D4ED8;
  --accent-ink: #1A44BE;
  /* The ink that reads on ANY saturated fill in this theme -- accent, ok,
     danger. A literal #fff works in the light theme and fails in the dark
     one, where those fills are light. */
  --accent-on: #FFFFFF;
  --accent-soft: #E7EDFC;

  --ok: #04785B;
  --ok-soft: #E0F2EC;
  --warn: #9A5B06;
  --warn-soft: #FAF0DF;
  --danger: #B4231C;
  --danger-soft: #FBE9E7;
  /* A parameter the operator changed from the preset. Amber throughout,
     carried over from the insole panel where it already meant this. */
  --edited: #9A5B06;
  --edited-soft: #FAF0DF;

  /* The 3D viewport stays dark in both themes. A model reads better on a dark
     ground, and the insole viewer's light rig is tuned against it. */
  --viewport: #141D27;
  --viewport-line: #223140;

  --shadow-sm: 0 1px 2px rgba(20, 26, 33, .07);
  --shadow: 0 1px 2px rgba(20, 26, 33, .06), 0 6px 16px -8px rgba(20, 26, 33, .18);
  --overlay: rgba(20, 26, 33, .38);
  --focus: var(--accent);
}

/* -------------------------------------------------------- dark palette --- */
/* Defined twice on purpose: once for the viewer's OS preference when no choice
   has been stamped, once for the explicit choice the shell writes. Guarding the
   media query with :not([data-theme="light"]) keeps an explicit light choice
   winning over a dark OS. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --surface: #161C24;
    --canvas: #0F141A;
    --sunken: #1E262F;
    --line: #2C3742;
    --line-soft: #232C36;

    --ink: #E8EDF3;
    --ink-2: #A3B0BF;
    --ink-3: #7D8B9B;

    --accent: #6BA0FF;
    --accent-ink: #8FB8FF;
    --accent-on: #0B1220;
    --accent-soft: #182741;

    --ok: #4FC49B;
    --ok-soft: #12291F;
    --warn: #E0A44A;
    --warn-soft: #2C2312;
    --danger: #F08B84;
    --danger-soft: #2E1917;
    --edited: #E0A44A;
    --edited-soft: #2C2312;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .45);
    --shadow: 0 1px 2px rgba(0, 0, 0, .45), 0 8px 20px -10px rgba(0, 0, 0, .7);
    --overlay: rgba(0, 0, 0, .58);
  }
}

:root[data-theme="dark"] {
  --surface: #161C24;
  --canvas: #0F141A;
  --sunken: #1E262F;
  --line: #2C3742;
  --line-soft: #232C36;

  --ink: #E8EDF3;
  --ink-2: #A3B0BF;
  --ink-3: #7D8B9B;

  --accent: #6BA0FF;
  --accent-ink: #8FB8FF;
  --accent-on: #0B1220;
  --accent-soft: #182741;

  --ok: #4FC49B;
  --ok-soft: #12291F;
  --warn: #E0A44A;
  --warn-soft: #2C2312;
  --danger: #F08B84;
  --danger-soft: #2E1917;
  --edited: #E0A44A;
  --edited-soft: #2C2312;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .45);
  --shadow: 0 1px 2px rgba(0, 0, 0, .45), 0 8px 20px -10px rgba(0, 0, 0, .7);
  --overlay: rgba(0, 0, 0, .58);
}

/* ------------------------------------------------- module compatibility --- */
/* Each module was written against its own vocabulary. Rather than rewrite three
   stylesheets, their names are bound to the canonical scale here. New rules
   should use the canonical names above; these exist so the redesign lands
   everywhere at once, and so a module can be migrated on its own schedule. */
:root {
  /* socket studio */
  --text: var(--ink);
  --text2: var(--ink-2);
  --bg: var(--surface);
  --bg2: var(--canvas);
  --bg3: var(--sunken);
  --border: var(--line);
  --glass: var(--surface);
  --glass2: var(--surface);
  --blue: var(--accent);
  --blue-strong: var(--accent-ink);
  --blue-bg: var(--accent-soft);
  --sage: var(--ok);
  --sage-strong: var(--ok);
  --green: var(--ok);
  --green-bg: var(--ok-soft);
  --orange: var(--warn);
  --orange-bg: var(--warn-soft);
  --warn-text: var(--warn);
  --warn-border: var(--line);
  --red: var(--danger);
  --red-bg: var(--danger-soft);
  --overlay-bg: var(--overlay);
  --body-a: transparent;
  --body-b: transparent;
  --busy-bg: var(--sunken);
  --neo-inset: none;
  --font-ui: var(--font-sans);
  --font-en: var(--font-sans);

  /* insole studio */
  --panel: var(--canvas);
  --card: var(--surface);
  --vp: var(--viewport);
  --vp-line: var(--viewport-line);
  --mono: var(--font-mono);
  --fa: var(--font-sans);

  /* batch build */
  --surface-2: var(--sunken);
  --bad: var(--danger);
  --bad-soft: var(--danger-soft);
}

/* -------------------------------------------------------------- basics --- */
* { box-sizing: border-box; }

/* One focus rule for the whole product. Keyboard users get a visible ring on
   every control in every module; pointer users are not shown one. Removing it
   is never the fix for a ring that looks wrong -- restyle it here. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* -------------------------------------------------------------- Persian --- */
/* The words change and the page does not: in Persian the layout stays left to
   right, by the owner's decision (2026-09-28). What changes is each piece of
   text's own direction, taken from its first letter -- so a Persian sentence
   reads right to left with "4 mm" and "STL" in their places, while a patient's
   name or a file name in Latin letters still reads left to right. Without it a
   Persian sentence with a number in it comes out in the wrong order. A `dir`
   attribute does not opt out: in Persian a status line marked ltr carries a
   Persian sentence too, and Latin text still comes out left to right.
   Vazirmatn draws the Persian -- in the monospace stack as well, whose own
   fallback for Arabic script is a typewriter face with the letters apart.
   A text field's placeholder ignores `plaintext`, so a field that takes words
   is right to left; its value still follows its own first letter. Letter
   spacing pulls a cursive script's joined letters apart, whatever the rule
   that asked for it, hence the one !important. */
@font-face { font-family: "Vazirmatn"; font-weight: 400; font-display: swap;
  src: url("/vendor/fonts/Vazirmatn-Regular.woff2") format("woff2"); }
@font-face { font-family: "Vazirmatn"; font-weight: 700; font-display: swap;
  src: url("/vendor/fonts/Vazirmatn-Bold.woff2") format("woff2"); }
html[lang="fa"] {
  --font-sans: "Vazirmatn", "IBM Plex Sans", "Segoe UI", Tahoma, sans-serif;
  --font-mono: "IBM Plex Mono", "Vazirmatn", "SFMono-Regular", Consolas, monospace;
}
html[lang="fa"] body * { unicode-bidi: plaintext; letter-spacing: normal !important; }
html[lang="fa"] :is(input:not([type]), input[type="text"], input[type="search"], textarea):not([dir="ltr"]) {
  direction: rtl;
}

/* Digits that line up. This interface is mostly numbers in columns. */
.mono, code, kbd, samp, pre,
input[type="number"], td, th, .num {
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
