/* Briefing Engine — shared stylesheet.
   Copied verbatim into every run directory by briefing.py; edit here. */

/* ponytail: font loaded here, not via a <link> in _page(). _page() is duplicated
   in the website's compose.py, so adding a <link> would drag this CSS-only phase
   into the HTML byte-identity constraint and force both repos to deploy together.
   Cost: a slower font load. Upgrade path: a <link> in _page() if it ever matters. */
@import url('https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;600;700&display=swap');

:root {
  --ground: #F0F0EC;
  --card: #FFFFFF;
  --ink: #6B6E6A;
  --ink-on-ground: #656865;
  --heading: #2F5E86;
  --green: #237A72;
  --divider: #E1E2DC;
  /* Banner gradient: drawn by the website's chrome fragment, not by this file; a cross-repo drift test pins both values in both repos. */
  --grad-a: #457B5E;
  --grad-b: #3B5D83;

  --font-ui: "Schibsted Grotesk", "Segoe UI", -apple-system, sans-serif;
  --font-read: Georgia, "Times New Roman", serif;

  /* Body grey for the current surface: --ink-on-ground on the cream ground,
     swapped to --ink inside white boxes. --ink clears AA on the ground too
     (4.52:1 vs the 4.5 bar) but only just; --ink-on-ground is 4.94:1, so the
     second grey exists for headroom, not because --ink fails. On the card
     --ink is 5.17:1. Surfaces that paint a third colour (badges) must set
     their own `color` in the same rule rather than inherit --ink-body. */
  --ink-body: var(--ink-on-ground);
}

body { font-family: var(--font-read); max-width: 52rem;
       margin: 2rem auto; padding: 0 1rem; line-height: 1.5;
       background: var(--ground); color: var(--ink-body); }
h1 { font-family: var(--font-ui); color: var(--heading);
     font-size: 1.7rem; border-bottom: 2px solid var(--heading); padding-bottom: .4rem; }
h2 { font-family: var(--font-ui); color: var(--heading);
     font-size: 1.35rem; margin-top: 2.2rem; border-bottom: 1px solid var(--divider);
     padding-bottom: .25rem; }
h3 { font-family: var(--font-ui); color: var(--heading);
     font-size: 1.05rem; margin-bottom: .45rem; }
a { color: var(--heading); }
section.category { --ink-body: var(--ink); color: var(--ink-body);
                   background: var(--card); border-radius: 10px;
                   padding: 1rem 1.25rem; margin: 1.5rem 0;
                   container-type: inline-size; }
.narrative { --ink-body: var(--ink); color: var(--ink-body);
             background: var(--card); padding: .8rem 1.1rem; border-left: 3px solid var(--green); }
ul.sections li { margin: .35rem 0; }
/* The reading column's own bulleted teasers get more breathing room than
   the compact rail lists (entities), which keep the tighter default above.
   On the briefing card the teasers now live in .cat-foot (Phase 12), not
   .cat-main, so both selectors carry the same rule. */
.cat-main ul.sections li, .cat-foot ul.sections li { margin: .75rem 0; }
/* Card layout: the two `section.category` cards style the same wrapper
   class names differently, so every rule below is scoped to one or the
   other. Detail card (`.detail-brief`, Phase 6, unchanged by Phase 12):
   the narrative renders full width above the split, then `.cat-aside`
   (map/Related) floats left of `.cat-main` (teasers). Briefing card
   (`.brief`, Phase 12): `.cat-body` holds `.cat-aside` (map/Related),
   `.cat-main` (narrative) and `.cat-entities` (entities) — map/Related and
   entities flank the narrative as a two-column grid; a `.cat-foot` below
   `.cat-body`, always full card width, holds the widest content (Trend
   watch, the teasers drawer, the items link) that a narrow column or rail
   would squeeze. `container-type: inline-size` on section.category makes
   the split respond to the CARD's own width, not the viewport — a
   container query cannot style its own container, so the split lives on
   child wrappers instead; below the breakpoint (and in browsers without
   container-query support) they simply stack in DOM order, which is also
   the phone layout. 48rem chosen from the rendered result: a single-column
   card is ~800px (body's 52rem minus its
   own padding) so the split applies there, but the ~556px card produced by
   the website's two-up grid (100rem breakpoint) stays stacked rather than
   splitting into four cramped columns. */
.cat-aside { margin: 0 0 .8rem; }
@container (min-width: 48rem) {
  .detail-brief .cat-aside { float: left; width: 33%; margin: 0 1.5rem .8rem 0; }
  .detail-brief .cat-main { display: flow-root; }
  /* No empty column: the grid only applies when .cat-main exists AND at
     least one of .cat-aside/.cat-entities exists, via :has() (same browser
     floor as container queries, no markup change needed). column-gap only
     (not a shorthand row gap): a row gap would add spurious space above
     .cat-entities when .cat-aside is absent (an empty auto row), and would
     replace .cat-aside's own .8rem bottom margin — which already spaces
     .cat-aside from .cat-entities in the shared left column — with 1.5rem.
     The plain grid-area rules below need no :has() guard of their own —
     grid-area is a no-op outside a grid — but .cat-main's margin reset
     does: the guard's extra specificity is what lets the reset beat the
     later unscoped `.brief .cat-main { margin: 0 0 .8rem; }` rule on grid
     cards, where the narrative spans both rows and a bottom margin would
     pad the body. It also limits the reset to cards where the grid
     actually applies, so a card with no grid (narrative-only) keeps its
     .8rem margin. */
  .brief .cat-body:has(> .cat-main):has(> .cat-aside, > .cat-entities) {
    display: grid;
    grid-template-columns: 33% minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    grid-template-areas: "aside main" "entities main";
    column-gap: 1.5rem;
  }
  .brief .cat-aside { grid-area: aside; }
  .brief .cat-main { grid-area: main; }
  .brief .cat-entities { grid-area: entities; }
  .brief .cat-body:has(> .cat-main):has(> .cat-aside, > .cat-entities) > .cat-main { margin: 0; }
}
.brief .cat-main { margin: 0 0 .8rem; }
.brief .cat-foot {
  border-top: 1px solid var(--divider); margin-top: 1rem; padding-top: 1rem;
}
.items-link { font-size: .9rem; }
.also-in { color: var(--ink-body); font-size: .875rem; }
.dedup-note { color: var(--ink-body); font-style: italic; font-size: .9rem; }
.trend { --ink-body: var(--ink); color: var(--ink-body);
         background: var(--card); border-left: 3px solid var(--green); padding: .5rem .9rem;
         margin: .6rem 0; }
.trend-provenance { background: var(--card); color: var(--ink);
                    border: 1px solid var(--divider); border-radius: 3px;
                    padding: 0 .35rem; font-size: .875rem; }
.trend-lines { margin: .4rem 0; }
.trend-line { margin: .3rem 0; font-size: .9rem; }
.trend-line .trend-provenance { margin-left: .3rem; }
.trend-line .trend-details { font-size: .875rem; margin-left: .3rem; }
/* Designer rule (docs/brand-refresh-plan.md): menus, buttons, CTAs,
   headers and footers take --font-ui; the briefing content itself
   (narrative, teasers, entity names, etc) stays --font-read/Georgia.
   .related (the "Related:" line) is navigation, not content, so it is
   grouped here too. .meta inside a summary is not listed separately: it
   has no font-family of its own, so it inherits --font-ui from the
   summary it sits in. */
details.stories > summary, .items-link, .to-top, .back-to-top,
.trend-details, footer, .related { font-family: var(--font-ui); }
details.stories > summary { cursor: pointer; list-style: none; font-size: .9rem;
                            margin: .5rem 0 0; }
details.stories > summary::-webkit-details-marker { display: none; }
details.stories > summary::before { content: "\25B8"; display: inline-block;
                                    margin-right: .4rem; color: var(--green); }
details.stories[open] > summary::before { content: "\25BE"; }
/* Interactive text uses the link colour, not --green: green on the grey ground
   is 4.48:1, just under WCAG AA. Green stays on arrows, borders and fills. */
details.stories > summary .expand-label { color: var(--heading);
                                          text-decoration: underline; }
details.stories > summary h3 { display: inline; margin: 0; }
details.stories > summary .meta { display: block; margin: .15rem 0 0 1rem; color: var(--ink-body); }
details.stories details.stories { margin-left: 1rem; }
.item { margin: 1.2rem 0; }
.item .meta { color: var(--ink-body); font-size: .875rem; margin: 0 0 .3rem; }
.story { border-left: 2px solid var(--divider); padding-left: .8rem; }
ul.sources li { font-size: .9rem; margin: .2rem 0; }
.badge { background: var(--card); color: var(--ink); border: 1px solid var(--divider);
         border-radius: 3px; padding: 0 .35rem; font-size: .875rem; }
.empty { color: var(--ink-body); font-style: italic; }
footer { margin-top: 3rem; color: var(--ink-body); font-size: .875rem; }
table { border-collapse: collapse; } td, th { padding: .2rem .8rem .2rem 0; text-align: left; }
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: .8rem; }
.ind-card { --ink-body: var(--ink); color: var(--ink-body);
            background: var(--card); border: 1px solid var(--divider); padding: .5rem .7rem; }
.ind-name { font-size: .875rem; margin: 0; }
.ind-value { font-size: 1.05rem; margin: .1rem 0; }
.ind-date, .ind-delta { color: var(--ink-body); font-size: .875rem; }
.ind-delta { margin: 0 0 .3rem; }
.spark { width: 100%; height: 4rem; }
.spark-line { stroke: var(--green); stroke-width: 2; }
.spark-dot { fill: var(--green); }
.spark-label { fill: var(--ink-body); font-size: 9px; font-family: Georgia, serif; }
.chart { width: 100%; height: auto; }
.chart-line { stroke: var(--green); stroke-width: 2; }
.chart-dot { fill: var(--green); }
.chart-grid { stroke: var(--divider); stroke-width: 1; }
.chart-axis { stroke: var(--divider); stroke-width: 1; fill: none; }
.chart-tick, .chart-axis-label {
  fill: var(--ink-body); font-size: 11px; font-family: Georgia, serif; }
table.econ-detail td, table.econ-detail th { border-bottom: 1px solid var(--divider); font-size: .875rem; }
.phase-line { font-size: .95rem; }
ul.gate-lines { font-size: .9rem; }
ul.entity-list li { margin: .2rem 0; font-size: .9rem; }
.entity-count { color: var(--ink-body); font-size: .875rem; }
.related { margin: .5rem 0; }
.related form, .related form button,
form.subscribe-button, form.subscribe-chip { display: inline; margin: 0; }
form.subscribe-chip button {
  background: none; border: 1px solid var(--divider); border-radius: 3px;
  color: var(--heading); font-size: .875rem; padding: 0 .3rem; cursor: pointer;
}
form.subscribe-button button {
  background: var(--green); color: var(--card); border: none; border-radius: 4px;
  font-size: .875rem; padding: .3rem .7rem; cursor: pointer; margin-bottom: .8rem;
}
.category-map { display: block; width: 100%; max-width: 22.5rem; height: auto; margin: .6rem 0 .2rem; }
/* Symbol categories carry a small icon on the heading line instead of a
   full-width banner; the <span> holds the heading text so the icon can be
   pushed to the right edge. */
.has-icon { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.category-icon { flex: none; height: 1.7rem; width: auto; border-radius: 3px; }
/* Topic tiles (brand-refresh Phase 8). This grid IS the page's contents
   list -- it replaced the plain link nav -- so it keeps `id="contents"`,
   which every card's "↑ Top" link targets. The category name is baked
   into the artwork, so the link's accessible name is the img `alt`, and
   art that is missing or slow degrades to a readable text link sitting
   on the anchor's own ground rather than a broken-image icon: hence the
   background, the min-height and the link colour on `.tiles a`, which
   apply whether or not the image paints. --heading on --divider is
   5.26:1 (the same pair Phase 7's chips use). auto-fill/minmax lays the
   tiles out with no media query and no per-slug rule, so replacing the
   art is a file drop. Above MAX_FULL_SIZE_TILES subscribed categories
   (Phase 10) the nav carries an extra `compact` class: same PNGs, but
   cropped to the middle third (the band the art keeps every name
   inside) with a tighter frame and gap, so a large subscription list
   doesn't push the news two screens down. */
.tiles ul { list-style: none; margin: 0 0 1.5rem; padding: 0; display: grid;
            grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
            gap: .75rem; }
.tiles a { display: flex; align-items: center; justify-content: center;
           min-height: 3rem; padding: .2rem; border-radius: 8px;
           background: var(--divider); color: var(--heading);
           font-family: var(--font-ui); font-size: .9rem; text-align: center; }
.tiles img { display: block; width: 100%; height: auto; border-radius: 6px; }
.tiles a:focus-visible { outline: 2px solid var(--heading); outline-offset: 2px; }
.tiles.compact ul  { gap: .3rem; }
.tiles.compact a   { padding: 3px; min-height: 0; }
.tiles.compact img { aspect-ratio: 533 / 102.67; object-fit: cover; object-position: center; }
.to-top { font-size: .875rem; margin: -.4rem 0 0; }
/* Detail page (brand-refresh Phase 6). */
.page-head { display: flex; justify-content: space-between; align-items: baseline;
             gap: 1rem; flex-wrap: wrap; }
/* Body grey, not --heading: the wireframe repeats the category name in
   the page header and the card title, but only the card title is blue —
   the page header row reads as ordinary body text. --ink-on-ground (not
   --ink) because this text sits on the grey page ground, same reasoning
   as --ink-body above. Specificity (0,1,1) beats the bare `h1` rule's
   (0,0,1) regardless of source order. */
.page-head h1 { border-bottom: none; padding-bottom: 0; margin: 0; color: var(--ink-on-ground); }
.page-date { font-family: var(--font-ui); color: var(--ink-on-ground); margin: 0; }
/* Topic tabs (brand-refresh Phase 7). The engine emits an empty
   `data-category-tabs` marker and the website substitutes the <nav> and
   its links at serve time; the classes live here, exactly as
   form.subscribe-button's do. The strip WRAPS -- no overflow-x scroller,
   no "show more": a scroller hides options and strands keyboard users,
   and 30 chips only fit a narrow screen if they are allowed to stack.
   Colours are the two pairs that clear AA (tests/test_style.py): white
   (--card) on --green is 5.12:1 for the current tab, --heading on
   --divider is 5.26:1 for the rest. The unselected chip takes the link
   colour rather than body grey because on --divider the alternatives
   both fail: --green is 3.93:1 there (it is 4.48:1 on --ground, a
   different pairing) and --ink-on-ground is 4.33:1. */
.topic-tabs { display: flex; flex-wrap: wrap; gap: .25rem;
              font-family: var(--font-ui); margin: 0 0 1rem; padding: 0; }
.topic-tabs a { background: var(--divider); color: var(--heading);
                border-radius: 3px; text-decoration: none;
                font-size: .8rem; line-height: 1.5; padding: .2rem .45rem; }
.topic-tabs a.current { background: var(--green); color: var(--card); }
.topic-tabs a:focus-visible { outline: 2px solid var(--heading); outline-offset: 2px; }
/* Card title underline (wireframe): neither card title is underlined.
   One rule for both cards — the briefing card's `<h2>` (Phase 5) and the
   detail card's `<h2>` (Phase 6) are both a direct child of a
   `section.category`. Follow-up: the website's `#sample-brief` copy on
   its home page keeps its own global `h2` underline until the website
   adds the equivalent rule; that block's own comment already says drift
   there is expected and cosmetic. */
section.category > h2 { border-bottom: none; padding-bottom: 0; margin-top: 0; }
.section-heading { border-bottom: none; padding-bottom: 0; }
/* A viewport media query, not a container query like .cat-aside/.cat-main
   above: the analysis sits directly in the page body, not inside a card
   whose own width varies (the website never places two of these side by
   side), so there is no container to query. The max-width cap lives here
   too: a full-width headline reads as "more AI" only on a wide screen —
   at a 400px viewport the cap left barely half the column in use. 25ch
   (not the designer's 22ch) is the tightest cap that still lands a
   ~48-character heading on two lines rather than three, checked in the
   rendered preview since h2 uses --font-ui, not the arithmetic. */
@media (min-width: 52rem) {
  .section-heading { max-width: 25ch; }
  .section-split { display: grid; grid-template-columns: 2fr 1fr; gap: 1.5rem; }
  .section-implications { border-left: 1px solid var(--divider); padding-left: 1.5rem; }
}
.back-to-top { font-size: .875rem; text-align: right; margin: .8rem 0 2.5rem; }
/* The five top-level detail-page drawers (Trend watch, Key people,
   Companies, Countries, Expand stories and insights) read as full-width
   menu rows separated by hairlines, per the wireframe — scoped to this
   class alone so nested entity-group drawers and the briefing page's
   drawers keep the tighter default above. */
.drawer { border-top: 1px solid var(--divider); }
/* ponytail: :last-of-type matches the last <details> among siblings, not
   the last .drawer — correct today because nothing emitted after this
   block (the analysis loop, all four econ-zone renderers) is a <details>.
   A future top-level <details> added after the drawers would silently eat
   this closing hairline; upgrade path is an explicit class on the last
   drawer or a :not() selector if that ever happens. */
.drawer:last-of-type { border-bottom: 1px solid var(--divider); }
details.stories.drawer > summary { padding: 1rem 0; margin: 0; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
