/* AtlasDays site tokens.

   The single source for palette, background wash, and card surface. Loaded
   first on every page, ahead of the per-page variant stylesheets, which from
   here on carry layout only. Before this file existed the same token block was
   copy-pasted into eighteen variant stylesheets and had already drifted: the
   homepage used opaque cards, the articles used translucent ones.

   The wash mirrors the app's `ScreenBackground` (AtlasDays/Shared/BackgroundWash.swift)
   at the Atlas blue accent, and the card fills mirror `Color.washedCard`
   (AtlasDays/Shared/CardSurface.swift). Values are resolved to hex here rather
   than recomputed, because the web has no UIColor to mix against. If the app's
   wash math changes, these need recomputing by hand.

   Two strengths, matching the app's intensity steps:
     default        the app's `.medium` step. Marketing surfaces (home, hubs).
     .wash-subtle   the app's `.subtle` step. Long-form reading (learn, help,
                    legal), where sustained text should not sit on a tinted
                    field. Set on <html> by the build.

   The app's wash is calibrated to one phone screen and resolves by ~85% of it.
   A page is far taller than a screen, so the gradient is sized to one viewport
   and does not repeat: the page is tinted where you land and settles into the
   plain canvas by the time you are reading. That keeps the app's shape rather
   than its literal geometry. */

:root,
html[data-theme="dark"] {
  color-scheme: dark;

  /* Brand blue, fixed. `--brand` is the app's accent and is what the wash and
     halo are built from. `--blue` is the interactive color (links, CTAs) and
     darkens in light mode for contrast, so the two cannot share a token. */
  --brand: #428FD2;
  --blue: #428FD2;
  --blue-soft: rgba(66, 143, 210, 0.14);

  /* Action gradient, mirroring the app's `AtlasActionStyle.gradient`
     (AtlasDays/Shared/AtlasActionStyles.swift): the accent through the middle
     falling away to one derived tone at both outer corners, so the button reads
     as a single slightly convex accent surface rather than a wash from one
     color to another. The outer tone is the accent blended toward the
     background — 34% toward black in dark, 20% toward white in light — which is
     how the app derives a hierarchical symbol's secondary layer, and is what
     makes the corners deepen in dark and lift in light on their own.
     Deliberately no glow and no gloss; it should read as a surface, not an
     effect. Values resolved to hex here because the web has no UIColor to mix
     against, so a change to the app's blend amounts needs recomputing by hand. */
  --action-base: #428FD2;
  --action-outer: #2C5E8B;
  --action-border: rgba(255, 255, 255, 0.12);
  /* `AtlasActionStyle.pillGradient`, for selected chips. A button's symmetric
     centre-to-corners fall-off reads as a highlight, which is loud repeated
     across a filter row, so a pill gets a single directional ramp at about
     half the blend instead. Same accent, same derivation. */
  --action-pill-far: #3777AE;

  /* Not pure black. The app is only ever one screen tall, so its wash never
     runs out and the canvas underneath is rarely seen; a page is many screens
     tall, and #000 meant everything below the first viewport was flat black.
     A soft near-black keeps the app's character, gives the card ladder
     somewhere to sit, and stops long articles reading as a void. Every wash
     stop below is this value plus the offset it always had, so the gradient's
     shape is unchanged and only its floor moved. */
  --bg: #0D1117;
  --bg-elevated: #171B21;
  --bg-card: #1F242B;
  --bg-card-strong: #262C34;
  --text: #f4f7fb;
  --muted: #b2b9c5;
  --muted-2: #8790a0;
  --line: rgba(255, 255, 255, 0.10);
  --line-strong: rgba(255, 255, 255, 0.16);
  --shadow: 0 14px 32px rgba(0, 0, 0, 0.32);
  /* Applied as `filter: drop-shadow()` on the iPhone frame, so it follows the
     device silhouette instead of a bounding box. Two stops: a tight contact
     shadow and a wide ambient one. */
  --device-shadow: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.34)) drop-shadow(0 20px 38px rgba(0, 0, 0, 0.40));

  /* Wash, `.medium`. Dark mixes onto the canvas, where every point added is
     pure gain, so the numbers look small and still read. The top stop leans
     harder on blue than on red and green rather than lifting all three
     together: a neutral lift only turns the page grey, and the tint is the
     part that is meant to be felt. Each stop still sits above `--bg` on every
     channel, so the ramp stays monotonic and meets the canvas without a seam. */
  --wash-top: #16283A;
  --wash-mid: #121A24;
  --wash-mid-stop: 52%;
  --wash-end-stop: 86%;
  --halo: rgba(66, 143, 210, 0.17);
}

html[data-theme="dark"].wash-subtle {
  --bg-card: #1D2024;
  --bg-card-strong: #23262B;
  --wash-top: #121E2B;
  --wash-mid: #0F1620;
  --wash-mid-stop: 45%;
  --wash-end-stop: 78%;
  --halo: rgba(66, 143, 210, 0.085);
}

html[data-theme="light"] {
  color-scheme: light;

  --brand: #428FD2;
  --blue: #246ca8;
  --blue-soft: rgba(66, 143, 210, 0.10);

  /* The app builds this from the raw accent in both schemes. Here it is built
     from `--blue`, which light mode already darkens for contrast: a white label
     on the raw #428FD2 clears the app's own threshold but sits under 3:1 on a
     white page, and the site made that call before this gradient existed.
     Same construction, one step darker base. */
  --action-base: #246ca8;
  --action-outer: #5089B9;
  --action-border: rgba(255, 255, 255, 0.25);
  --action-pill-far: #3A7BB1;

  --bg: #F2F2F7;
  --bg-elevated: #ffffff;
  --bg-card: #F7FAFD;
  --bg-card-strong: #ffffff;
  --text: #0d1422;
  --muted: #526075;
  --muted-2: #6c788b;
  --line: rgba(12, 22, 40, 0.09);
  --line-strong: rgba(12, 22, 40, 0.14);
  --shadow: 0 12px 28px rgba(16, 28, 48, 0.08);
  --device-shadow: drop-shadow(0 2px 5px rgba(16, 28, 48, 0.18)) drop-shadow(0 18px 34px rgba(16, 28, 48, 0.22));

  /* Wash, `.medium`. Light mixes toward a brightness-matched accent (#4EA8F7,
     the brand blue lifted to the canvas's own brightness) rather than the raw
     brand blue. Mixing toward the raw color spends lightness to buy chroma,
     which near white is a bad exchange: the page goes dull before it goes
     colorful. Holding brightness fixed means a stronger step only widens the
     gap between channels, so the wash gains color and the page keeps its
     lightness. Same rule the app's `washLightRGB255` follows.

     Stepped up one notch in August 2026: light mode read washed-out next to
     the app at the same `.medium` intensity. Each stop moved from a 13% / 8%
     mix toward #4EA8F7 to 20% / 13%, so the new mid is exactly the old top.
     Blue stays pinned at 247 and only red and green come down, which is the
     brightness-holding rule above. */
  --wash-top: #D1E3F7;
  --wash-mid: #DDE8F7;
  --wash-mid-stop: 42%;
  --wash-end-stop: 84%;
  --halo: rgba(78, 168, 247, 0.19);
}

html[data-theme="light"].wash-subtle {
  --bg-card: #FBFDFE;
  --wash-top: #EBEFF7;
  --wash-mid: #EEF0F7;
  --wash-mid-stop: 31%;
  --wash-end-stop: 62%;
  --halo: rgba(78, 168, 247, 0.06);
}

/* The sticky header sits IN the wash rather than across it. Mixing it from the
   canvas color cut a visible seam directly under the bar, because the top of
   the page is exactly where the wash is strongest and the canvas is furthest
   away. Deriving it from `--wash-top` means the bar starts as a translucent
   slice of the color already behind it and then picks up whatever scrolls
   under, which is how the app's nav bar behaves over its own wash. */
html {
  --header-bg: color-mix(in srgb, var(--wash-top) 82%, transparent);

  /* Horizontal, not diagonal. This deliberately diverges from the app, whose
     `AtlasActionStyle` runs `.topTrailing` → `.bottomLeading`: at the width a
     web CTA gets, that diagonal put the bright band across one corner and read
     as a lighting mistake rather than a curve. `to right` puts the bright stop
     down the button's vertical centre line and fans it out to the left and
     right edges, so a wide button reads as one lit surface across its length
     rather than a band near one end. Jorick's call, August 2026. If the app's
     button is ever revisited, this is the one token intentionally out of
     parity.

     The hairline is an inset ring rather than a `border` so it sits inside the
     fill the way SwiftUI's `strokeBorder` does, without shrinking the gradient
     box; the drop shadow rides in the same declaration. SwiftUI's shadow
     radius is roughly half a CSS blur, so radius 6 becomes 12px. */
  --action-gradient: linear-gradient(
    to right,
    var(--action-outer) 0%,
    var(--action-base) 50%,
    var(--action-outer) 100%
  );
  --action-chrome: inset 0 0 0 1px var(--action-border), 0 2px 12px rgba(0, 0, 0, 0.08);
  --action-pill-gradient: linear-gradient(to right, var(--action-base), var(--action-pill-far));
}

/* Increased contrast thickens the ring, as `AtlasActionStyle.borderColor` does. */
@media (prefers-contrast: more) {
  :root, html[data-theme="dark"] { --action-border: rgba(255, 255, 255, 0.30); }
  html[data-theme="light"] { --action-border: rgba(255, 255, 255, 0.45); }
}

/* The wash sits on the root, not on <body>, so it is never at the mercy of a
   variant stylesheet setting a flat `body { background: var(--bg) }`, and so
   there is no canvas-propagation ambiguity about which box sizes it.

   Three stops rather than two. A straight ramp to the canvas spends its color
   evenly and is visually over by the halfway mark. Holding the mid stop high
   gives the wash a shoulder, so it carries down the page and then lets go,
   which is what depth looks like. The last stop is `--bg` itself, so the
   gradient meets the untinted page below it with no seam at any strength. */
html {
  background-color: var(--bg);
  background-image:
    radial-gradient(ellipse 70% 55% at 50% -8%, var(--halo), transparent 70%),
    linear-gradient(
      to bottom,
      var(--wash-top) 0%,
      var(--wash-mid) var(--wash-mid-stop),
      var(--bg) var(--wash-end-stop)
    );
  background-repeat: no-repeat, no-repeat;
  background-position: top center, top center;
  background-size: 100% 100vh, 100% 100vh;
}

/* Reduced transparency drops to the flat canvas, the way the app's wash does. */
@media (prefers-reduced-transparency: reduce) {
  html {
    background-image: none;
  }
}

/* Jurisdiction flag beside an article H1. Defined here because every article
   loads tokens.css, while the per-page variants that also declare it cover
   only some of the pages that use one. */
.title-flag {
  display: inline-block;
  width: 56px;
  height: 42px;
  border-radius: 8px;
  object-fit: cover;
  border: 1px solid var(--line);
  box-shadow: 0 6px 16px rgba(0,0,0,0.14);
  margin: 0 0 14px;
}
