/* Artifactory design system — one file, loaded by every page (/, /sculpt/,
   /assembly/, /vector/). Pages map their own variables onto these tokens and
   use these components, so a change here lands everywhere.

   Register: a black working canvas with a faint dot grid, Geist at regular
   weight only, monochrome. Every fill and every ink is white (dark theme) or
   black (light theme) at a set opacity, so layers stack the same way on the
   canvas, on a card, or over the live 3D stage:
     surface   the card itself, frosted over whatever is behind it
     raised    +6% / +5%   buttons, inputs, wells
     raised-2  +11% / +9%  hover, selected
     ink 92%, ink-2 66%, ink-3 50% (light: 90/68/58%)
   No strokes: no borders, dividers or selection rings. The only outline is
   the keyboard focus ring. No hue anywhere in the chrome; color belongs to
   the work. The one exception to "flat" is the dials, which are drawn as
   physical knobs (tokens below) because they are turned like physical knobs.
   Measured from flora.ai on 2026-11-04 (#000 canvas, near-white primary); no
   Flora marks, wordmark or display serif are used. */

:root {
  color-scheme: dark;
  --ds-font: "Geist", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ds-w: 400;                    /* the only weight */

  --ds-canvas: #000000;
  --ds-surface: rgba(44, 44, 43, .96);
  /* Cards separate from the stage by tone alone: no stroke, no shadow. */
  --ds-elev: none;
  --ds-blur: blur(24px) saturate(140%);
  --ds-raised: rgba(255, 255, 255, .06);
  --ds-raised-2: rgba(255, 255, 255, .11);
  --ds-line: transparent;         /* strokes are off; kept so old references resolve */
  --ds-line-2: transparent;
  --ds-dot: rgba(255, 255, 255, .09);

  --ds-ink: rgba(255, 255, 255, .92);
  --ds-ink-2: rgba(255, 255, 255, .66);
  --ds-ink-3: rgba(255, 255, 255, .5);   /* 4.5:1 or better on surface, raised and raised-2 */

  --ds-primary: rgba(255, 255, 255, .92); /* the one light button per surface */
  --ds-on-primary: #000000;
  --ds-select: rgba(255, 255, 255, .92);
  --ds-danger: #ff6b5e;

  /* Knob: a dark plastic cap on a skirt, lit from above, casting a shadow. */
  --ds-knob-hi: #4a4a4a; --ds-knob-mid: #262626; --ds-knob-lo: #111111;
  --ds-knob-skirt-hi: #3a3a3a; --ds-knob-skirt-lo: #050505;
  --ds-knob-sheen: rgba(255, 255, 255, .2);
  --ds-knob-shadow: rgba(0, 0, 0, .75);
  --ds-knob-ind: rgba(255, 255, 255, .95);
  --ds-knob-face: radial-gradient(78% 78% at 50% 28%, var(--ds-knob-hi), var(--ds-knob-mid) 58%, var(--ds-knob-lo));

  --ds-r-sm: 4px;                 /* rows inside a card */
  --ds-r: 6px;                    /* buttons, inputs */
  --ds-r-card: 10px;              /* cards, panels */
  --ds-h: 28px;                   /* control height, desktop */
  --ds-h-row: 26px;               /* list rows inside a card */
  --ds-h-touch: 40px;             /* control height, phones */
  --ds-t-xs: 11px; --ds-t-sm: 11px; --ds-t: 12px; --ds-t-lg: 14px;
  --ds-gap: 4px;                  /* between controls */
  --ds-pad: 6px;                  /* inside a card */
  --ds-edge: 8px;                 /* card to screen edge */
  --ds-dur: 140ms;
}

:root[data-theme="light"] {
  color-scheme: light;
  --ds-canvas: #ebebea;
  --ds-surface: rgba(250, 250, 249, .94);
  --ds-elev: none;
  --ds-raised: rgba(0, 0, 0, .05);
  --ds-raised-2: rgba(0, 0, 0, .09);
  --ds-dot: rgba(0, 0, 0, .10);
  --ds-ink: rgba(0, 0, 0, .9);
  --ds-ink-2: rgba(0, 0, 0, .68);
  --ds-ink-3: rgba(0, 0, 0, .58);
  --ds-primary: rgba(0, 0, 0, .9);
  --ds-on-primary: #ffffff;
  --ds-select: rgba(0, 0, 0, .9);
  /* Knob: a pale cap, same light, softer shadow. */
  --ds-knob-hi: #ffffff; --ds-knob-mid: #ededed; --ds-knob-lo: #cfcfcf;
  --ds-knob-skirt-hi: #ffffff; --ds-knob-skirt-lo: #b8b8b8;
  --ds-knob-sheen: rgba(255, 255, 255, .8);
  --ds-knob-shadow: rgba(0, 0, 0, .3);
  --ds-knob-ind: rgba(0, 0, 0, .85);
}

/* ---------- canvas ---------- */
.ds-canvas {
  background-color: var(--ds-canvas);
  background-image: radial-gradient(var(--ds-dot) 1px, transparent 1.2px);
  background-size: 20px 20px;
}

/* ---------- type ---------- */
.ds-label { font: 400 var(--ds-t-sm)/1.2 var(--ds-font); color: var(--ds-ink); }
/* Regular weight only, on every page and inside the compiled app: hierarchy
   comes from size and ink opacity. */
body, body * { font-weight: var(--ds-w) !important; }
.ds-meta  { font: 400 var(--ds-t-sm)/1.2 var(--ds-font); color: var(--ds-ink-3); }
.ds-hint  { font: 400 var(--ds-t-xs)/1.35 var(--ds-font); color: var(--ds-ink-3); }

/* ---------- node card: label row above a hairline card ---------- */
.ds-node-head { display: flex; justify-content: space-between; gap: 8px; padding: 2px 4px 4px; }
.ds-card { background: var(--ds-surface); border-radius: var(--ds-r-card); -webkit-backdrop-filter: var(--ds-blur); backdrop-filter: var(--ds-blur); }

/* ---------- buttons ---------- */
.ds-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--ds-h); padding: 0 10px; border-radius: var(--ds-r);
  font: 400 var(--ds-t)/1 var(--ds-font); white-space: nowrap; cursor: pointer;
  background: var(--ds-raised); color: var(--ds-ink); border: 0;
  transition: background var(--ds-dur), color var(--ds-dur);
}
.ds-btn:hover { background: var(--ds-raised-2); }
/* A toggle that is on takes a fill step and full ink, as a selected row does.
   The one light button per surface stays the primary action. */
.ds-btn[aria-pressed="true"] { background: var(--ds-raised-2); color: var(--ds-ink); }
.ds-btn .ico { flex: none; }

/* ---------- segmented control: options in one raised well ----------
   Same shape as the Object mode | Sculpt mode switch. Works for one-of
   (Add | Subtract) and any-of (Symmetry X Y Z) groups alike. */
.ds-seg { display: inline-flex; gap: 2px; padding: 2px; border-radius: var(--ds-r); background: var(--ds-raised); }
.ds-seg-o {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: calc(var(--ds-h) - 4px); padding: 0 10px; border: 0; border-radius: var(--ds-r-sm);
  background: transparent; color: var(--ds-ink-2); font: 400 var(--ds-t)/1 var(--ds-font); cursor: pointer;
  transition: background var(--ds-dur), color var(--ds-dur);
}
.ds-seg-o:hover { color: var(--ds-ink); }
.ds-seg-o[aria-pressed="true"] { background: var(--ds-raised-2); color: var(--ds-ink); }
.ds-seg-o.sq { width: calc(var(--ds-h) - 4px); padding: 0; }
.ds-btn:disabled { opacity: .4; cursor: default; }
.ds-btn:disabled:hover { background: var(--ds-raised); }
.ds-btn.pri { background: var(--ds-primary); color: var(--ds-on-primary); border-color: transparent; }
.ds-btn.pri:hover { opacity: .86; }
.ds-btn.q { background: transparent; color: var(--ds-ink-2); }
.ds-btn.q:hover { background: var(--ds-raised); color: var(--ds-ink); }
.ds-btn.icon { width: var(--ds-h); padding: 0; }

.ds-kbd {
  font: 400 10px/1 var(--ds-font); color: var(--ds-ink-3);
  padding: 2px 4px; border-radius: 3px; background: var(--ds-raised-2);
}

/* ---------- inputs ---------- */
.ds-input {
  height: var(--ds-h); padding: 0 8px; border-radius: var(--ds-r);
  background: var(--ds-raised); color: var(--ds-ink); border: 0;
  font: 400 var(--ds-t)/1 var(--ds-font);
}
.ds-input::placeholder { color: var(--ds-ink-3); }

/* ---------- no strokes, one focus ring ----------
   Every page loads this file, so this one rule takes the borders and ring
   shadows out of the main app's compiled CSS and the three hand-built pages
   alike. Separation comes from fill. Keyboard focus is the one outline left,
   and it is forced on so no page can hide it. Exceptions opt back in with
   .ds-keep-stroke (a marker that sits on arbitrary color needs its edge). */
*:not(.ds-keep-stroke), *:not(.ds-keep-stroke)::before, *:not(.ds-keep-stroke)::after {
  border-width: 0 !important; box-shadow: none !important;
}
:focus-visible { outline: 2px solid var(--ds-select) !important; outline-offset: 2px !important; }

@media (max-width: 560px) {
  :root { --ds-h: var(--ds-h-touch); }
  .ds-input { font-size: 16px; } /* stops iOS zoom on focus */
}
@media (prefers-reduced-motion: reduce) { :root { --ds-dur: 0ms; } }

