/* =====================================================
   Bramble articles — reading layer.
   =====================================================

   Three jobs, and only these three:

     1. A dark reading mode, driven by :root[data-theme="dark"].
     2. Section breaks — the long pieces run dense, and a reader
        needs a place to put the book down.
     3. The phone. The comparison table and the charts were built
        wide and left to scroll sideways; on a phone they now
        reflow instead.

   Loaded after chrome.css and after each page's inline <style>, so
   it can correct both without either having to know about it. The
   pages keep their own tokens; dark mode redefines those tokens
   rather than restating every rule, which is why a card, a chip or
   a border that already reads var(--cream) follows along without
   being named here.

   Cached for a year under /assets/ (see _headers), so bump the ?v=
   on the <link> in every article when this file changes.
   ===================================================== */


/* =====================================================
   1. Dark reading
   =====================================================

   The palette inverts rather than greys out. --charcoal was the ink
   and is now the light on a dark ground; --linen was the ground and
   is now the deep one. That inversion is what makes the existing
   rules work unchanged: .audio-player-btn is charcoal-on-linen in
   the light and becomes linen-on-charcoal here without a line of
   its own.

   Every value below was measured against its own ground rather than
   picked by eye — the same discipline the homepage's Circle card
   had to learn. On the page ground (#16130F): ink 15.6, body 10.8,
   captions 6.9, links 9.1. On the card ground (#1F1B16): 14.5, 10.0,
   6.6. All clear AA for normal text with room to spare.

   Gold is untouched. It is the one CTA colour, it clears AA on both
   grounds, and it still takes dark text — never white.
   ===================================================== */

:root[data-theme="dark"] {
  --linen:    #16130F;   /* the ground */
  --cream:    #1F1B16;   /* card surfaces */
  --charcoal: #F1EADF;   /* the ink, inverted */
  --bark:     #CDC3B5;
  --stone:    #3C352C;   /* borders, dividers */
  --mist:     #A29889;
  --amber:    #D9A85F;
  --sage:     #6FC894;
  --rust:     #D89393;
  --rust-text:  #E09B9B;
  --steel:    #86A8D0;
  --ink:      #F1EADF;

  --amber-text: #DCAE68;
  --mist-text:  #A89E8F;
  --sage-text:  #7FD3A1;

  --border-soft: rgba(241, 234, 223, 0.11);
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.28), 0 1px 1px rgba(0, 0, 0, 0.2);

  color-scheme: dark;
}

/* The chrome carries its own literal tokens so it renders the same on
   pages that define nothing. That independence is the reason it has to
   be told about dark mode explicitly. */
:root[data-theme="dark"] {
  --bc-linen: #16130F;
  --bc-charcoal: #F1EADF;
  --bc-bark: #CDC3B5;
  --bc-amber: #DCAE68;
  --bc-stone: rgba(60, 53, 44, 0.9);
}

:root[data-theme="dark"] .site-header {
  background: rgba(22, 19, 15, 0.82);
}

/* Two places in the chrome use --bc-charcoal as a ground rather than as
   ink, and inverting the token turns a dark band into a light one with
   linen text on it. Both are dark bands by design, in either theme, so
   they get a literal value here — the footer a shade deeper than the
   page so it still reads as the end of it. */
:root[data-theme="dark"] .launch-banner {
  background: #241E17;
}

:root[data-theme="dark"] footer.site-footer {
  background: #100E0B;
}

:root[data-theme="dark"] .site-nav-menu {
  background: #1F1B16;
  border-color: #3C352C;
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, 0.55);
}

:root[data-theme="dark"] .site-nav-menu-link:hover {
  background: rgba(196, 154, 60, 0.14);
}

/* The wordmark is charcoal line art, which disappears on this ground.
   The linen version already exists — the footer has used it all along.
   Swapping it in CSS keeps the header markup byte-identical to
   scripts/chrome_blocks.py, which check-chrome.py requires. */
:root[data-theme="dark"] .site-logo-full {
  content: url("/assets/BrambleLogo.dark.png");
}

/* Patches — the handful of places a literal colour was written down
   instead of a token. Each one is a light-mode value that cannot
   invert on its own. */
:root[data-theme="dark"] .audio-player-btn:hover { background: #ded5c8; }
:root[data-theme="dark"] .cycle-fig-num { color: #16130F; }
:root[data-theme="dark"] .draft-note { background: #241E16; }
:root[data-theme="dark"] .skip-link { color: #16130F; }
:root[data-theme="dark"] a { border-bottom-color: rgba(220, 174, 104, 0.32); }
:root[data-theme="dark"] a:hover { border-bottom-color: rgba(241, 234, 223, 0.45); }
:root[data-theme="dark"] .keep-reading .kr-title { border-bottom-color: rgba(220, 174, 104, 0.32); }
:root[data-theme="dark"] table.compare tr.is-bramble td { background: rgba(196, 154, 60, 0.09); }
:root[data-theme="dark"] .cta-secondary { border-color: var(--stone); }

/* The charts were drawn with literal fills. They now read tokens
   (see the .ch-fill-* classes below), and these are the values those
   tokens take on a dark card. */
:root[data-theme="dark"] {
  --ch-natural: #D9A85F;
  --ch-substance: #86A8D0;
  --ch-grid: #4A4238;
  --ch-knockout: #1F1B16;
  --ch-rise: #D89393;
  --ch-flat: #86A8D0;
}

:root {
  --ch-natural: #B07840;
  --ch-substance: #4A6A8E;
  --ch-grid: #C4B8A8;
  --ch-knockout: #FFF8F0;
  --ch-rise: #C07070;
  --ch-flat: #4A6A8E;
}

.ch-fill-natural { fill: var(--ch-natural); }
.ch-fill-substance { fill: var(--ch-substance); }
.ch-stroke-grid { stroke: var(--ch-grid); }
.ch-stroke-knockout { stroke: var(--ch-knockout); }
.ch-stroke-rise { stroke: var(--ch-rise); }
.ch-stroke-flat { stroke: var(--ch-flat); }
.ch-text-rise { fill: var(--ch-rise); }
.ch-text-flat { fill: var(--ch-flat); }
.ch-label { fill: var(--fg-1); }
.ch-value, .ch-tick, .ch-axis, .ch-empty { fill: var(--fg-3); }
.ch-value-in { fill: var(--bg-card); }

/* The rings in the footer pattern are linen on charcoal in both
   themes — the footer never changes ground. Nothing to do there. */


/* =====================================================
   2. The toggle
   =====================================================

   It sits on the article's own eyebrow row, not in the header. The
   header is one shared block on every page and is checked byte for
   byte; this belongs to the reading experience, and the reading
   experience is the article.
   ===================================================== */

.article-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}

.article-top .eyebrow {
  margin-bottom: 0;
}

:root .theme-toggle {
  display: none;
}

/* data-theme is only ever set by the boot script, so with scripting off
   the control that does nothing is never offered. The article itself
   reads exactly as it did before. */
:root[data-theme] .theme-toggle {
  display: inline-flex;
}

.theme-toggle {
  flex: 0 0 auto;
  align-items: center;
  gap: 7px;
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 400;
  color: var(--fg-3);
  background: transparent;
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  padding: 7px 14px 7px 11px;
  cursor: pointer;
  transition: color 240ms ease, border-color 240ms ease, background 240ms ease;
}

.theme-toggle:hover {
  color: var(--fg-1);
  border-color: var(--stone);
  background: var(--bg-card);
}

.theme-toggle:focus-visible {
  outline: 2px solid var(--fg-accent);
  outline-offset: 2px;
}

.theme-toggle svg {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
}

/* One button, two faces. The icon shows where the tap goes, not
   where you are. */
.theme-toggle .theme-icon-dark { display: block; }
.theme-toggle .theme-icon-light { display: none; }
:root[data-theme="dark"] .theme-toggle .theme-icon-dark { display: none; }
:root[data-theme="dark"] .theme-toggle .theme-icon-light { display: block; }
.theme-toggle .theme-label-dark { display: inline; }
.theme-toggle .theme-label-light { display: none; }
:root[data-theme="dark"] .theme-toggle .theme-label-dark { display: none; }
:root[data-theme="dark"] .theme-toggle .theme-label-light { display: inline; }

@media (max-width: 420px) {
  .theme-toggle { padding: 7px 11px; }
  .theme-toggle .theme-toggle-text { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .theme-toggle { transition: none; }
}


/* Placed HERE, above sections 3 and 4, and not at the end of the file
   where it was first written. These are unmedia-queried base rules, and
   `.figure-scroll svg { display: block; min-width: 600px }` is the same
   specificity as section 4's `@media (max-width: 620px) .figure-scroll
   svg.ch-wide { display: none }`. Written last, it won the tie and every
   phone got the wide drawing scrolling sideways — the exact failure the
   wide/narrow pair exists to prevent, and invisible on a desktop. Source
   order is load-bearing; keep the base rules above the overrides. */

/* =====================================================
   6. The diagram layer
   =====================================================

   The figure scaffolding and the SVG type scale used to live only
   in is-porn-as-addictive-as-cocaine.html's inline <style>, because
   that was the only article with drawings in it. Three more articles
   now argue a mechanism, and a mechanism is the one thing a drawing
   does better than a paragraph — so the scaffolding moves here and
   every article can reach it.

   The values below are copied from that article verbatim rather than
   improved, because this sheet loads last and would otherwise silently
   restyle the two charts already shipped in it. If you change a number
   here, you are changing those charts too. The inline copy stays where
   it is; it is now a duplicate, and a harmless one.

   The wide/narrow pairing is section 4's rule and still applies: a
   drawing that has to work at 327px gets drawn twice, never scaled.
   ===================================================== */

.figure { margin: 36px 0 30px; }

.figure-scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  background: var(--bg-card); border: 1px solid var(--border-soft);
  border-radius: 16px; padding: 18px 16px;
}

/* `min(600px, 100%)`, not a flat 600px. A flat floor is wider than the
   reading column at every width below 860 — the column is 630, its
   content box 598 after padding — so both charts in the cocaine article
   scrolled sideways from 620px up, by 2px at 700–860 and by 42px at
   640. The narrow drawing was sitting unused the whole time, because
   the swap happens at 620 and the wide one does not fit until 860.

   Capping the floor at the container lets the wide drawing shrink the
   last few percent instead of scrolling: at a 590 column its labels
   render near 11px rather than 13.5, which is legible, where a sideways
   scroll hides the row carrying the argument — the failure section 4
   already calls the worse one.

   This means a figure with no `.ch-narrow` would shrink without limit
   on a phone. Don't ship one. The rule is still to draw it twice. */
.figure-scroll svg { display: block; min-width: min(600px, 100%); width: 100%; height: auto; }

@media (min-width: 860px) {
  .figure { margin-left: -60px; margin-right: -60px; }
}

.figure figcaption {
  font-size: 13.5px; line-height: 1.65; color: var(--fg-3);
  margin: 14px 2px 0;
}
.figure figcaption b { color: var(--fg-2); font-weight: 500; }

.ch-label { font-family: var(--font-sans); font-size: 13.5px; fill: var(--fg-1); font-weight: 400; }
.ch-value { font-family: var(--font-sans); font-size: 12.5px; fill: var(--fg-3); font-variant-numeric: tabular-nums; }
.ch-tick  { font-family: var(--font-sans); font-size: 11.5px; fill: var(--fg-3); font-variant-numeric: tabular-nums; }
.ch-axis  { font-family: var(--font-sans); font-size: 11.5px; fill: var(--fg-3); letter-spacing: .06em; text-transform: uppercase; }
.ch-empty { font-family: var(--font-sans); font-size: 13px; fill: var(--fg-3); font-style: italic; }

/* Two more fills the new diagrams need. --ch-natural is the warm
   amber the existing charts use for the thing being described;
   --ch-substance the cool steel for the thing it is set against.
   These name the same two colours as marks rather than bars. */
.ch-fill-card   { fill: var(--bg-card); }
.ch-fill-muted  { fill: var(--ch-grid); }
.ch-stroke-natural { stroke: var(--ch-natural); }
.ch-stroke-substance { stroke: var(--ch-substance); }
.ch-text-natural { fill: var(--ch-natural); }
.ch-text-substance { fill: var(--ch-substance); }


/* =====================================================
   3. Section breaks
   =====================================================

   These pieces are two to three thousand words and every section
   used to begin the same way: heading, paragraph, paragraph. A
   reader scrolling on a phone had nothing to tell him he had
   finished one thought and started another.

   So each top-level section opens with a short amber rule and more
   air above it. A rule rather than an ornament: the page already
   spends its decoration budget on the Trusted Circle pattern and
   the botanical line work, and a repeating glyph every four hundred
   words would read as furniture. The rule is only present where a
   section genuinely begins — a direct child h2 of the article
   column — so the FAQ's h3s, the keep-reading block and the CTA
   card are untouched.
   ===================================================== */

.article > .container > h2 {
  margin-top: 68px;
}

.article > .container > h2::before {
  content: "";
  display: block;
  width: 36px;
  height: 1px;
  background: var(--fg-accent);
  opacity: 0.6;
  margin: 0 0 20px;
}

/* The first heading after the lede doesn't need the extra air —
   the byline rule and the lede have already broken the page. */
.article > .container > .lead-para + h2 {
  margin-top: 52px;
}

.article > .container > .keep-reading h2::before,
.cta-block h2::before,
.faq h2::before {
  content: none;
}

/* A blockquote-pull is its own break. Give it room to be one. */
.pull {
  margin: 44px 0;
}


/* =====================================================
   4. The phone
   ===================================================== */

@media (max-width: 760px) {
  /* ---- The comparison table ----------------------------------
     It was a 760px-minimum table inside a sideways scroller, which
     on a 375px screen means a man reads two of six columns and has
     to discover the other four by dragging. Under 760 it becomes
     one card per app: the name as the card's heading, then each
     column as a labelled row. The header row goes to screen
     readers only — every cell carries its own label now.

     The labels come from data-label attributes in the markup
     rather than from nth-child guesses, so a reordered column
     cannot silently mislabel a row. */
  .table-wrap {
    overflow: visible;
    border: none;
    border-radius: 0;
    margin: 20px 0 24px;
  }

  .table-wrap table.compare {
    min-width: 0;
    background: transparent;
    display: block;
    font-size: 15px;
  }

  .table-wrap table.compare thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .table-wrap table.compare tbody,
  .table-wrap table.compare tr,
  .table-wrap table.compare td {
    display: block;
    width: 100%;
  }

  .table-wrap table.compare tr {
    background: var(--bg-card);
    border: 1px solid var(--border-soft);
    border-radius: 14px;
    padding: 2px 18px 8px;
    margin: 0 0 14px;
  }

  .table-wrap table.compare tr:last-child {
    margin-bottom: 0;
  }

  .table-wrap table.compare th,
  .table-wrap table.compare td {
    padding: 11px 0;
    border-bottom: 1px solid var(--border-soft);
  }

  .table-wrap table.compare td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--fg-3);
    margin-bottom: 3px;
  }

  /* The app's name is the card's heading, so it drops its label and
     takes the serif — and it must be allowed to wrap, which the
     desktop nowrap forbids. */
  .table-wrap table.compare tbody td:first-child {
    font-family: var(--font-serif);
    font-size: 20px;
    font-weight: 500;
    white-space: normal;
    padding: 16px 0 12px;
  }

  .table-wrap table.compare tbody tr:last-child td {
    border-bottom: 1px solid var(--border-soft);
  }

  .table-wrap table.compare tr td:last-child {
    border-bottom: none;
  }

  .table-wrap table.compare tr.is-bramble {
    border-color: rgba(196, 154, 60, 0.45);
  }

  .table-wrap table.compare tr.is-bramble td {
    background: transparent;
  }
}

/* ---- The charts --------------------------------------------
   Each chart now ships two drawings: the wide one, and one drawn
   for a narrow column. This is duplication, and it is deliberate.
   A single SVG scaled down to a 327px content column renders its
   13.5px labels at about 6px — legible to nobody, least of all to
   the audience this site is overwhelmingly read on. Scrolling the
   chart sideways was the old answer and it hides the row that
   carries the whole argument.

   Only one of the pair is ever displayed, and display:none takes the
   other out of the accessibility tree with it — so a screen reader
   meets one chart, not two. Their title/desc ids differ for the same
   reason two elements may not share an id. */
/* The page's own `.figure-scroll svg` rule outranks a bare `.ch-narrow`,
   so these carry the element too — otherwise both drawings show at once,
   which is exactly what happened the first time. */
.figure-scroll svg.ch-narrow { display: none; }

@media (max-width: 620px) {
  .figure-scroll {
    overflow-x: visible;
    padding: 16px 14px;
  }
  .figure-scroll svg { min-width: 0; }
  .figure-scroll svg.ch-wide { display: none; }
  .figure-scroll svg.ch-narrow { display: block; }
}

@media (max-width: 600px) {
  /* The reading column itself. 17px at 1.7 was set for a laptop;
     on a phone the measure is narrower, so the line height can
     come up and the gap between paragraphs with it. */
  .article > .container > p {
    margin-bottom: 22px;
  }

  .article > .container > h2 {
    margin-top: 54px;
  }

  .article > .container > h2::before {
    margin-bottom: 16px;
  }

  .article > .container > .lead-para + h2 {
    margin-top: 42px;
  }

  /* Figures earn the full width of the phone rather than sitting
     inside the text gutter — the drawing is the point, and 24px of
     margin on each side is 13% of the screen. */
  .figure,
  .table-wrap {
    margin-left: -24px;
    margin-right: -24px;
  }

  .figure .figure-scroll {
    border-radius: 0;
    border-left: none;
    border-right: none;
  }

  .figure figcaption {
    margin-left: 26px;
    margin-right: 26px;
  }

  .table-wrap {
    padding: 0 24px;
  }

  /* Tap targets. A 14px link in a list of links is a 14px target. */
  .keep-reading li { margin-bottom: 22px; }
  .cta-primary,
  .cta-secondary { padding: 14px 24px; }
  .cta-row { gap: 10px; }
  .cta-block { padding: 28px 20px; }

  /* The provider cards and the stat cards run edge to edge on a
     phone; their inner padding is doing the work instead. */
  .prov { padding: 22px 0; }
  .prov-head { gap: 8px; }
}


/* =====================================================
   5. The plate — a held still inside the reading
   =====================================================

   One photograph per article, set at the turn where the piece
   changes direction. It is the held-shot idiom the homepage uses
   for its clips, reduced to a single frame: 16:7, 6px radius,
   masked so the bottom edge dissolves into the page instead of
   cutting a hard line across it.

   A still rather than a clip, deliberately. Nothing has to stay
   readable on top of it, so it needs no scrim — but a video here
   would need the lazy-load contract check-clips.py gates, a poster,
   a reduced-motion branch and a boomerang encode, all to put motion
   behind prose a man is trying to read. The frame says the same
   thing for 15KB.

   The mask is alpha, not a scrim, which is why the same rule works
   on the light ground and the dark one without being restated.

   Never put text on one of these. The hero and the Circle card both
   had to learn that the token scale this site is built from does not
   survive a photograph; here the copy stays on the page ground and
   the question never arises.
   ===================================================== */

.plate {
  margin: 38px 0 34px;
}

.plate img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 7;
  object-fit: cover;
  border-radius: 6px;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 62%, transparent 100%);
}

/* On the dark page a frame graded for linen reads a stop hot. This
   is a comfort adjustment on an image carrying no text, not a
   contrast fix — brightness() is linear and could not win one of
   those anyway. */
:root[data-theme="dark"] .plate img {
  filter: brightness(0.88) saturate(0.94);
}

.plate figcaption {
  margin-top: 10px;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  color: var(--fg-3);
}

@media (max-width: 600px) {
  /* Same reasoning as .figure above: the drawing is the point, and
     24px a side is 13% of the screen. */
  .plate {
    margin-left: -24px;
    margin-right: -24px;
  }
  .plate img { border-radius: 0; }
  .plate figcaption { margin-left: 26px; margin-right: 26px; }
}
