/* chrome.css — styles for the site chrome shared by EVERY surface: the
   full-screen menu ([data-menu]), the desktop drawer ([data-drawer]), and the
   footer ([data-footer-cta]/[data-footer-meta]). Loaded by both shells (see fragments.mjs)
   so there is one copy. The masthead is NOT here — its markup + CSS differ
   between the shells (index uses <header id="masthead">, the article wraps it
   in a .stack with the reading-morph header), so it stays per-shell.

   Base geometry for [data-menu], [data-drawer], [data-footer-cta], [data-footer-meta] lives
   inline on the markup (see tools/build/chrome.mjs); this file holds the
   responsive tweaks + the desktop drawer's full styling. */

/* ---- selection ----
   The site never defined one, so every selection anywhere — body copy, a
   headline, text inside the search field — painted in the browser's default
   blue. That blue belongs to no palette on this page. A wash of the accent at
   low alpha reads as ours and still clears the AA contrast bar against the
   text it sits behind, in either theme. Kept out of the per-shell sheets so
   articles and index pages cannot drift apart on it. */
::selection { background: rgba(227, 66, 52, 0.20); color: var(--fg); }
:root[data-theme="dark"] ::selection { background: rgba(227, 66, 52, 0.38); color: #FFFFFF; }

/* ---- search fields ----
   input[type=search] keeps its native appearance in Chromium and Safari, which
   adds a clear button drawn in the OS accent colour — another blue we do not
   own, sitting inside a field we drew ourselves. The field is styled end to
   end here; Escape still clears it. */
input[type="search"] { appearance: none; -webkit-appearance: none; }
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }

/* ---- top nav ----
   Three items: Search, Subscribe, About. Archive and Topics used to sit here
   too, and the four-item set collided with the centred wordmark below 1440 —
   Archive was hidden under a breakpoint to buy room. Three items clear the
   wordmark at every width, so that breakpoint is gone, and both routes are
   still one click away in the desktop drawer.

   Subscribe carries no box. The bordered call-to-action was the convention
   for a nav whose job was conversion; this nav's job is navigation.

   It is "Subscribe" and not "Newsletter" because the drawer and the footer
   both already say Subscribe, and the page it opens is /subscribe/ titled
   Subscribe. One destination, one name, in all three places. */
@media (hover: hover) {
  [data-site] .topnav-link:hover { color: var(--accent) !important; }
}
[data-site] .topnav-link:active { color: var(--accent) !important; }
[data-site] .topnav-link { transition: color 0.18s ease; }

/* ---- full-screen menu overlay: responsive type + single-column topics ---- */
@media (max-width: 759.98px) { [data-site] [data-menu] { padding-left: 22px !important; padding-right: 22px !important; padding-bottom: 30px !important; } }
@media (max-width: 759.98px) { [data-site] [data-menu] nav button, [data-site] [data-menu] nav > a { font-size: 2.5rem !important; } }
@media (max-width: 759.98px) { [data-site] [data-menu] [data-panel] > div { grid-template-columns: 1fr !important; gap: 12px !important; } }
@media (max-width: 759.98px) { [data-site] [data-menu] [data-panel] [data-label] { font-size: 1.15rem !important; } }

/* Desktop/tablet: the top-nav "Search" already unfolds a search bar, so the
   search field inside the hamburger menu is redundant — hide it. Phone keeps it
   (no top-nav, so the menu is the only place to search). The form[data-menu-search]
   re-show rule out-specifies this on the in-menu search when it is wanted. */
@media (min-width: 760px) and (max-width: 1023.98px) { [data-site] [data-menu] [data-menu-search] { display: none !important; } }
@media (min-width: 1024px) { [data-site] [data-menu] [data-menu-search] { display: none !important; } }
@media (min-width: 760px) and (max-width: 1023.98px) { [data-site] [data-menu] form[data-menu-search] { display: flex !important; max-width: none !important; } }
@media (min-width: 1024px) { [data-site] [data-menu] form[data-menu-search] { display: flex !important; max-width: none !important; } }

@media (hover: hover) { [data-menu] a[href="/feed.xml"]:hover { color: var(--accent) !important; } }
@media (hover: hover) { [data-site] .footer-nav-link:hover { color: var(--accent) !important; } }
[data-site] .footer-nav-link:active { color: var(--accent) !important; }
[data-menu] a[href="/feed.xml"]:active { color: var(--accent) !important; }

/* ---- footer / subscribe ---- */
@keyframes footerRingSpin { to { transform: rotate(360deg); } }
/* MCF stamp invert. :hover for real pointers, :active for touch. */
@media (hover: hover) {
  .mcf-mini:hover { background: var(--fg) !important; color: var(--bg) !important; }
  .mcf-mini:hover [data-sigil] { background: var(--bg) !important; }
}
.mcf-mini:active { background: var(--fg) !important; color: var(--bg) !important; }
.mcf-mini:active [data-sigil] { background: var(--bg) !important; }

@media (min-width: 760px) and (max-width: 1023.98px) { [data-site] [data-footer-cta], [data-site] [data-footer-meta] { padding-left: 50px !important; padding-right: 50px !important; } }
@media (min-width: 1024px) { [data-site] [data-footer-cta], [data-site] [data-footer-meta] { padding-left: 50px !important; padding-right: 50px !important; } }

@media (max-width: 759.98px) { [data-site] [data-footer-cta] { padding: 30px 8px !important; gap: 22px !important; } }
/* The orbital ring is a desktop-only flourish; on tablet it floats in a large
   empty gap beside the subscribe form, so hide it below the 1024 desktop
   boundary (not just on phones). */
@media (max-width: 1023.98px) { [data-site] [data-footer-ring] { display: none !important; } }
@media (max-width: 759.98px) { [data-site] [data-subscribe-row] { flex-direction: column !important; } }
@media (max-width: 759.98px) { [data-site] [data-subscribe-row] button { width: 100% !important; justify-content: center !important; } }
@media (max-width: 759.98px) { [data-site] [data-footer-meta] { padding: 34px 8px 22px !important; flex-wrap: nowrap !important; gap: 16px !important; min-height: 150px !important; } }
@media (max-width: 759.98px) { [data-site] #globe-footer-desktop { display: none !important; } }
/* stack the footer's left group (globe + nav) vertically on phones, nav centered
   under the globe */
@media (max-width: 759.98px) { [data-site] [data-footer-meta-left] { flex-direction: column !important; align-items: center !important; gap: 18px !important; } }
@media (max-width: 759.98px) { [data-site] [data-footer-meta-left] nav { align-items: center !important; } }
@media (max-width: 759.98px) { [data-site] #globe-footer-mobile { display: inline-flex !important; align-self: center !important; margin-left: 0 !important; margin-bottom: 0 !important; } }
/* centre the back-to-top button in the right column, and bottom-align the
   credits with the footer nav */
@media (max-width: 759.98px) { [data-site] [data-footer-meta-right] [data-backtotop] { width: 28px !important; height: 34px !important; margin-top: 0 !important; transform: translateY(110px) !important; } }
@media (max-width: 759.98px) { [data-site] [data-footer-copy] { margin-bottom: 0 !important; } }

/* ===== Desktop menu panel (data-drawer) =====
   Compact two-column panel that unfolds from the masthead rule on desktop,
   replacing the full-screen overlay there (the overlay remains the mobile/
   tablet menu). Geometry (top offset, width, utility-column centering) is
   measured from the live masthead at open time by chrome.js; colors ride the
   theme tokens, so dark mode inverts the panel automatically. */
@media (max-width: 759.98px) {
  [data-drawer] { display: none !important; }
}
@media (min-width: 760px) {
  [data-drawer] {
    position: fixed; right: 0; z-index: 3200; background: var(--bg);
    border: 1px solid var(--fg); border-top: none; border-right: none;
    box-sizing: border-box; padding: 18px 20px 12px;
    display: flex; flex-direction: column;
    opacity: 0; visibility: hidden;
    /* Unfold downward from the masthead rule instead of sliding into place from
       above it. The panel is positioned with its top ON that rule, so a
       translateY(-10px) start put it 10px INSIDE the header — and since it fades
       in over the same 280ms, its left border was visible crossing the header
       for the first ~150ms of every open and close. Measured before: 10px of
       overlap at t=0, still 2.2px at t=120ms and already 78% opaque.

       clip-path reveals it from its own top edge, so nothing is ever painted
       above the rule and there is no border to catch. Visibility is switched,
       not interpolated — instant on open, held until the fade finishes on
       close — because a transitioned visibility is still hidden on the tick the
       attribute lands. */
    clip-path: inset(0 0 100% 0);
    transition: opacity 0.24s ease, clip-path 0.3s cubic-bezier(.22, 1, .36, 1), visibility 0s linear 0.3s;
  }
  [data-drawer][data-open="1"] {
    opacity: 1; visibility: visible; clip-path: inset(0 0 0 0);
    transition: opacity 0.24s ease, clip-path 0.3s cubic-bezier(.22, 1, .36, 1), visibility 0s;
  }

  /* the top-nav swaps out while the panel is open (class set on the header) */
  [data-top-nav] { transition: opacity 0.2s ease; }
  [data-site] header#masthead.drawer-navhide [data-top-nav],
  #stage[data-site] .masthead.drawer-navhide [data-top-nav],
  .drawer-navhide [data-top-nav] { opacity: 0; visibility: hidden; pointer-events: none; }
  [data-site] header#masthead.drawer-navhide,
  #stage[data-site] .masthead.drawer-navhide { z-index: 3300 !important; }

  [data-drawer] .drawer-cols { display: flex; gap: 18px; }
  [data-drawer] .drawer-topics { flex: 0 0 184px; display: flex; flex-direction: column; }
  [data-drawer] .drawer-label { font-family: 'Fragment Mono', monospace; font-size: 11.5px; letter-spacing: 0.04em; color: var(--accent); margin-bottom: 9px; }
  [data-drawer] .drawer-chips { display: flex; flex-direction: column; }
  /* Latest column. Three headlines, so the tiles are rules rather than boxes —
     four bordered chips holding one word each could carry a border; three
     holding a full headline cannot, and the panel would read as a form. */
  [data-drawer] .drawer-tile { border-top: 1px solid var(--tileborder); padding: 11px 0 11px 14px; display: block; position: relative; text-decoration: none; cursor: pointer; }
  [data-drawer] .drawer-chips > .drawer-tile:last-child { border-bottom: 1px solid var(--tileborder); }
  [data-drawer] .drawer-dot { position: absolute; left: 0; top: 18px; width: 6px; height: 6px; background: var(--accent); opacity: 0; transform: translateX(-4px); transition: opacity 0.18s ease, transform 0.18s ease; }
  [data-drawer] .drawer-tile-label { display: block; transition: transform 0.18s ease; }
  [data-drawer] .drawer-tile-title { display: block; font-family: 'Newsreader', Georgia, serif; font-size: 0.98rem; line-height: 1.3; color: var(--fg); }
  [data-drawer] .drawer-tile-date { display: block; margin-top: 5px; font-family: 'Fragment Mono', monospace; font-size: 10.5px; letter-spacing: 0.04em; color: var(--faded); }
  /* Same rule as the utility links: the tile is the hit target and never moves,
     only its label slides, so resting the pointer inside cannot start a
     hover/unhover loop. */
  @media (hover: hover) {
    [data-drawer] .drawer-tile:hover .drawer-dot { opacity: 1; transform: translateX(0); }
    [data-drawer] .drawer-tile:hover .drawer-tile-label { transform: translateX(10px); }
  }
  [data-drawer] .drawer-tile:active .drawer-dot { opacity: 1; transform: translateX(0); }
  [data-drawer] .drawer-tile:active .drawer-tile-label { transform: translateX(10px); }

  [data-drawer] .drawer-right { flex: 1 1 0; min-width: 0; border-left: 1px solid var(--tileborder); padding-left: 20px; display: flex; flex-direction: column; box-sizing: border-box; }
  [data-drawer] .drawer-search { display: flex; align-items: center; gap: 4px; height: 34px; border: 1px solid var(--fg); background: transparent; padding: 0 2px 0 10px; margin: 0 0 14px; box-sizing: border-box; flex: none; }
  [data-drawer] .drawer-search input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; height: 100%; font-family: 'Fragment Mono', monospace; font-size: 12px; letter-spacing: 0.01em; color: var(--fg); }
  [data-drawer] .drawer-search button { appearance: none; background: none; border: none; color: var(--accent); cursor: pointer; padding: 4px; margin: 0; display: inline-flex; align-items: center; flex: none; }

  /* utility column: centered stack, positioned on the close button's axis by JS */
  [data-drawer] .drawer-wrap { display: flex; flex-direction: column; align-items: center; width: fit-content; min-width: 140px; }
  [data-drawer] .drawer-links { display: flex; flex-direction: column; align-items: center; }
  /* The link slides right on hover and an accent square appears in the space it
     leaves. The <a> itself used to be what moved — which meant the hover target
     slid out from under a stationary cursor, unhovered, slid back under it,
     rehovered, and did that for as long as the pointer rested in the 17px band
     it was vacating. Held perfectly still, the item oscillated across 13px and
     never settled.

     So the box no longer moves: the padding reserves the travel on both sides,
     which keeps the label centred in the column exactly as before, and only the
     inner <span> slides. The hit area is constant, so hover is a single state
     change however long you rest there. */
  [data-drawer] .drawer-links a, [data-drawer] .drawer-disabled { font-family: 'Cormorant Garamond', Georgia, serif; font-weight: 600; font-size: 1.5rem; line-height: 1.28; padding: 5px 17px; }
  [data-drawer] .drawer-links a { color: var(--fg); text-decoration: none; position: relative; width: fit-content; }
  [data-drawer] .drawer-links a > span { display: inline-block; transition: transform 0.18s ease; }
  [data-drawer] .drawer-links a::before { content: ""; position: absolute; left: 17px; top: 50%; width: 7px; height: 7px; background: var(--accent); opacity: 0; transform: translate(-6px, -50%); transition: opacity 0.18s ease, transform 0.18s ease; }
  @media (hover: hover) {
    [data-drawer] .drawer-links a:hover > span { transform: translateX(17px); }
    [data-drawer] .drawer-links a:hover::before { transform: translate(0, -50%); opacity: 1; }
  }
  [data-drawer] .drawer-links a:active > span { transform: translateX(17px); }
  [data-drawer] .drawer-links a:active::before { transform: translate(0, -50%); opacity: 1; }
  [data-drawer] .drawer-disabled { color: var(--faded); opacity: 0.55; cursor: default; }

  [data-drawer] .drawer-icons { display: flex; align-items: center; justify-content: space-between; align-self: stretch; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--tileborder); }
  [data-drawer] .drawer-icons a { display: inline-flex; align-items: center; color: var(--fg); text-decoration: none; transition: color 0.18s ease; }
  @media (hover: hover) { [data-drawer] .drawer-icons a:hover { color: var(--accent); } }
  [data-drawer] .drawer-icons a:active { color: var(--accent); }

  [data-drawer] .drawer-bottom { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--tileborder); display: flex; align-items: center; }
  [data-drawer] .drawer-bottom button { appearance: none; background: none; border: none; padding: 0; display: inline-flex; align-items: center; gap: 10px; cursor: pointer; color: var(--fg); transition: color 0.2s; font: inherit; }
  @media (hover: hover) { [data-drawer] .drawer-bottom button:hover { color: var(--accent); } }
  [data-drawer] .drawer-bottom button:active { color: var(--accent); }
  [data-drawer] .drawer-theme-icon { display: inline-flex; width: 18px; height: 18px; align-items: center; justify-content: center; }
  [data-drawer] [data-theme-label] { font-family: 'Fragment Mono', monospace; font-size: 12px; letter-spacing: 0.04em; }
}

/* Visually hidden, still announced.
   For headings that the page's structure needs but its design does not show —
   the homepage h1, whose visible counterpart is the masthead wordmark (an <a>,
   which cannot carry the heading without nesting one inside a link).
   Not `display:none` and not `visibility:hidden`: both remove the element from
   the accessibility tree, which is the opposite of the point. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ==========================================================================
   Skip link — see skipLink() in tools/build/chrome.mjs for why it exists.

   Parked off the top of the viewport rather than display:none, because
   display:none removes it from the tab order and a skip link that cannot be
   tabbed to is not a skip link. It comes back on :focus only.

   z-index sits above the sticky masthead (100) and below the menu overlay
   (2000): it must not be painted under the header it is helping you leave.
   ========================================================================== */
.skip-link {
  position: absolute;
  left: 12px;
  top: -60px;
  z-index: 1500;
  padding: 10px 16px;
  background: var(--bg, #fff);
  color: var(--fg, #060606);
  border: 1px solid var(--fg, #060606);
  font-family: 'Fragment Mono', ui-monospace, monospace;
  font-size: 13px;
  letter-spacing: 0.02em;
  text-decoration: none;
  transition: top 0.16s ease;
}
.skip-link:focus { top: 12px; }
/* The target takes tabindex="-1" so focus can land on it; that makes it
   focusable, and a focus ring around the whole article is noise. The skip
   already moved the reader where they asked to go. */
#main-content:focus { outline: none; }
#main-content:focus-visible { outline: none; }

/* ==========================================================================
   Focus floor.

   Most interactive things here already draw their own focus state, and several
   are better than a generic ring — the footnote reference opens its panel, the
   TOC strip expands, the share buttons raise their tooltip. What was missing
   was a FLOOR: anything that defines nothing was showing nothing, and which
   controls those are is not knowable by reading the CSS, only by tabbing
   through every page.

   :where() has zero specificity, so this loses to every existing rule,
   including the ones that deliberately say outline:none. It only ever applies
   where nothing else does. That is the point — it cannot regress a considered
   focus style, and it cannot be forgotten by the next control someone adds.

   :focus-visible, not :focus, so a mouse click does not leave a ring behind.
   ========================================================================== */
:where(a[href], button, input, select, textarea, summary, [tabindex]:not([tabindex="-1"])):focus-visible {
  outline: 2px solid var(--accent, #D12B1D);
  outline-offset: 2px;
}

/* ==========================================================================
   Touch targets.

   The category eyebrow ("Finance", "Infrastructure") is 11-12px type, which
   makes the link box about 14px tall. WCAG 2.5.8 asks for 24x24 CSS px, and on
   a phone this is a real miss rather than a technicality: it is the one control
   in a card that is not the headline, and it sits directly above one, so a
   near-miss lands on the article instead of the topic.

   Padding grows the hit area; the negative margin gives the space back to the
   layout, so nothing moves. Applied to the link only — the row keeps its
   spacing, and the text keeps its position to the pixel.
   ========================================================================== */
[data-site] .catlink,
[data-site] .row-eyebrow > a {
  display: inline-block;
  padding-block: 5px;
  margin-block: -5px;
}

/* ==========================================================================
   Search fields.

   All three (header, menu, /search/) are composed controls: a bordered wrapper
   around an icon, a borderless input and a button. The input carries an inline
   `outline:none` so no ring draws inside that frame — a fair visual call, but
   inline styles beat the focus floor above, so tabbing into search showed
   nothing at all.

   The wrapper is what reads as the control, so the wrapper is what lights up.
   Two channels, not one: the border goes accent AND a ring is drawn outside it,
   because border colour alone is a colour-only cue (WCAG 1.4.1) and the field's
   resting border is already a strong line.
   ========================================================================== */
.searchfield:focus-within {
  border-color: var(--accent) !important;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ==========================================================================
   Remaining sub-24px hit targets, by rule rather than by instance.

   Same padding/negative-margin trade as the category eyebrow: the touchable box
   grows, the layout does not move. Listed individually because each one had a
   different reason for being small, and a blanket min-height on every link
   would wreck the prose.
   ========================================================================== */

/* Footer credit, on all ten routes — the smallest persistent link on the site.
   min-height rather than padding: both of these are already flex containers
   with their own padding, so a padding-block declaration REPLACED what they
   had and made the box smaller. min-height cannot do that. */
[data-site] .mcf-mini { min-height: 24px; align-items: center; }

/* Article byline: the author link and the share button sit on one baseline. */
[data-site] .author-link { display: inline-block; padding-block: 4px; margin-block: -4px; }
[data-site] .byline-share { min-height: 24px; align-items: center; }

/* The article kicker is already a bordered chip; it just sits 3px short. */
[data-site] .kicker { min-height: 24px; box-sizing: border-box; }

/* The heading anchor was 9x9 — a quarter of the minimum, and the hardest thing
   on the site to hit. It is absolutely positioned beside its heading, so
   padding grows the box without moving the icon or reflowing the heading. */
[data-site] .heading-anchor {
  padding: 8px;
  margin: -8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* The "(opens in a new tab)" note on links whose accessible name comes from
   their own text. Clipped rather than display:none so screen readers still
   reach it — and, as a side effect, reader modes that strip the clip show it in
   plain sight, which is a fair outcome for a warning. */
.vh-newtab {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
