/* Voronda — design tokens.

   The palette is twelve tones pulled from the bougainvillea photograph: two grounds, two
   structural neutrals, and an eight-step red ramp running oxblood to pale petal. It exists to
   keep this site off the blue-violet-gradient road every AI company has been on since 2022.

   Pages commit to a ground rather than striping sections: <body data-ground="dark"> or "light".
   Semantic tokens flip with it, so one stylesheet serves both. */

:root {
  /* The twelve, in source order. Raw tones — reach for the semantic tokens below instead. */
  --c-carbon:    oklch(14.5% 0.000 0);       /* #0A0A0A */
  --c-white:     oklch(92.7% 0.007 5.6);     /* #EBE5E6 */
  --c-charcoal:  oklch(31.8% 0.005 67.7);    /* #343230 */
  --c-warmgray:  oklch(46.4% 0.013 39.4);    /* #605754 */
  --c-oxblood:   oklch(33.8% 0.127 27.8);    /* #6A0C0B */
  --c-crimson:   oklch(44.6% 0.179 28.8);    /* #A00707 */
  --c-red:       oklch(52.1% 0.211 29.1);    /* #C60605 */
  --c-scarlet:   oklch(59.2% 0.241 29.2);    /* #EB0805 */
  --c-vermilion: oklch(60.9% 0.229 28.8);    /* #ED2921 */
  --c-rose:      oklch(62.9% 0.200 25.3);    /* #E94645 */
  --c-dusty:     oklch(68.7% 0.152 21.4);    /* #E96F70 */
  --c-petal:     oklch(76.7% 0.088 19.3);    /* #E69D9D */

  /* The bright ground's own whites and blushes: the white of the bougainvillea's bracts, lifted,
     and two tints of its petals for panels. */
  --c-paper:     oklch(97.8% 0.006 17);      /* #FAF5F5 */
  --c-blush:     oklch(94.6% 0.022 17);      /* #F6E8E7 */
  --c-blush-2:   oklch(90.5% 0.048 19);      /* #F3D5D3 */

  --font: Chivo, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;

  /* Fluid type. Display caps at 92px: past that a page is shouting, not designing. */
  /* Display floors at 36px: "Your data stays" in Black has to fit a 390px viewport
     without clipping, and German compounds are longer still. */
  --t-display: clamp(2.25rem, 1.1rem + 5.2vw, 5.75rem);
  --t-h1:      clamp(2rem, 1.3rem + 3.3vw, 4rem);
  --t-h2:      clamp(1.75rem, 1.3rem + 2vw, 2.75rem);
  --t-h3:      clamp(1.3rem, 1.15rem + 0.6vw, 1.625rem);
  --t-lead:    clamp(1.1875rem, 1.1rem + 0.5vw, 1.4375rem);
  --t-body:    clamp(1.0625rem, 1.02rem + 0.22vw, 1.1875rem);
  --t-small:   0.9375rem;
  --t-label:   0.75rem;

  --w-body: 400;
  --w-ui: 500;
  --w-strong: 600;
  --w-display: 900;

  /* Display tracks tight, never past -0.04em or the letters start touching. */
  --track-display: -0.035em;
  --track-h: -0.02em;
  --track-label: 0.15em;

  --lh-display: 0.98;
  --lh-h: 1.12;
  --lh-body: 1.62;
  --lh-body-dark: 1.68; /* light type on dark reads lighter and wants more air */

  --measure: 68ch;
  --measure-tight: 54ch;

  /* Spacing. Deliberately uneven at the top so section rhythm can vary. */
  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.5rem;   --s-6: 2rem;     --s-7: 3rem;     --s-8: 4rem;
  --s-9: 6rem;     --s-10: 8rem;
  --s-section: clamp(2.5rem, 1.8rem + 2.4vw, 4rem);
  --s-section-lg: clamp(3.5rem, 2.6rem + 3.6vw, 6rem);
  --header-h: 72px;
  --gutter: clamp(1.25rem, 0.6rem + 3vw, 4.5rem);
  --shell: 1320px;

  /* Semantic z-index. Never a bare 999. */
  --z-base: 0;
  --z-raised: 10;
  --z-sticky: 100;
  --z-header: 200;
  --z-overlay: 300;
  --z-dialog: 400;
  --z-toast: 500;

  /* Exponential ease-out only. No bounce, no elastic. */
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 140ms;
  --dur: 260ms;
  --dur-slow: 620ms;

  --focus: 2px solid var(--c-scarlet);
  --focus-offset: 3px;

  /* Geometry: one V and one hairline, and nothing else (2026-10-13).
     The V is measured from the mark (assets/logo/voronda-mark.svg): the outer edge of the left arm
     runs from (230, 319) to the point at (619, 988), 30.1° off the vertical, and the right arm
     mirrors it within two degrees. So the V opens at 60°, and a V of any width w is w × 0.866 deep:
     the two sides of an equilateral triangle. Every small V on the site (the ticks where hairlines
     meet) is cut at exactly this angle. The page-wide notches (.bright, .vpanel) and the portraits'
     points are the same V pressed flat by the width of a screen, and keep their own depth.
     The hairline is the one rule for structure: 1px, in the ground's own --rule-firm (between
     cells) or --rule (quieter lines inside a cell). The colours stay in the ground blocks below, so
     the line flips with the ground; --hairline is the ready-made border. In a hairline grid there
     are no shadows, no rounded corners and no filled cards: the lines are the structure. */
  --v-angle: 60deg;                         /* the opening between the arms */
  --v-depth: 0.866;                         /* depth per unit of width: cos(30°) */
  --v-cut: polygon(0 0, 100% 0, 50% 100%);  /* the V as a notch hanging from a rule */
  --v-tick: 0.75rem;                        /* a tick's width; its depth is --v-tick × --v-depth */
  --hair: 1px;
}

/* The hairline, worked out again on every element that changes the ground, so it always takes that
   ground's own rule colour (a custom property is resolved where it is declared). */
[data-ground], .drench, .ground-light, .ground-bright {
  --hairline: var(--hair) solid var(--rule-firm);
  --hairline-soft: var(--hair) solid var(--rule);
}

/* Dark ground — the default for hero, work and contact. */
[data-ground="dark"] {
  --bg: var(--c-carbon);
  --bg-raised: oklch(19% 0.004 30);
  --bg-drench: var(--c-oxblood);
  --ink: var(--c-white);
  /* Warm gray only reaches 3.0:1 on carbon and fails as body text. A tint of the
     soft white gets 6.5:1, which is why muted-on-dark is a tint and not a grey. */
  --ink-muted: oklch(92.7% 0.007 5.6 / 0.62);
  --ink-faint: oklch(92.7% 0.007 5.6 / 0.42);
  /* Faint is for lines and marks. Text that is meant to read quietly gets this, 4.8:1. */
  --ink-faint-text: oklch(92.7% 0.007 5.6 / 0.52);
  --accent: var(--c-scarlet);      /* 3.2:1 on carbon — large text and UI only */
  --accent-text: var(--c-petal);   /* 9.1:1 on carbon — safe for accent body */
  --rule: oklch(92.7% 0.007 5.6 / 0.16);
  --rule-firm: oklch(92.7% 0.007 5.6 / 0.32);
  --sk-glow: oklch(92.7% 0.007 5.6 / 0.16);   /* the soft glow a loading shape breathes with (site.css, loading) */
  --placeholder-bg: oklch(92.7% 0.007 5.6 / 0.07);
  --lh-body-ground: var(--lh-body-dark);
}

/* Light ground — for the pages people actually read at length. */
[data-ground="light"] {
  --bg: var(--c-white);
  --bg-raised: oklch(95.5% 0.004 5.6);
  --bg-drench: var(--c-oxblood);
  --ink: var(--c-charcoal);        /* 10.3:1 */
  --ink-muted: var(--c-warmgray);  /* 5.7:1 */
  --ink-faint: oklch(46.4% 0.013 39.4 / 0.7);
  --ink-faint-text: oklch(46.4% 0.013 39.4 / 0.91);  /* 4.7:1, for quiet text */
  --accent: var(--c-red);          /* 4.9:1 — passes body, only just */
  --accent-text: var(--c-crimson); /* deeper, for accent text that must be read */
  --rule: oklch(31.8% 0.005 67.7 / 0.14);
  --rule-firm: oklch(31.8% 0.005 67.7 / 0.28);
  --sk-glow: oklch(76.7% 0.088 19.3 / 0.36);
  --placeholder-bg: oklch(31.8% 0.005 67.7 / 0.06);
  --lh-body-ground: var(--lh-body);
}

/* Drenched oxblood panels. Verified: soft white 10.1:1, petal 5.8:1. */
.drench {
  --bg: var(--c-oxblood);
  --bg-raised: oklch(38% 0.13 27.8);
  --ink: var(--c-white);
  --ink-muted: oklch(92.7% 0.007 5.6 / 0.72);
  --ink-faint: oklch(92.7% 0.007 5.6 / 0.5);
  --ink-faint-text: oklch(92.7% 0.007 5.6 / 0.68);   /* 4.6:1 on the raised oxblood too */
  --accent: var(--c-petal);
  --accent-text: var(--c-petal);
  --rule: oklch(92.7% 0.007 5.6 / 0.2);
  --rule-firm: oklch(92.7% 0.007 5.6 / 0.38);
  --sk-glow: oklch(76.7% 0.088 19.3 / 0.34);
  --placeholder-bg: oklch(92.7% 0.007 5.6 / 0.09);
  --lh-body-ground: var(--lh-body-dark);
  background: var(--bg);
  color: var(--ink);
}

/* A light band inside a dark page: the light ground's tokens, scoped to one stretch.
   Same values as [data-ground="light"], so contrast is as verified there. */
.ground-light {
  --bg: var(--c-white);
  --bg-raised: oklch(95.5% 0.004 5.6);
  --ink: var(--c-charcoal);
  --ink-muted: var(--c-warmgray);
  --ink-faint: oklch(46.4% 0.013 39.4 / 0.7);
  --ink-faint-text: oklch(46.4% 0.013 39.4 / 0.91);  /* 4.7:1, for quiet text */
  --accent: var(--c-red);
  --accent-text: var(--c-crimson);
  --rule: oklch(31.8% 0.005 67.7 / 0.14);
  --rule-firm: oklch(31.8% 0.005 67.7 / 0.28);
  --sk-glow: oklch(76.7% 0.088 19.3 / 0.36);
  --placeholder-bg: oklch(31.8% 0.005 67.7 / 0.06);
  --lh-body-ground: var(--lh-body);
  background: var(--bg);
  color: var(--ink);
  line-height: var(--lh-body-ground);
}

/* The bright ground: where the home and school pages turn after their dark opening. The bracts'
   white lifted to paper, charcoal ink, the reds at full strength. Measured on paper (and on the
   blush panels): charcoal 12.0:1 (10.8), warm gray 6.6:1 (6.0), quiet text 5.2:1 (4.7), crimson
   7.8:1 (7.0), red 5.7:1; the red button's white label 6.1:1. The header takes the same tokens
   while it sits over a bright stretch (motion.js). */
.ground-bright, .header.is-bright {
  --bg: var(--c-paper);
  --bg-raised: var(--c-blush);
  --ink: var(--c-charcoal);
  --ink-muted: var(--c-warmgray);
  --ink-faint: oklch(46.4% 0.013 39.4 / 0.6);
  --ink-faint-text: oklch(52% 0.012 39.4);
  --accent: var(--c-red);
  --accent-text: var(--c-crimson);
  --rule: oklch(31.8% 0.005 67.7 / 0.12);
  --rule-firm: oklch(31.8% 0.005 67.7 / 0.24);
  --sk-glow: oklch(76.7% 0.088 19.3 / 0.4);
  --placeholder-bg: oklch(31.8% 0.005 67.7 / 0.06);
  --lh-body-ground: var(--lh-body);
  --panel: var(--c-blush-2);
  color-scheme: light;
}
.ground-bright { background: var(--bg); color: var(--ink); line-height: var(--lh-body-ground); }
