/* ============================================================
   MEDSY — BASE / RESET
   Minimal reset, base element styles, accessibility primitives
   and the small set of typographic helpers the system leans on.
   ============================================================ */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;color-scheme:light}
body{
  font-family:var(--f-body);
  color:var(--text-body);
  background:var(--bg);
  line-height:var(--lh-body);
  font-size:var(--fs-body);
  letter-spacing:var(--ls-body);
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  font-optical-sizing:auto;
  accent-color:var(--forest);
  caret-color:var(--forest);
}
img,svg{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{font-family:inherit;color:inherit}
/* Medsy draws its own press states everywhere, so suppress the mobile grey
   tap flash system-wide rather than per-component. */
a,button,label,summary,[role="button"],[role="option"],[role="tab"],[tabindex]{-webkit-tap-highlight-color:transparent}
::selection{background:var(--selection-bg);color:var(--forest-900)}

/* ---- scrollbars: thin, green-tinted, track-less — native gray bars never
   appear inside Medsy surfaces (tables, drawers, panels, palettes) ---- */
*{scrollbar-width:thin;scrollbar-color:rgba(var(--forest-rgb),.28) transparent}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:rgba(var(--forest-rgb),.24);border-radius:var(--r-pill);border:3px solid transparent;background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:rgba(var(--forest-rgb),.4);border:3px solid transparent;background-clip:padding-box}
::-webkit-scrollbar-corner{background:transparent}

/* ---- focus-visible ring (accessibility) ---- */
:focus{outline:none}
a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,
select:focus-visible,[tabindex]:focus-visible{
  outline:2px solid var(--forest);outline-offset:2px;border-radius:var(--r-sm);
  box-shadow:0 0 0 5px var(--focus-ring);
}

/* ---- forced-colors (Windows High Contrast): box-shadow focus rings are
   stripped, so components that opt out of the outline above (mcq option, srs,
   segmented, dropzone, slider) would lose their focus indicator. Re-assert a
   system-coloured outline on every focusable in that mode. ---- */
@media (forced-colors: active){
  a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,
  select:focus-visible,[tabindex]:focus-visible,[role="button"]:focus-visible,
  .mcq-option:focus-visible,.srs-btn:focus-visible,.v-segmented button:focus-visible,
  .v-dropzone:focus-visible,.v-slider-input:focus-visible,.tab-btn:focus-visible,
  .cmdk-item:focus-visible,.menu-item:focus-visible{
    outline:2px solid CanvasText !important;outline-offset:2px;
  }
}

/* ---- prefers-contrast: strengthen the intentionally-soft green hairlines and
   muted text for low-vision users, without changing the resting aesthetic.

   Raise the SOURCE ink tokens, not the --text-* aliases. Both themes declare
   --text-muted:var(--ink-soft) / --text-faint:var(--ink-faint), so lifting
   --ink-soft/--ink-faint reaches the aliases AND the many components that read
   the source tokens directly (.v-ft-text, .li-sub, chart labels). Overriding
   --text-muted alone — as this block used to — strengthened the alias users and
   silently skipped everything else. One mechanism, both themes: the dark mirror
   in tokens/themes.css overrides this same list.

   The border-width bump is a PROPERTY on component selectors, not a token, so it
   is not theme-scoped and needs no dark counterpart. ---- */
@media (prefers-contrast: more){
  :root{
    --line:rgba(15,104,68,.40);
    --line-soft:rgba(15,104,68,.26);
    --line-mint:rgba(15,104,68,.55);
    --ink-soft:#3F4945;
    --ink-faint:#566B62;
  }
  .pill-outline,.btn-outline{border-width:2px}
}

/* ---- screen-reader only ---- */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ============================================================
   TYPOGRAPHY HELPERS
   ============================================================ */
/* premium ragging: headings balance their lines, body copy avoids orphans.
   Element-level so every surface (cards, templates, consumers) inherits. */
h1,h2,h3,.v-display,.v-h2,.card-title{text-wrap:balance}
p,li,dd,figcaption,.card-text{text-wrap:pretty}
.v-display{
  font-family:var(--f-display);font-weight:var(--fw-bold);
  line-height:var(--lh-tight);letter-spacing:var(--ls-display);
  color:var(--text-strong);
}
.v-h2{
  font-family:var(--f-display);font-weight:var(--fw-bold);
  font-size:var(--fs-h2);line-height:var(--lh-snug);
  letter-spacing:var(--ls-display);color:var(--text-strong);
}
.eyebrow{
  font-family:var(--f-caps);font-size:var(--fs-eyebrow);font-weight:var(--fw-medium);
  letter-spacing:var(--ls-caps-wide);text-transform:uppercase;color:var(--forest);
  display:inline-flex;align-items:center;gap:.7em;
}
.eyebrow::before{content:'';width:26px;height:1.5px;background:var(--forest);display:inline-block;border-radius:2px}
.grad-text{
  background:var(--grad-text);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
}
/* .mono means "a literal value": real monospace + fixed-width figures, so code,
   keys, IDs and hex never reflow as their characters change. */
.mono{font-family:var(--f-code);font-variant-numeric:tabular-nums;font-feature-settings:"ss01" off}
/* .figs means "a number that must hold its column": the brand face with Inter's
   real tabular figures. Use on count-ups, live readouts, numeric table columns
   and chart values — monospace is for literals, not for alignment. */
.figs{font-variant-numeric:tabular-nums}
/* The clipped-gradient fill has no colour of its own: in forced-colors mode and
   on paper it would render as nothing. Fall back to solid ink in both. */
@media (forced-colors: active){.grad-text{background:none;-webkit-text-fill-color:currentColor;color:CanvasText}}
@media print{.grad-text{background:none;-webkit-text-fill-color:currentColor;color:var(--forest)}}

/* ============================================================
   DECOR: blobs, grids, grain
   ============================================================ */
.blob{position:absolute;border-radius:50%;filter:blur(60px);opacity:.5;pointer-events:none;z-index:0}
.dotgrid{background-image:radial-gradient(var(--line) 1.4px,transparent 1.4px);background-size:22px 22px}
.linegrid{background-image:linear-gradient(var(--line-soft) 1px,transparent 1px),linear-gradient(90deg,var(--line-soft) 1px,transparent 1px);background-size:32px 32px}

@media (prefers-reduced-motion: reduce){
  /* transition-duration must be a TRUE 0s (with 0s delay): duration+delay=0 means
     no transition is ever created, so state flips (visibility on overlay children,
     theme colours) commit synchronously. The common `.001ms` hack instead turns
     every property change into a PENDING transition that needs an animation-clock
     tick — under a throttled clock (background tab, low-power mode, automation)
     a modal's descendants can stay computed-hidden long after the scrim flips,
     and focus() refuses them. Nothing in the system waits on transitionend. */
  *,*::before,*::after{animation-duration: .001ms!important;animation-iteration-count:1!important;transition-duration:0s!important;transition-delay:0s!important;scroll-behavior:auto!important}
}
