/* =====================================================================
   Lario dark layer.

   The brand is light only. This sheet adds the second theme, and it is
   nothing but tokens - there is not one rule in it. That is new: it used
   to carry a patch list for fourteen rules in lario.css, eleven that
   hardcoded a colour and three that read a themed token while sitting on
   a surface that does not move. All fourteen are fixed upstream in the
   lario-brand skill now, so the list is gone. tools/check-theme.py keeps
   the second kind from coming back.

   Load it AFTER lario.css and BEFORE the product and chart layers.

   How it works - light-dark(), not a selector
   ------------------------------------------------------------------
   Every token that differs by theme is re-declared once as
   light-dark(light, dark). The light half is byte-identical to the brand
   value, so light mode is unchanged; the dark half is used when the
   element's used color-scheme is dark. That is set three ways:

     :root                      color-scheme: light dark  -> follow the OS
     :root[data-theme="light"]  color-scheme: light       -> forced light
     :root[data-theme="dark"]   color-scheme: dark        -> forced dark

   So the OS preference is honoured with no JavaScript at all, and a
   toggle only has to write one attribute. A browser without light-dark()
   drops these declarations and falls back to the brand values in
   lario.css - which is light mode, correctly rendered.

   color-scheme is a property, not a root-level switch, so any subtree
   can force a theme and the light-dark() tokens inside it resolve to
   that theme - including the ones declared here on :root, because an
   unregistered custom property resolves where it is used.

   color-scheme also tells the browser to draw its own parts dark:
   scrollbars, spinners, the caret, and native select and date popups.

   The derivation
   ------------------------------------------------------------------
   The dark neutrals are not a flip of the light ones. Each one holds the
   brand ramp's hue (OKLCH ~286 at chroma ~0.005 - the zinc the brand
   palette is cut from) and moves lightness until it measures the same
   WCAG contrast against the dark canvas that it measures against white
   today. The hierarchy is preserved as a measurement, not as a guess:

     token       light      on #FFF   dark       on #1D1D20   L / C / h
     ink         #27272A    14.89:1   #F1F1F4    14.92:1      .959 .004 286
     ink-2       #606063     6.27:1   #9E9EA2     6.30:1      .700 .006 286
     gray        #D4D4D8     1.48:1   #3A3A3C     1.48:1      .349 .003 286
     line        #E4E4E7     1.27:1   #2F2F32     1.26:1      .306 .005 286
     line-soft   #EBEBEB     1.19:1   #2B2B2E     1.19:1      .290 .005 286
     mist        #FAFAFA     1.04:1   #1A1A1D     1.03:1      .219 .006 286
     paper       #FFFFFF        -     #1D1D20        -        .232 .006 286

   Every step keeps its DIRECTION as well as its ratio. mist is one step
   BELOW paper in both themes, so a well, a chip and a docs rail stay
   recessed rather than raised, and a card on a mist surface still sits
   above it. An earlier pass anchored paper at #18181B and was then
   forced to put mist above it - there is nothing below #18181B but
   black. Anchoring the recessed step instead and putting paper one step
   up costs nothing and keeps the two themes structurally identical.

   mist is also "text on ink" in the brand sheet - .lr-btn, .lr-faq p.
   Because ink flips too, the pairing survives: a light #F1F1F4 button
   with #1A1A1D text measures 15.40:1, against 14.27:1 for the
   light-mode inverse.

   gray stays faint. #D4D4D8 is 1.48:1 on white, which is already below
   any text threshold, and the dark step holds that 1.48:1. Placeholder
   and disabled text is therefore equally hard to read in both themes.
   That is a brand-level finding, not a dark-mode one, and it belongs
   upstream; fixing it here would have made the two themes disagree
   about what "disabled" looks like.

   What is NOT here
   ------------------------------------------------------------------
   Brand identity and imagery: --lr-lime, --lr-turquoise, --lr-star,
   --lr-fresh, --lr-sky, --lr-glass-line, --lr-photo-fade. A photo card
   is dark in both themes because the fade above it is, so --lr-photo-ink,
   --lr-photo-line and --lr-on-photo are single-valued and live in the
   brand sheet rather than here.
   ===================================================================== */

:root { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* Switching the theme must not animate, and must not be left half-done.
   Set data-theme-switching on <html> for the one frame the attribute
   changes in, and clear it straight after:

     root.setAttribute("data-theme-switching", "");
     root.setAttribute("data-theme", next);
     void root.offsetWidth;                       // force the recalc
     setTimeout(() => root.removeAttribute("data-theme-switching"), 0);

   A theme switch changes the colour of nearly every element on the page.
   Cross-fading all of them over the brand's 0.4s reads as a wash rather
   than as a change, so it is suppressed. That is the whole reason: it is
   a judgement about how the switch should feel, not a fix for anything
   broken. Without it the page still arrives at the right colours, it just
   takes 0.4s and looks like a smear on the way.

   Use setTimeout rather than requestAnimationFrame: a background or
   hidden tab never paints, so rAF never fires and the attribute would
   never be cleared. (That same fact - no paint, no frames, so no
   transition ever progresses - is why an accessibility audit run against
   a hidden browser reports every transitioned colour as stale. It is the
   audit that is wrong there, not the page.) */
:root[data-theme-switching],
:root[data-theme-switching] *,
:root[data-theme-switching] *::before,
:root[data-theme-switching] *::after {
  transition: none !important;
}

:root {
  /* The neutral ramp. Light halves match lario.css exactly. */
  --lr-ink:       light-dark(#27272A, #F1F1F4);
  --lr-ink-2:     light-dark(#606063, #9E9EA2);
  --lr-gray:      light-dark(#D4D4D8, #3A3A3C);
  --lr-line:      light-dark(#E4E4E7, #2F2F32);
  --lr-line-soft: light-dark(#EBEBEB, #2B2B2E);
  --lr-mist:      light-dark(#FAFAFA, #1A1A1D);
  --lr-paper:     light-dark(#FFFFFF, #1D1D20);

  /* Elevation. A black shadow says nothing on a near-black canvas, so the
     dark theme keeps the brand's geometry, deepens the blacks, and adds a
     hairline ring - which is what actually separates a floating surface
     from the page once the shadow cannot.

     light-dark() takes two comma-separated arguments, and a multi-layer
     shadow is itself comma-separated, so the whole value cannot go in
     one. The layer COLOURS go in instead, and the geometry is written
     once. The ring is transparent in light mode, where the shadow is
     still doing its job. */
  --lr-sh-1:    light-dark(rgba(0, 0, 0, .18), rgba(0, 0, 0, .60));
  --lr-sh-2:    light-dark(rgba(0, 0, 0, .16), rgba(0, 0, 0, .50));
  --lr-sh-3:    light-dark(rgba(0, 0, 0, .06), rgba(0, 0, 0, .35));
  --lr-sh-ring: light-dark(rgba(0, 0, 0, 0),   rgba(241, 241, 244, .07));
  --lr-shadow-float:
    0 .6px .6px -1.25px var(--lr-sh-1),
    0 2.29px 2.29px -2.5px var(--lr-sh-2),
    0 10px 10px -3.75px var(--lr-sh-3),
    0 0 0 1px var(--lr-sh-ring);

  /* The dot screen. The brand draws #EBEBEB dots at 40% on white.
     Inverted to light dots on a dark canvas, 40% is a visible grid
     rather than a texture, so the dark halves drop to 5.5% and 7% -
     matched against the light texture at the same 12px grid, then
     checked in both. */
  --lr-texture:      light-dark(rgba(235, 235, 235, .4), rgba(241, 241, 244, .055));
  --lr-texture-well: light-dark(rgba(228, 228, 231, .4), rgba(241, 241, 244, .07));

  /* A 35% ink veil disappears over a dark page, so the dark half is
     deeper and neutral - it is dimming a dark surface, not tinting a
     light one. The brand sheet has no modal, so this token is declared
     here and consumed by the product layer. */
  --lr-scrim: light-dark(rgba(39, 39, 42, .35), rgba(0, 0, 0, .65));
}
