/* ==========================================================================
   Fovea — design tokens
   --------------------------------------------------------------------------
   Art direction: "calm clinical". Restraint over decoration. This is a health
   screening tool, so it has to read as trustworthy rather than exciting — no
   gamified scores, no alarm-red, no gradient soup. Depth comes from precise
   spacing and hairline borders, not drop shadows.

   The single hard rule that shapes everything below: BRAND COLOUR MUST NEVER
   TOUCH A TEST SURFACE. A tinted chrome beside a colour plate shifts perceived
   hue via simultaneous contrast, and any tint near an optotype lowers effective
   contrast. Both silently corrupt the result. Test surfaces therefore get their
   own strictly neutral palette, defined at the bottom of this file.
   ========================================================================== */

:root {
  /* ---------------------------------------------------------------- brand
     Deep indigo: the colour of optics and instruments, calm and non-clinical
     without being playful. The amber accent is a deliberate nod to the macula
     lutea — the "yellow spot" the fovea sits in — and is used sparingly. */
  --brand-50:  #f1f0ff;
  --brand-100: #e5e2ff;
  --brand-200: #cec9ff;
  --brand-300: #aea4ff;
  --brand-400: #8b78fd;
  --brand-500: #6d55f5;
  --brand-600: #5a3ee2;
  --brand-700: #4a2fbe;
  --brand-800: #3d289a;
  --brand-900: #33257a;
  --brand-950: #1f1550;

  --accent-300: #ffd68a;
  --accent-500: #f0a11a;
  --accent-600: #d1830a;
  --accent-700: #a66300;

  /* ------------------------------------------------------------ semantic
     Two separate families, and the distinction is deliberate.

     RESULT tokens describe a screening outcome. They carry NO good/bad axis:
     a colour vision deficiency is a difference, not a failure, and a red
     "result" would frighten someone over a test that cannot diagnose anything.
     The three outcomes are Typical / Follow-up suggested / Inconclusive, and
     every one is always paired with an icon and a word so the meaning never
     rests on hue — this app's core audience cannot rely on hue.

     ERROR tokens are for system failures only: storage full, canvas
     unavailable, calibration invalid. Red lives here and nowhere else. */
  --ok-fg:        #0f6f42;
  --ok-bg:        #e7f6ee;
  --ok-border:    #b6e3ca;

  --watch-fg:     #8a5300;
  --watch-bg:     #fdf3e2;
  --watch-border: #f5dcae;

  --error-fg:     #a63a24;
  --error-bg:     #fdeeea;
  --error-border: #f6cec3;

  --info-fg:      #2b4a8f;
  --info-bg:      #ecf1fd;
  --info-border:  #c6d5f4;

  /* --------------------------------------------------------- typography */
  --font-display: "Instrument Sans", "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body:    "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* ---------------------------------------------------------------------
     The type scale steps by 0.1 log units (x1.25893) — which is exactly the
     step between two adjacent lines of a LogMAR acuity chart. Every heading is
     therefore one chart line larger than the one below it, and the large-text
     accessibility mode is literally "one line up" on the chart. Half-steps
     (x1.1220, 0.05 log) fill in where the UI needs a finer gradation.
     --------------------------------------------------------------------- */
  --text-2xs:  0.708rem;   /* 11.3px  -1.5 lines — legal/footnote only */
  --text-xs:   0.794rem;   /* 12.7px  -1.0 line */
  --text-sm:   0.891rem;   /* 14.3px  -0.5 line */
  --text-base: 1rem;       /* 16.0px   baseline — never smaller for body copy */
  --text-lg:   1.122rem;   /* 18.0px  +0.5 line */
  --text-xl:   1.259rem;   /* 20.1px  +1.0 line */
  --text-2xl:  1.585rem;   /* 25.4px  +2.0 lines */
  --text-3xl:  1.995rem;   /* 31.9px  +3.0 lines */
  --text-4xl:  2.512rem;   /* 40.2px  +4.0 lines */
  --text-5xl:  3.162rem;   /* 50.6px  +5.0 lines */
  --text-6xl:  3.981rem;   /* 63.7px  +6.0 lines */

  --leading-tight:  1.15;
  --leading-snug:   1.3;
  --leading-normal: 1.55;
  --leading-relaxed:1.7;

  --tracking-tight: -0.02em;
  --tracking-snug:  -0.011em;
  --tracking-wide:  0.02em;
  --tracking-caps:  0.06em;

  --weight-normal:   400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;

  /* ------------------------------------------------------------- spacing
     4px base. Named by step so the scale can be retuned in one place. */
  --space-0:  0;
  --space-1:  0.25rem;
  --space-2:  0.5rem;
  --space-3:  0.75rem;
  --space-4:  1rem;
  --space-5:  1.25rem;
  --space-6:  1.5rem;
  --space-8:  2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-32: 8rem;

  /* -------------------------------------------------------------- shape */
  --radius-xs:   4px;
  --radius-sm:   6px;
  --radius-md:   10px;
  --radius-lg:   14px;
  --radius-xl:   20px;
  --radius-2xl:  28px;
  --radius-full: 9999px;

  --border-width: 1px;

  /* ---------------------------------------------------------- elevation
     Two-layer shadows: a tight contact shadow plus a wide ambient one. Kept
     very low-opacity so cards read as paper, not as floating glass. */
  --shadow-xs: 0 1px 2px rgb(16 20 28 / 0.04);
  --shadow-sm: 0 1px 2px rgb(16 20 28 / 0.05), 0 2px 6px rgb(16 20 28 / 0.04);
  --shadow-md: 0 2px 4px rgb(16 20 28 / 0.05), 0 8px 20px rgb(16 20 28 / 0.06);
  --shadow-lg: 0 4px 8px rgb(16 20 28 / 0.06), 0 16px 40px rgb(16 20 28 / 0.09);
  --shadow-focus: 0 0 0 3px var(--focus-ring);

  /* ------------------------------------------------------------- motion
     Nothing may animate within sight of a test target, so these tokens are for
     chrome only. Durations stay short; this is a utility, not a showreel. */
  --ease-out:   cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out:cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring:cubic-bezier(0.34, 1.56, 0.64, 1);

  --dur-instant: 90ms;
  --dur-fast:    150ms;
  --dur-normal:  240ms;
  --dur-slow:    400ms;

  /* -------------------------------------------------------------- layout */
  --measure:        68ch;   /* readable line length for prose */
  --container-sm:   40rem;
  --container-md:   56rem;
  --container-lg:   72rem;
  --container-xl:   84rem;
  --header-height:  60px;

  --z-base:    0;
  --z-sticky:  100;
  --z-header:  200;
  --z-overlay: 300;
  --z-modal:   400;
  --z-toast:   500;
}

/* ==========================================================================
   Light theme (default)
   Contrast ratios against --surface-0 (#ffffff), WCAG 2.2:
     --text-1 #14181f  17.8:1  AAA
     --text-2 #4a5462   7.7:1  AAA
     --text-3 #697384   4.8:1  AA   (never used below 16px)
     --brand-600        6.5:1  AA
     --brand-700        8.6:1  AAA (used for text; 600 is for fills)
   ========================================================================== */
:root,
:root[data-theme="light"] {
  color-scheme: light;

  --surface-0: #ffffff;   /* page */
  --surface-1: #f7f8fa;   /* sunken panels, table stripes */
  --surface-2: #eff1f5;   /* raised cards on a tinted page */
  --surface-3: #e4e7ed;   /* pressed / selected */
  --surface-inverse: #14181f;

  --text-1: #14181f;
  --text-2: #4a5462;
  --text-3: #697384;
  --text-inverse: #ffffff;
  --text-brand: var(--brand-700);

  --border-1: #e5e8ed;    /* decorative hairlines and card edges — not a UI boundary */
  --border-2: #7f8794;    /* control outlines — >=3.2:1 on every light surface (SC 1.4.11) */
  --border-3: #5b6472;    /* hover/active on an interactive border */

  --focus-ring: color-mix(in srgb, var(--brand-500) 45%, transparent);

  --btn-primary-bg:     var(--brand-600);
  --btn-primary-bg-hov: var(--brand-700);
  --btn-primary-fg:     #ffffff;

  --canvas-grid: rgb(20 24 31 / 0.05);
}

/* ==========================================================================
   Dark theme
   Surfaces are near-neutral with a trace of blue so they don't read as muddy.
   Brand is lifted to the 400 step because the 600 fails contrast on dark.
     --text-1 #e9ebf0 on --surface-0 #0e1116  15.9:1  AAA
     --text-2 #a7aebc                          8.5:1  AAA
     --text-3 #7d8698                          5.2:1  AA
   ========================================================================== */
:root[data-theme="dark"] {
  color-scheme: dark;

  --surface-0: #0e1116;
  --surface-1: #151920;
  --surface-2: #1d222b;
  --surface-3: #272d38;
  --surface-inverse: #f2f4f7;

  --text-1: #e9ebf0;
  --text-2: #a7aebc;
  --text-3: #7d8698;
  --text-inverse: #0e1116;
  --text-brand: var(--brand-300);

  --border-1: #232833;    /* decorative hairlines and card edges */
  --border-2: #6b7587;    /* control outlines — >=3.4:1 on every dark surface (SC 1.4.11) */
  --border-3: #8b95a7;    /* hover/active on an interactive border */

  --focus-ring: color-mix(in srgb, var(--brand-400) 55%, transparent);

  --btn-primary-bg:     var(--brand-500);
  --btn-primary-bg-hov: var(--brand-400);
  --btn-primary-fg:     #ffffff;

  --ok-fg:        #6ee7a8;
  --ok-bg:        #0d2a1c;
  --ok-border:    #1c4d34;

  --watch-fg:     #f5c465;
  --watch-bg:     #2e2210;
  --watch-border: #56411b;

  --error-fg:     #f5a08a;
  --error-bg:     #2f1a15;
  --error-border: #573028;

  --info-fg:      #9dbaf5;
  --info-bg:      #141d33;
  --info-border:  #29385c;

  --shadow-xs: 0 1px 2px rgb(0 0 0 / 0.3);
  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.35), 0 2px 6px rgb(0 0 0 / 0.3);
  --shadow-md: 0 2px 4px rgb(0 0 0 / 0.35), 0 8px 20px rgb(0 0 0 / 0.35);
  --shadow-lg: 0 4px 8px rgb(0 0 0 / 0.4), 0 16px 40px rgb(0 0 0 / 0.45);

  --canvas-grid: rgb(233 235 240 / 0.06);
}

/* ==========================================================================
   High contrast — an accessibility mode, not a theme.
   Users with low vision are a core audience here, so this is a first-class
   setting rather than a fallback.
   ========================================================================== */
:root[data-high-contrast] {
  --text-2: var(--text-1);
  --text-3: var(--text-1);
  --border-1: var(--text-1);
  --border-2: var(--text-1);
  --border-3: var(--text-1);
  --border-width: 2px;
  --shadow-xs: none;
  --shadow-sm: none;
  --shadow-md: none;
  --shadow-lg: none;
}

/* Large-text mode scales the root, so every rem-based size follows. */
:root[data-large-text] {
  font-size: 20px;
}

/* ==========================================================================
   TEST SURFACES
   --------------------------------------------------------------------------
   These override the active theme completely while a test is running. They are
   not decorative choices — each is a measurement condition:

   neutral  Munsell N7-ish mid grey. Colour plates are read against a neutral
            surround so no surrounding hue biases perception. Brand colour and
            every tinted element are suppressed here.
   white    Maximum-luminance white for acuity and near vision, so the optotype
            contrast is the ~100% the scoring assumes.
   dark     Near-black for flicker, afterimage and peripheral-drift work, where
            a bright field would swamp the stimulus.
   ========================================================================== */
:root[data-test-mode="neutral"] {
  --test-bg:    #8a8a8a;
  --test-fg:    #1a1a1a;
  --test-fg-2:  #222222;  /* 4.61:1 on the grey surround; #333 was only 3.66 */
  --test-panel: #9a9a9a;
  --test-border:#6e6e6e;
}

:root[data-test-mode="white"] {
  --test-bg:    #ffffff;
  --test-fg:    #000000;
  --test-fg-2:  #333333;
  --test-panel: #f2f2f2;
  --test-border:#cccccc;
}

:root[data-test-mode="dark"] {
  --test-bg:    #0a0a0a;
  --test-fg:    #f0f0f0;
  --test-fg-2:  #b8b8b8;
  --test-panel: #161616;
  --test-border:#2e2e2e;
}
