/*
  The palette, and the only place any of these values exist.

  It lives in public/ rather than in index.css because TWO documents need it
  and only one of them is bundled: the app (index.html, which links it) and
  the static bookmarklet install page (public/bookmarklet.html, which is
  served verbatim and cannot import the bundle's CSS). A second copy of the
  hexes in that page is exactly the drift this avoids -- so no component, and
  no page, hardcodes a colour anywhere else.

  ---------------------------------------------------------------------------
  The palette is near-monochrome on purpose.

  Colour carries no meaning here except in four places: the brand pair, the
  accent, the warning, and the dot on a tag. Everything else is a neutral,
  and the neutrals are close together -- the separation between a surface and
  the surface behind it is often a single hairline rather than a fill. That is
  what makes a dense list readable: with nothing competing, position and
  weight do the work, and the eye goes to the one thing that is coloured.

  The neutrals are green-tinted rather than cool grey. Not enough to be seen
  as green, but enough that the lime tile in the corner belongs to the same
  page instead of being a sticker on it. A grey with a blue undertone beside
  a yellow-green mark is the specific thing that makes a rebrand look
  half-applied.

  THE SIDEBAR IS THE DELIBERATE EXCEPTION. Its five values below are the
  pre-rebrand greys, restored on request after the tinted version shipped
  and was seen: the column is the largest flat field of colour on screen,
  and a tint that is invisible on a 1px hairline is a wash at 240x1080. It
  reads as a grey, which is what it is for. The tint stays where it is
  actually subliminal -- the hairlines, the hovers and the washes on the
  white card -- so nothing here contradicts the paragraph above; the rule is
  that the tint is for small areas, and the column is not one.
*/
:root {
  color-scheme: light dark;

  /* ---------------------------------------------------------- the brand

     The two hexes from the logo, and the only two colours in this file that
     are the SAME in both themes. That is deliberate: the mark is the one
     thing on screen that has to be recognisably itself whatever the OS is
     doing, and a lime tile that turned olive at night would stop being the
     logo.

     They are a PAIR and they are used as a pair. --brand-ink appears on
     --brand and nowhere else -- it is 10.51:1 there, and 1.5:1 on the dark
     canvas, so using it as a text colour in its own right is the one way to
     make this palette illegible. Anything that needs a readable green is
     --accent below. */
  --brand: #C6FF74;
  --brand-ink: #123C2C;

  /* Neutrals, light. --bg is the reading canvas, --side the navigation
     column, and they differ by about 2% -- enough to separate, not enough
     to become a stripe. */
  --bg: #FFFFFF;
  /*
     A REAL grey, not a hint of one. This was #FAFAF9 -- 2% off pure white --
     which read as "white with a rounding error" beside the content card
     rather than as a distinct surface. The product this is modelled on sits
     its navigation on a plainly grey ground and lets the content be the only
     white thing on screen, which is what makes the card look raised at all.
  */
  --side: #F0F0EE;
  --panel: #FFFFFF;
  --ink: #151A17;
  --dim: #6C736E;
  --faint: #939A96;

  /* Two weights of edge. --line is the separator between rows, quiet enough
     to disappear at a glance; --line-strong is a border that has to be seen,
     on a control. */
  --line: #EAECE7;
  --line-strong: #DCDFD8;

  /* --wash is hover. --sel is a selected or active surface -- flatter and
     cooler than a hover, because it persists. Both are tuned against the
     WHITE content pane. */
  --wash: #F3F5F0;
  --sel: #F0F2ED;

  /* ------------------------------------------------------- the sidebar

     Its own three values, and it needs them: --wash and --sel are lighter
     than the sidebar's own ground, so reusing them there made hover
     LIGHTEN a row and selection almost invisible. A surface with a
     different ground needs its own states.

     --side-ink is deliberately softer than --ink. Near-black nav labels on
     a grey column read as heavy and slightly shouty; a dark grey is what
     lets every entry sit at one weight while the active one is picked out
     by its fill instead of by everything else being faded. */
  --side-ink: #3B3D42;
  /*
     The quiet text in the column -- group labels and counts -- and it is a
     MEASURED value, not --dim reused.

     Both of these once sat under WCAG AA on this ground: the group label at
     4.28:1 and the count, which shares this value, at 2.56:1. #666970 is
     4.82:1 on #F0F0EE, with enough headroom that a later nudge to the ground
     does not silently break it again -- as the rebrand proved, when the
     ground moved to a tinted grey and back and this value stayed passing at
     both ends (4.86:1 on the tinted one).

     The count shares this value rather than staying fainter, and is
     distinguished by being right-aligned and tabular instead. Same rule as
     the labels above: separate by position, not by fading below legibility.
  */
  --side-dim: #666970;
  --side-hover: #E7E7E4;
  --side-active: #E0E0DC;

  /* ---------------------------------------------------------- the accent

     The READABLE half of the brand: everything that has to be seen as a
     colour while also being seen as a shape -- link text, a focus ring, the
     2px rule down a selected row.

     It is not --brand. The lime is 1.17:1 on white; as 13px link text or a
     2px hairline on the content card it is not dim, it is absent. So the
     accent is the logo's deep green lifted until it separates from --ink
     without leaving the family: #1B6E4E is 6.20:1 on the canvas and 5.43:1
     on the sidebar, and still unmistakably the same green as the mark.

     In dark mode the relationship inverts -- there the lime IS the readable
     one (13.27:1) and the deep green is the invisible one -- so the accent
     becomes a lime, toned a few points off --brand so that 13px of it does
     not vibrate. This asymmetry is the point, not a compromise: the pair
     stays fixed, and the accent is whichever end of it the ground can carry.

     --accent-ink is what sits ON the accent, for the rare filled case. */
  --accent: #1B6E4E;
  --accent-ink: #FFFFFF;

  /* Something is wrong, and it is not the accent's job to say so.

     This used to be --accent, back when the accent was amber and could pass
     for a warning. A green one cannot: a failed sign-in rendered in the same
     colour as a successful link reads as reassurance. Two call sites -- the
     sign-in error and the bookmarklet's not-ready notice -- and both mean
     the same thing, so they share a token rather than each inventing a red.
     5.82:1 on the canvas, 5.10:1 on the sidebar's ground. */
  --warn: #AF4034;

  /* Inter for everything, including the article body. Linear's own
     proportions only hold if the reading surface shares them; a serif here
     would have made the reader a different application wearing the same
     chrome. Both faces stay declared -- --serif is unused by the app and
     kept only so a future long-form surface has somewhere to start. */
  --sans: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --serif: Newsreader, Georgia, serif;

  /* --ink split into channels, so a shadow or a scrim can borrow the
     palette's own colour at an alpha instead of inventing a grey. Declared
     beside --ink rather than derived, because CSS cannot decompose a hex --
     keep the two in step by hand. */
  --ink-rgb: 21 26 23;

  /* --------------------------------------------------------------- shape

     Radius is a token for the same reason colour is: it is a decision about
     what KIND of thing something is, made once. Two values carry almost the
     whole system.

     --r-pill is anything that reads as a discrete, detachable object: a
     filter, a tag, a chip. Fully round rather than merely rounded, which is
     the difference between "a small button" and "a token". An earlier pass
     argued the filter row was chrome and should match the 5px controls; the
     product it is modelled on rounds them fully, and it turns out that is
     what makes a dense row of them scan as a set rather than as a toolbar.

     --r-panel is the radius of a SURFACE -- something the content sits on,
     rather than something in the content. Bigger, and used sparingly.

     --r-mark is the logo's own corner, and it is a RATIO, not a length: the
     tile is 100 on 652, so anything drawing the mark at any size rounds it
     by 15.3% and matches the favicon exactly. A fixed px radius here would
     be visibly wrong at two of the three sizes the mark is drawn at. */
  --r-pill: 999px;
  --r-panel: 10px;
  --r-mark: 15.3%;

  /* ------------------------------------------------------------ tag hues

     Eight, because a library of a few dozen tags wants enough separation to
     tell two apart at a 7px dot and not so many that neighbouring hues stop
     being distinguishable. A tag is assigned one by hashing its NAME, so the
     colour is stable across sessions, across devices and across reloads
     without anything being stored -- and two people looking at the same tag
     see the same colour.

     Muted on purpose. These are the only saturated things in the palette,
     and at a 7px dot a fully saturated hue reads as an alert.

     These did NOT move with the rebrand, and that is the correct call: they
     are a data palette, chosen so that eight arbitrary tags stay apart from
     each other, and re-tuning them toward the brand would make them worse at
     the only thing they do. The brand-adjacent members (--tag-2's green,
     --tag-8's olive) never collide with the accent in practice because a tag
     is always a 7px dot and the accent is always a rule or a word. */
  --tag-1: #7A5AF8;
  --tag-2: #2E9E6B;
  --tag-3: #C77D34;
  --tag-4: #4C8DF6;
  --tag-5: #B0455E;
  --tag-6: #2C8C8C;
  --tag-7: #5B62C4;
  --tag-8: #7E8B33;
}

/*
  Dark. Guarded with :not([data-theme="light"]) so an explicit light choice
  beats a dark OS, and repeated under [data-theme="dark"] below so the
  toggle wins in the other direction too. Nothing outside these blocks may
  define a colour: a value that exists only here never applies in the
  un-stamped default state, which is the classic unreadable-page bug.

  --brand and --brand-ink are absent from both blocks on purpose -- see the
  note on them above. They are the two values that do not have a night form.

  Not a naive inversion. The canvas is darker than the sidebar's neighbour
  in light mode but LIGHTER than the sidebar here, because on a dark ground
  the eye reads recession as depth -- the navigation column sits behind the
  content rather than beside it. The accent crosses to the other end of the
  brand pair, because #1B6E4E on a black ground is 2.3:1 and gone.
*/
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0C0E0D;
    --side: #0A0B0C;
    --panel: #101312;
    --ink: #F1F4F1;
    --dim: #888F8B;
    --faint: #616864;
    --line: #1C1F1D;
    --line-strong: #292D2A;
    --wash: #131614;
    --sel: #161917;
    /* Softer than --ink here too, for the same reason: on a near-black
       column, #F1F4F1 labels glare. The hover and active fills LIGHTEN
       rather than darken, because the sidebar is already the darkest
       surface on screen and there is nowhere below it to go. */
    --side-ink: #C2C6CC;
    /* 5.40:1 on #0A0B0C. --faint would be 3.39:1 here, which fails. */
    --side-dim: #82868F;
    --side-hover: #17181A;
    --side-active: #1E1F23;
    --accent: #A9E85C;
    --accent-ink: #0C0E0D;
    --warn: #E5847F;
    --ink-rgb: 241 244 241;

    /* Lifted, not the same hues dimmed: a mid-saturation violet that reads
       clearly on white disappears against #0C0E0D. */
    --tag-1: #8E6BFF;
    --tag-2: #3FB984;
    --tag-3: #D99A4E;
    --tag-4: #5E9DFF;
    --tag-5: #D06A82;
    --tag-6: #45A5A5;
    --tag-7: #767DDB;
    --tag-8: #9BAA46;
  }
}

:root[data-theme="dark"] {
  --bg: #0C0E0D;
  --side: #0A0B0C;
  --panel: #101312;
  --ink: #F1F4F1;
  --dim: #888F8B;
  --faint: #616864;
  --line: #1C1F1D;
  --line-strong: #292D2A;
  --wash: #131614;
  --sel: #161917;
  --side-ink: #C2C6CC;
  /* 5.40:1 on #0A0B0C. --faint would be 3.39:1 here, which fails. */
  --side-dim: #82868F;
  --side-hover: #17181A;
  --side-active: #1E1F23;
  --accent: #A9E85C;
  --accent-ink: #0C0E0D;
  --warn: #E5847F;
  --ink-rgb: 241 244 241;
  --tag-1: #8E6BFF;
  --tag-2: #3FB984;
  --tag-3: #D99A4E;
  --tag-4: #5E9DFF;
  --tag-5: #D06A82;
  --tag-6: #45A5A5;
  --tag-7: #767DDB;
  --tag-8: #9BAA46;
}
