@import url('https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;1,400&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@700&display=swap');

:root {
  --bg: #faf9f7;
  --surface: #ffffff;
  --text: #2c2c2c;
  --text-muted: #6b6b6b;
  --accent: #e85d26;
  --accent-hover: #d04f1c;
  --accent-soft: rgba(232, 93, 38, 0.12);
  --border: #e5e2dd;
  --code-bg: #f0eeeb;
  --shadow: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
  --shadow-lg: 0 6px 18px rgba(0,0,0,0.08);
  --measure: 700px;
  /* The nav is the one row that is not prose. Signed in on a Space page it
     carries eight entries beside the brand and the theme toggle, which is
     about 780px of content: inside `--measure` they had nowhere to go but on
     top of each other, whatever the window was. It is wider than the column
     it sits over, and deliberately. */
  --nav-measure: 980px;
  /* The two halves of the mark and the wordmark: the signal is orange in
     both themes, the other person is the page's own text colour, so it is
     cream on dark and ink on light rather than cream on cream. */
  --brand-signal: #e8834f;
  --brand-other: var(--text);
}

[data-theme="dark"] {
  --bg: #171717;
  --surface: #222222;
  --text: #e8e6e3;
  --text-muted: #9c9c9c;
  --accent: #f0824d;
  --accent-hover: #f59464;
  --accent-soft: rgba(240, 130, 77, 0.16);
  --border: #353535;
  --code-bg: #2c2c2c;
  --shadow: 0 1px 3px rgba(0,0,0,0.3);
  --shadow-lg: 0 6px 18px rgba(0,0,0,0.4);
  --brand-other: #f4efe8;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.7;
  font-size: 17px;
  transition: background 0.3s, color 0.3s;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--accent);
  text-decoration: none;
  transition: color 0.2s;
}

a:hover {
  color: var(--accent-hover);
}

::selection {
  background: var(--accent-soft);
}

/* ---- navigation ---- */

nav {
  max-width: var(--nav-measure);
  margin: 0 auto;
  padding: 1.25rem 1.25rem 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* The same gap the entries use, so the theme toggle -- a child of nav now
     that ADR-0017 keeps it on the bar -- sits exactly where it always did,
     one entry's width from the last link. */
  gap: 1.1rem;
}

/* `flex: none`, where the row it sits in must never have it (ADR-0017): the
   wordmark is one nowrap word, so shrinking it does not reflow anything --
   it just draws "musubihub" underneath the first nav entry. The row shrinks;
   the brand does not. */
nav .brand {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--text);
  flex: none;
}

nav .brand:hover .logo-musubi {
  color: var(--brand-signal);
}

.logo-icon {
  height: 2.1rem;
  width: 2.1rem;
  display: block;
  flex: none;
}

/* The mark's four strokes and two heads, coloured from the theme. */
.logo-mark .logo-a { fill: var(--brand-signal); }
.logo-mark .logo-b { fill: var(--brand-other); }
.logo-mark .logo-a-wave,
.logo-mark .logo-b-wave { fill: none; stroke-width: 5; stroke-linecap: round; }
.logo-mark .logo-a-wave { stroke: var(--brand-signal); }
.logo-mark .logo-b-wave { stroke: var(--brand-other); }

nav .logo-text {
  display: inline-flex;
  gap: 2px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: -0.06em;
  line-height: 1;
  white-space: nowrap;
}
nav .logo-musubi { color: var(--brand-other); transition: color 0.2s; }
nav .logo-hub { color: var(--brand-signal); }

nav .nav-right {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  /* ADR-0017: never `flex: none`. A row that cannot shrink draws its items
     on top of each other instead of fitting the screen, and the wrap added
     for narrow screens never has a width to wrap at. */
  min-width: 0;
  margin-left: auto;
}

nav .nav-link {
  font-size: 0.9rem;
  color: var(--text-muted);
  font-weight: 500;
  padding: 0.25rem 0;
  border-bottom: 1.5px solid transparent;
}

nav .nav-link:hover,
nav .nav-link.active {
  color: var(--text);
  border-bottom-color: var(--accent);
}

/* Every entry is one or two words and is read as a label: a "Log out" broken
   over two lines is what lands on top of the theme toggle. */
nav .nav-link,
.nav-handle {
  white-space: nowrap;
}

/* The two Handles are the only entries whose width is somebody else's
   decision -- `owners.HANDLE_PATTERN` allows thirty characters, and a row
   sized for the longest of them would be a row sized for nothing. They are
   therefore the part of the bar that gives: capped, and cut with an ellipsis
   rather than pushing the links they sit between off the row. */
nav .nav-handle,
nav .nav-space-handle {
  max-width: 8ch;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The Space segment (#45): the Handle of the Space a page is about and its
   Ask, set off from the global entries by a rule rather than by a separator
   character, so it reads as one group at every width.

   It lives here, with the rest of the nav, because a media query adds no
   specificity: this rule and the narrow-screen one that overrides it both
   score (0,1,1), so source order alone decides and the base rule has to come
   first. Written below the responsive block it would silently win below
   640px and the panel would keep the row's indent and vertical rule. */
nav .nav-space {
  display: inline-flex;
  align-items: center;
  gap: 1.1rem;
  padding-left: 1.1rem;
  border-left: 1px solid var(--border);
}

/* The two controls that never leave the bar (ADR-0017): the theme toggle at
   every width, and the menu button below 640px. */
nav .nav-controls {
  display: inline-flex;
  align-items: center;
  gap: 1.1rem;
  flex: none;
}

/* Hidden until the nav collapses: above 640px every entry is on the bar and
   there is nothing for it to open. */
nav .nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--border);
  border-radius: 8px;
  width: 2.1rem;
  height: 2.1rem;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  flex: none;
}

nav .nav-toggle:hover {
  color: var(--text);
  border-color: var(--accent);
}

.theme-toggle {
  background: none;
  border: 1px solid var(--border);
  border-radius: 8px;
  width: 2.1rem;
  height: 2.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  color: var(--text);
  transition: all 0.2s;
}

.theme-toggle:hover {
  border-color: var(--accent);
  background: var(--code-bg);
}

/* ---- layout ---- */

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 2.5rem 1.25rem 5rem;
}

.hero {
  margin-bottom: 2.5rem;
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--border);
}

.hero h1 {
  font-family: 'EB Garamond', Georgia, serif;
  font-size: 2.9rem;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin-bottom: 0.75rem;
}

.hero p {
  color: var(--text-muted);
  font-size: 1.05rem;
  max-width: 540px;
}

/* The Space hero (#41): the Handle under the Display Name, the Bio under
   both. Muted like every other line of the hero, the Handle a step smaller
   because the name above it is the title now. */
.hero .space-handle {
  font-size: 0.95rem;
  margin-top: -0.5rem;
  margin-bottom: 0.75rem;
}

.hero .space-bio {
  color: var(--text);
  margin-bottom: 0.75rem;
}

.hero-home {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}

.hero-home .hero-text {
  flex: 1 1 auto;
  min-width: 0;
}

.hero-art {
  flex: 0 0 auto;
  width: clamp(160px, 30%, 220px);
  height: auto;
  display: block;
}

.section-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
  margin-bottom: 1rem;
  font-weight: 600;
}

/* ---- post cards ---- */

.post-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.5rem 1.6rem;
  margin-bottom: 1rem;
  transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
  box-shadow: var(--shadow);
  display: block;
  color: var(--text);
}

.post-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
  border-color: var(--accent);
  color: var(--text);
}

.post-card .post-date {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-bottom: 0.45rem;
  font-weight: 500;
  letter-spacing: 0.02em;
}

.post-card .post-title {
  font-family: 'EB Garamond', Georgia, serif;
  font-size: 1.45rem;
  font-weight: 600;
  margin-bottom: 0.45rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
}

.post-card .post-excerpt {
  color: var(--text-muted);
  font-size: 0.93rem;
  line-height: 1.6;
}

.post-card .post-tag {
  display: inline-block;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: var(--code-bg);
  color: var(--text-muted);
  padding: 0.2rem 0.55rem;
  border-radius: 4px;
  margin: 0.8rem 0.3rem 0 0;
  font-weight: 600;
}

/* ---- the home page: the pitch and the Owner Directory (#45) ---- */

/* Three lines, one idea each, read as a list without looking like one. */
.pitch p {
  color: var(--text-muted);
  font-size: 1.05rem;
  max-width: 540px;
  margin-bottom: 0.5rem;
}

.cta-row {
  margin-top: 1.4rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.cta {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  font-size: 0.95rem;
  padding: 0.6rem 1.4rem;
  border-radius: 8px;
  transition: background 0.2s;
}

.cta:hover {
  background: var(--accent-hover);
  color: #fff;
}

/* The second call to action of the signed-in home page (#64). Upload a Raw
   Text is what the Owner came to do; Your Space is where it ends up, so it
   is a button of the same size wearing the page's own colours. */
.cta-secondary {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}

.cta-secondary:hover {
  background: var(--surface);
  color: var(--text);
  border-color: var(--accent);
}

.directory-search {
  margin-bottom: 1.25rem;
}

.directory-search input {
  width: 100%;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.95rem;
}

.directory-search input:focus {
  outline: 2px solid var(--accent-soft);
  border-color: var(--accent);
}

/* One Owner: the Display Name over the Handle, the Bio, then the Article
   count and the LinkedIn. The card wears `.post-card`, but it is an
   `<article>` rather than an `<a>`: the LinkedIn inside it is a link of its
   own, and an anchor cannot be nested in an anchor. */
.owner-card:hover {
  transform: none;
  box-shadow: var(--shadow);
  border-color: var(--border);
}

.owner-name {
  font-family: 'EB Garamond', Georgia, serif;
  font-size: 1.45rem;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--text);
  display: inline-block;
}

.owner-name:hover {
  color: var(--accent);
}

.owner-handle {
  font-size: 0.85rem;
  color: var(--text-muted);
  margin-top: 0.15rem;
}

.owner-bio {
  color: var(--text-muted);
  font-size: 0.93rem;
  line-height: 1.6;
  margin-top: 0.55rem;
}

.owner-meta {
  display: flex;
  align-items: center;
  /* The profile chip reads `in/{handle}` (#62), which is as long as the
     Handle an Owner chose, so the row wraps rather than pushing the chip
     out of the card on a narrow viewport. */
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 0.9rem;
  font-size: 0.8rem;
  color: var(--text-muted);
  font-weight: 500;
}

.owner-linkedin {
  color: var(--accent);
  /* A flex item refuses to shrink below its content by default; a long
     Handle, or the host-and-path fallback, breaks inside the card instead. */
  min-width: 0;
  overflow-wrap: anywhere;
}

/* The Space's tag list: the same chips the cards wear, made clickable.
   Each one is a link back to space.html with `?tag=` (ADR-0009). */
.space-tags {
  margin: 0 0 2rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.space-tags .tag-filter {
  display: inline-block;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: var(--code-bg);
  color: var(--text-muted);
  padding: 0.3rem 0.65rem;
  border-radius: 4px;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid transparent;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.space-tags .tag-filter:hover {
  color: var(--text);
  border-color: var(--border);
}

.space-tags .tag-filter-on {
  color: var(--text);
  border-color: var(--text-muted);
}

/* The Articles Reorganization linked this one to (ADR-0010), under it. */
.article-related {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
}

.article-related h2 {
  font-family: 'EB Garamond', Georgia, serif;
  font-size: 1.4rem;
  font-weight: 600;
  margin-bottom: 1rem;
}

/* ---- article ---- */

article {
  animation: fadeIn 0.4s ease;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

article .post-header {
  margin-bottom: 2.5rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--border);
}

article .post-header h1 {
  font-family: 'EB Garamond', Georgia, serif;
  font-size: 2.5rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin-bottom: 0.75rem;
  text-wrap: balance;
}

/* ---- Space and Article pages (ADR-0009) ---- */

article .article-subtitle {
  font-family: 'EB Garamond', Georgia, serif;
  font-size: 1.3rem;
  line-height: 1.35;
  color: var(--text-muted);
  margin-bottom: 0.75rem;
}

/* Where an Import built an Article from (#92): one quiet line under the
   tags, not a badge -- it is provenance, not a status. */
.article-source {
  margin-top: 1rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}

/* The tags under a rendered Article: the same chips the cards use. */
article #article-tags {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
}

article #article-tags .post-tag {
  display: inline-block;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  background: var(--code-bg);
  color: var(--text-muted);
  padding: 0.2rem 0.55rem;
  border-radius: 4px;
  margin: 0 0.3rem 0 0;
  font-weight: 600;
}

article .post-meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--text-muted);
  font-size: 0.85rem;
}

article .post-meta .dot {
  opacity: 0.4;
}

article h2 {
  font-family: 'EB Garamond', Georgia, serif;
  font-size: 1.85rem;
  font-weight: 600;
  margin-top: 3rem;
  margin-bottom: 0.9rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

article h3 {
  font-weight: 600;
  font-size: 1.12rem;
  margin-top: 2.25rem;
  margin-bottom: 0.6rem;
  line-height: 1.3;
}

article p {
  margin-bottom: 1.3rem;
}

article p a,
article li a {
  text-decoration: underline;
  text-decoration-color: var(--accent-soft);
  text-underline-offset: 3px;
}

article p a:hover,
article li a:hover {
  text-decoration-color: var(--accent);
}

article strong {
  font-weight: 600;
}

article code {
  background: var(--code-bg);
  padding: 0.12rem 0.38rem;
  border-radius: 4px;
  font-size: 0.86em;
  font-family: 'SF Mono', 'Fira Code', ui-monospace, Menlo, monospace;
  overflow-wrap: anywhere;
}

article pre {
  background: var(--code-bg);
  padding: 1.1rem 1.25rem;
  border-radius: 10px;
  overflow-x: auto;
  margin-bottom: 1.3rem;
  font-size: 0.84em;
  line-height: 1.6;
  border: 1px solid var(--border);
}

article pre code {
  background: none;
  padding: 0;
  overflow-wrap: normal;
}

article ul, article ol {
  margin-bottom: 1.3rem;
  padding-left: 1.4rem;
}

article li {
  margin-bottom: 0.5rem;
}

article li::marker {
  color: var(--text-muted);
}

article blockquote {
  border-left: 3px solid var(--accent);
  padding: 0.25rem 0 0.25rem 1.1rem;
  margin: 1.5rem 0;
  color: var(--text-muted);
  font-style: italic;
}

article hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 2.75rem 0;
}

/* tables: site.js wraps each one in .table-wrap so wide ones scroll */
.table-wrap {
  overflow-x: auto;
  margin-bottom: 1.3rem;
  -webkit-overflow-scrolling: touch;
}

article table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9em;
  min-width: 480px;
}

article table th {
  text-align: left;
  font-weight: 600;
  padding: 0.6rem 0.75rem;
  border-bottom: 2px solid var(--border);
  font-size: 0.78em;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

article table td {
  padding: 0.55rem 0.75rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

article table td code {
  white-space: nowrap;
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.88rem;
  color: var(--text-muted);
  margin-bottom: 2rem;
  font-weight: 500;
}

.back-link:hover {
  color: var(--accent);
}

/* ---- figures & inline SVG diagrams ---- */

article figure {
  margin: 1.75rem 0;
}

article figure .diagram-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  padding: 0.75rem;
}

article figure img,
article figure video {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: 12px;
}

article figure .diagram {
  width: 100%;
  min-width: 560px;
  height: auto;
  display: block;
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
}

article figcaption {
  font-size: 0.82rem;
  color: var(--text-muted);
  margin-top: 0.7rem;
  text-align: center;
  line-height: 1.5;
  padding: 0 0.5rem;
}

/* ---- mermaid diagrams (ADR-0006) ---- */
/* The container js/markdown.js builds for a ```mermaid fence, filled by
   js/diagrams.js. Every colour in the diagram itself comes from the CSS
   variables above, handed to Mermaid as theme variables, so the toggle
   re-themes the SVG and this rule needs no colour of its own. */

article figure[data-mermaid] .mermaid-target svg {
  display: block;
  margin: 0 auto;
  max-width: 100%;
  height: auto;
}

/* The code a Visitor reads until a render succeeds -- and for good, when
   Mermaid refuses the block or the CDN is unreachable. */
article figure[data-mermaid] .diagram-source {
  margin: 0;
  background: transparent;
  border: 0;
}

article figure[data-mermaid] [hidden] {
  display: none;
}

.d-box { fill: var(--surface); stroke: var(--border); stroke-width: 1.2; }
.d-box-soft { fill: var(--code-bg); stroke: var(--border); stroke-width: 1.2; }
.d-box-accent { fill: var(--accent); stroke: none; }
.d-box-outline { fill: none; stroke: var(--accent); stroke-width: 1.4; }
.d-text { fill: var(--text); font-size: 12px; }
.d-text-b { fill: var(--text); font-size: 12px; font-weight: 600; }
.d-text-sm { fill: var(--text-muted); font-size: 10.5px; }
.d-text-inv { fill: #ffffff; font-size: 12px; font-weight: 600; }
.d-text-accent { fill: var(--accent); font-size: 11px; font-weight: 600; }
.d-mono { font-family: 'SF Mono', 'Fira Code', ui-monospace, Menlo, monospace; font-size: 10.5px; fill: var(--text); }
.d-line { stroke: var(--text-muted); stroke-width: 1.3; fill: none; }
.d-line-accent { stroke: var(--accent); stroke-width: 1.6; fill: none; }
.d-dash { stroke-dasharray: 4 3; }
.d-arrowhead { fill: var(--text-muted); }
.d-arrowhead-accent { fill: var(--accent); }
.d-good { fill: #2e9e5b; }
.d-bad { fill: #d03b3b; }
.d-warn { fill: #e0a100; }
.d-aws { fill: var(--surface); stroke: #e0a100; stroke-width: 1.4; }
.d-lane { fill: var(--code-bg); stroke: none; opacity: 0.55; }

article .callout {
  border-left: 3px solid var(--accent);
  background: var(--surface);
  border-radius: 0 10px 10px 0;
  padding: 1rem 1.25rem;
  margin: 1.5rem 0;
  box-shadow: var(--shadow);
}

article .callout p:last-child {
  margin-bottom: 0;
}

article .callout .callout-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent);
  font-weight: 600;
  margin-bottom: 0.35rem;
}

/* ---- footer ---- */

footer {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 1.75rem 1.25rem 2.5rem;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.82rem;
}

footer .footer-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

footer .footer-links {
  display: flex;
  gap: 1.25rem;
}

/* ---- responsive ---- */

/* ADR-0017: the bar keeps the brand, the theme toggle and the menu button,
   and every entry moves into a panel the button opens. A wrapped nine-item
   row was the alternative, and the nav has grown twice already (#45, #46)
   with another entry coming, so it would not have lasted.

   940px and not 640px, which is where this started. The breakpoint is not
   about the window: the bar is `--nav-measure` wide at most, and a signed-in
   Admin on a Space page needs about 780px of it -- 860px once both Handles
   are as long as `owners.HANDLE_PATTERN` lets them be. The collapse has to
   happen wherever the bar itself is narrower than that, and 940px of window
   minus its padding is the first width where the longest nav fits with room
   to spare. Below it the panel does the same job it does on a phone. */
@media (max-width: 940px) {
  nav { position: relative; }
  nav .nav-toggle { display: inline-flex; }
  nav .nav-right {
    display: none;
    position: absolute;
    top: 100%;
    left: 1.25rem;
    right: 1.25rem;
    z-index: 30;
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
    margin-top: 0.6rem;
    padding: 0.85rem 1rem;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
  }
  nav.nav-open .nav-right { display: flex; }
  nav .nav-link { font-size: 0.95rem; text-align: left; }
  /* Stacked, the Handles have a row of their own and nothing to crowd: the
     cap that keeps them out of the links' way on the bar would only cut a
     name nobody is short of room for here. */
  nav .nav-handle,
  nav .nav-space-handle {
    max-width: none;
  }
  /* The segment's rule runs down the left of a row (#45); stacked, it is
     the line above the group instead. */
  nav .nav-space {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
    padding-left: 0;
    padding-top: 0.75rem;
    border-left: 0;
    border-top: 1px solid var(--border);
  }
}

@media (max-width: 640px) {
  body { font-size: 16px; }
  nav { padding: 1rem 1rem 0; }
  main { padding: 1.75rem 1rem 3.5rem; }
  .logo-icon { height: 1.8rem; width: 1.8rem; }
  nav .logo-text { font-size: 1.15rem; }
  /* The panel is inset by the bar's own padding, which is narrower here than
     it is on the tablet widths the collapse now covers. */
  nav .nav-right { left: 1rem; right: 1rem; }
  .hero h1 { font-size: 2.1rem; }
  .hero { margin-bottom: 2rem; padding-bottom: 1.5rem; }
  .hero-home { flex-direction: column-reverse; align-items: flex-start; gap: 1rem; }
  .hero-art { width: min(45%, 160px); align-self: center; }
  .post-card { padding: 1.2rem 1.25rem; border-radius: 12px; }
  .post-card .post-title { font-size: 1.25rem; }
  article .post-header h1 { font-size: 1.85rem; }
  article h2 { font-size: 1.55rem; margin-top: 2.5rem; }
  article h3 { font-size: 1.05rem; }
  article pre { padding: 0.9rem 1rem; border-radius: 8px; }
  article figure .diagram-scroll { padding: 0.5rem; border-radius: 10px; }
  article hr { margin: 2.25rem 0; }
}

/* The wordmark is the name, so it stays at every width: in a monospace face
   it is a fixed ~8em, which still fits beside the two controls on a 320px
   phone once it is a size smaller. */
@media (max-width: 380px) {
  nav .logo-text { font-size: 1rem; }
}

/* ---- Chat page ---- */
.chat {
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.chat-log {
  max-height: 60vh;
  min-height: 240px;
  overflow-y: auto;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.chat-msg { display: flex; flex-direction: column; max-width: 85%; }
.chat-user { align-self: flex-end; align-items: flex-end; }
.chat-assistant { align-self: flex-start; }
.chat-bubble {
  padding: 0.6rem 0.85rem;
  border-radius: 10px;
  background: var(--accent-soft);
  line-height: 1.5;
}
.chat-user .chat-bubble { background: var(--accent); color: #fff; }
.chat-bubble p { margin: 0 0 0.5rem; }
.chat-bubble p:last-child { margin-bottom: 0; }
.chat-bubble ul { margin: 0.25rem 0 0.5rem 1.1rem; padding: 0; }
.chat-bubble code {
  font-size: 0.9em;
  padding: 0.05em 0.3em;
  background: rgba(0, 0, 0, 0.06);
  border-radius: 4px;
}
.chat-sources {
  margin-top: 0.4rem;
  font-size: 0.85rem;
  color: var(--text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 0.6rem;
}
.chat-sources a { color: var(--accent); }
.chat-form {
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem;
  border-top: 1px solid var(--border);
}
.chat-form input {
  flex: 1;
  min-width: 0;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
}
.chat-form button {
  padding: 0.6rem 1.1rem;
  border: 0;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  cursor: pointer;
}
.chat-form button:hover { background: var(--accent-hover); }
.chat-form button:disabled, .chat-form input:disabled { opacity: 0.6; cursor: default; }
.chat-note {
  margin: 0;
  padding: 0 0.75rem 0.75rem;
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* Signup, verify, login and reset (ADR-0002): one card, one column. */
.auth {
  max-width: 460px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 1.5rem;
}
.auth-form { display: flex; flex-direction: column; gap: 1.1rem; }
.field { display: flex; flex-direction: column; gap: 0.35rem; }
.field label { font-weight: 600; font-size: 0.9rem; }
.field input {
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
}
.field input:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.field input:disabled { opacity: 0.6; cursor: default; }
.field-hint, .field-note {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-muted);
}
.field-note:empty { display: none; }
.field-note.is-error { color: #c0392b; }
.field-note.is-ok { color: #1e8449; }
[data-theme="dark"] .field-note.is-error { color: #f07167; }
[data-theme="dark"] .field-note.is-ok { color: #6fcf97; }
.auth-form button[type="submit"] {
  padding: 0.7rem 1.1rem;
  border: 0;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.auth-form button[type="submit"]:hover { background: var(--accent-hover); }
.auth-form button[type="submit"]:disabled { opacity: 0.6; cursor: default; }
.auth-notice {
  margin-bottom: 1rem;
  padding: 0.7rem 0.9rem;
  border-radius: 8px;
  background: var(--accent-soft);
  font-size: 0.85rem;
}
.auth-alt {
  margin-top: 1.1rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.link-button {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--accent);
  cursor: pointer;
}
.link-button:hover { color: var(--accent-hover); }

/* Signed-in Owner in the nav. */
.nav-handle {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-muted);
}
/* A button, but it has to sit in the row as if it were one more nav link,
   so only the chrome is reset and the .nav-link border-bottom is kept. */
button.nav-logout {
  border-top: 0;
  border-right: 0;
  border-left: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}

/* ---- Upload page (#17, ADR-0004) ---- */
/* The card is the auth card, only wider: a Raw Text is a wall of text and a
   460px column makes pasting one feel like filling in a form field. */
.auth.upload { max-width: var(--measure); }

/* The Import page (#90, #91) is the same card at the same width: from #94 it
   carries the other path beside its own form, and a 460px column would put
   the two of them in about 180px each. */
.auth.import { max-width: var(--measure); }

/* ---- The two paths into a Space (#94) ---- */
/* The Raw Text and the Import, side by side on both pages that offer them,
   so that neither reads as the afterthought of the other: the Import used to
   be linked from nowhere at all, and a line under a sixteen-row textarea
   would have been the same thing with extra steps. */
.upload-paths {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 15rem);
  gap: 1.5rem;
  align-items: start;
}

/* The form comes first in the markup on both pages and is placed first
   here, so the focus order is the order the columns are read in (WCAG
   2.4.3): reordering them with `grid-column` would put the other path's
   link before the field the page exists for. The stacked case is handled
   in the media query below instead.

   With the form hidden -- the Import page on a deployment with no
   `GITHUB_TOKEN` -- the panel left behind would sit in the 15rem column
   with an empty one beside it, so `js/import.js` adds the modifier that
   collapses the grid to the one column it still has something to put in. */
.upload-paths.upload-paths-alone { grid-template-columns: minmax(0, 1fr); }

.upload-path-import {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
}

.upload-path-import h2 {
  margin: 0;
  font-size: 1rem;
}

.upload-path-import p { margin: 0; }

/* Below the width at which `main` stops being `--measure` wide, a second
   column leaves the textarea narrower than the prose being pasted into it.
   They stack instead, the short panel on top. */
@media (max-width: 760px) {
  .upload-paths { grid-template-columns: minmax(0, 1fr); }
  /* The four-line panel on top, where the form is sixteen rows of textarea
     below it. Ordering it here and not in the markup costs the focus order
     nothing: stacked, the visual order is the ordered order. */
  .upload-paths > .upload-path-import { order: -1; }
}
.field textarea {
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
  line-height: 1.6;
  resize: vertical;
  min-height: 16rem;
}
.field textarea:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.field textarea:disabled { opacity: 0.6; cursor: default; }

/* The Article Status trail an Owner watches while the Job runs. */
.status-trail {
  list-style: none;
  margin: 0.9rem 0 0.6rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.status-step {
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.78rem;
  color: var(--text-muted);
}
.status-step.is-done { border-color: var(--accent-soft); color: var(--text); }
.status-step.is-current {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--text);
  font-weight: 600;
}

/* ---- Editor page (#20, ADR-0007) ---- */
/* The same wide card as the upload page, with the preview under it: an
   Article is read at the measure, and so is the thing you are editing. */
.auth.editor { margin-bottom: 1.5rem; }
.editor-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.editor-actions button[type="submit"] {
  padding: 0.7rem 1.1rem;
  border: 0;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.editor-actions button[type="submit"]:hover { background: var(--accent-hover); }
.editor-actions button[type="submit"]:disabled { opacity: 0.6; cursor: default; }
.editor-actions .link-button { color: #c0392b; font-size: 0.85rem; }
[data-theme="dark"] .editor-actions .link-button { color: #f07167; }

/* One Rejection Reason per row: the category, the passage the Validation
   Agent quoted, and the line of advice that came with it. */
.rejection-reasons { list-style: none; margin: 0.8rem 0 0; padding: 0; }
.rejection-reason {
  margin-bottom: 0.9rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--border);
  border-left: 3px solid #c0392b;
  border-radius: 8px;
  background: var(--bg);
}
[data-theme="dark"] .rejection-reason { border-left-color: #f07167; }
.reason-category {
  display: block;
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.reason-quote {
  margin: 0.4rem 0;
  padding-left: 0.8rem;
  border-left: 2px solid var(--border);
  font-style: italic;
}
.reason-note { margin: 0; font-size: 0.9rem; color: var(--text-muted); }

/* The preview is the Article as a Visitor will read it, so it reuses the
   `article` styles rather than inventing a second set. */
.auth.editor-preview { max-width: var(--measure); }
.preview-heading {
  margin: 0 0 0.8rem;
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.preview-body .diagram-scroll { overflow-x: auto; }
.preview-body .mermaid svg { max-width: 100%; height: auto; }

/* ---- The Admin's preview of one Article (#44) ---- */
/* A banner above the Article: the Status it is in, the Rejection Reasons
   when it was rejected, and the one action the Admin has here. */
.article-status {
  max-width: var(--measure);
  margin-bottom: 1.6rem;
  padding: 0.8rem 1rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  background: var(--accent-soft);
}
.article-status.is-rejected { border-left-color: #c0392b; }
[data-theme="dark"] .article-status.is-rejected { border-left-color: #f07167; }
.article-status-line { margin: 0; font-size: 0.9rem; }
.article-status .owner-actions { margin-top: 0.5rem; }
.article-status .field-note { margin: 0.4rem 0 0; }
.article-status .field-note:empty { display: none; }
.owner-article-title { color: inherit; text-decoration: underline; text-decoration-color: var(--border); }
.owner-article-title:hover { color: var(--accent); }

/* ---- Moderation page (#23) ---- */
/* One card, one row per Owner. Wider than the reading measure on purpose:
   the Admin is scanning a list, not reading prose. */
.auth.admin { max-width: 52rem; }
.owner-list { list-style: none; margin: 0; padding: 0; }
.owner-row {
  padding: 0.9rem 1rem;
  margin-bottom: 0.8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
}
.owner-row.is-disabled { border-left: 3px solid #c0392b; }
[data-theme="dark"] .owner-row.is-disabled { border-left-color: #f07167; }
.owner-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.6rem;
}
.owner-handle { font-weight: 600; }
.owner-email { font-size: 0.85rem; color: var(--text-muted); }
.owner-badge {
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--accent-soft);
  border-radius: 999px;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
/* The Visibility badge of a Hidden Article (#88): the row is the Owner's own
   and stays legible, but the one Article nobody else can see says so. */
.owner-badge.is-hidden {
  border-style: dashed;
  border-color: var(--border);
}
.owner-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  margin-top: 0.35rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.owner-fact.is-error { color: #c0392b; }
[data-theme="dark"] .owner-fact.is-error { color: #f07167; }
.owner-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 0.6rem;
}
.owner-actions .link-button, .owner-article .link-button { font-size: 0.85rem; }
.link-button.is-danger { color: #c0392b; }
[data-theme="dark"] .link-button.is-danger { color: #f07167; }

/* The inline confirmation: the question and its two answers, in the row the
   action belongs to. #23 asks for this instead of a browser dialog. */
.confirm-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-top: 0.6rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--accent-soft);
  border-radius: 8px;
  background: var(--accent-soft);
}
.confirm-question { font-size: 0.85rem; }

.owner-articles { list-style: none; margin: 0.7rem 0 0; padding: 0; }
.owner-article {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 0.4rem 0;
  border-top: 1px solid var(--border);
  font-size: 0.9rem;
}
.owner-article-status {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}
.owner-note { margin: 0.5rem 0 0; }

/* ---- The Owner's Dashboard (#46) ---- */
/* One card per section, as wide as the Admin's page: these are lists to scan
   -- Articles, Views, questions -- and not prose to read. */
.auth.dashboard { max-width: 52rem; margin-bottom: 1.5rem; }

/* The strip that links the four pages of the Owner area and marks the one
   being read (#65, ADR-0016). It wraps rather than scrolls, so the narrowest
   phone shows two rows of entries instead of hiding the last one. */
.owner-subnav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  max-width: 52rem;
  margin: 0 auto 1.5rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--border);
}
.owner-subnav-link {
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  color: var(--text-muted);
  font-size: 0.9rem;
  text-decoration: none;
}
.owner-subnav-link:hover { color: var(--text); background: var(--code-bg); }
.owner-subnav-link.is-current {
  color: var(--accent);
  background: var(--accent-soft);
  font-weight: 600;
}

/* The bell that opens an Owner's Notifications (#93, ADR-0029). It is one of
   the controls that never leave the bar, the same square as the theme toggle
   beside it, and its panel drops under the bar from its right edge -- the
   same space the collapsed menu uses, which is why only one is open at once. */
.nav-bell-wrap { position: relative; display: inline-flex; }
.nav-bell {
  position: relative;
  width: 2.1rem;
  height: 2.1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: none;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.2s;
}
.nav-bell:hover,
.nav-bell[aria-expanded="true"] { color: var(--text); border-color: var(--accent); background: var(--code-bg); }
.nav-bell.has-unread { color: var(--accent); }
.nav-bell-count {
  position: absolute;
  top: -0.45rem;
  right: -0.45rem;
  min-width: 1.1rem;
  height: 1.1rem;
  padding: 0 0.3rem;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1.1rem;
  text-align: center;
}
.nav-bell-count[hidden] { display: none; }
.nav-bell-panel {
  position: absolute;
  top: calc(100% + 0.6rem);
  right: 0;
  z-index: 40;
  width: min(22rem, calc(100vw - 2.5rem));
  /* A disclosure, not a takeover: about ninety Notifications can be drawn
     (one Import a day, ninety-day ttl), and the list scrolls itself rather
     than running off the bottom of the window. */
  max-height: 70vh;
  overflow-y: auto;
  padding: 0.85rem 1rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
  text-align: left;
}
.nav-bell-panel[hidden] { display: none; }
/* Below ADR-0017's breakpoint the bell is not the last control on the bar,
   so a panel hung from its right edge would run off the left of a phone.
   It hangs from the nav instead, exactly where the collapsed menu does. */
@media (max-width: 940px) {
  .nav-bell-wrap { position: static; }
  .nav-bell-panel {
    top: 100%;
    left: 1.25rem;
    right: 1.25rem;
    width: auto;
    margin-top: 0.6rem;
  }
}
.nav-bell-heading { margin: 0 0 0.6rem; font-weight: 600; font-size: 0.95rem; }
.nav-bell-list { list-style: none; margin: 0; padding: 0; }
.nav-bell-row {
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.5rem;
  border: 1px solid var(--border);
  border-radius: 8px;
}
.nav-bell-row:last-child { margin-bottom: 0; }
.nav-bell-row.is-unread { border-left: 3px solid var(--accent); }
.nav-bell-message { margin: 0 0 0.35rem; font-size: 0.9rem; }
.nav-bell-link { color: var(--accent); font-size: 0.9rem; font-weight: 600; }
.nav-bell-row .field-hint { margin: 0.35rem 0 0; }

/* The line above the Articles when an Import left some of them Hidden: the
   Owner's next step, where the Articles are. */
.review-notice {
  margin: 0 0 1rem;
  padding: 0.8rem 1rem;
  border: 1px solid var(--accent);
  border-left-width: 3px;
  border-radius: 8px;
  background: var(--accent-soft);
  font-size: 0.95rem;
}
.dash-row.is-awaiting-review { border-left: 3px solid var(--accent); }

/* The email and the LinkedIn profile on Settings: two facts, no controls. */
.owner-identity {
  display: grid;
  grid-template-columns: minmax(8rem, auto) 1fr;
  gap: 0.4rem 1rem;
  margin: 0;
}
.owner-identity dt { color: var(--text-muted); font-size: 0.9rem; }
.owner-identity dd { margin: 0; font-size: 0.9rem; word-break: break-word; }
.owner-identity dd a { color: var(--accent); }
.dash-heading {
  margin: 0 0 0.6rem;
  font-size: 1.05rem;
  letter-spacing: -0.01em;
}
.dash-list { list-style: none; margin: 0; padding: 0; }
.dash-row {
  padding: 0.9rem 1rem;
  margin-bottom: 0.8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
}
.dash-row.is-rejected { border-left: 3px solid #c0392b; }
[data-theme="dark"] .dash-row.is-rejected { border-left-color: #f07167; }
.dash-row.is-compact {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 0.4rem;
  padding: 0.5rem 0.8rem;
}
.dash-row-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.6rem;
}
.dash-title { font-weight: 600; }
.dash-answer {
  margin: 0.5rem 0;
  font-size: 0.92rem;
  color: var(--text-muted);
  white-space: pre-wrap;
}
.owner-badge.is-error { border-color: #c0392b; color: #c0392b; }
[data-theme="dark"] .owner-badge.is-error { border-color: #f07167; color: #f07167; }
.dash-totals { margin-bottom: 0.8rem; }
.dash-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.6rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--accent-soft);
  border-radius: 8px;
  background: var(--accent-soft);
}
.dash-total-label { font-weight: 600; }
.dash-total-value { font-size: 0.9rem; color: var(--text-muted); }

/* The Views charts (#66, ADR-0018): inline SVG built by js/charts.js, with
   no library behind it. Every colour is a variable, so the bars and the axis
   live in either theme; the column chart has a viewBox and width:100%, so it
   scales down to a phone with no media query and no resize listener. */
.views-chart {
  margin: 0 0 0.9rem;
  padding: 0.6rem 0.4rem 0.2rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
}
.views-chart-svg { display: block; width: 100%; height: auto; overflow: visible; }
.views-chart-bar { fill: var(--accent); }
.views-chart-axis { stroke: var(--border); stroke-width: 1; }
.views-chart-scale,
.views-chart-tick,
.views-chart-axis-note {
  fill: var(--text-muted);
  font-size: 10px;
  font-family: inherit;
}
.views-chart-axis-note { font-style: italic; }
.views-chart-caption {
  margin: 0.3rem 0 0;
  font-size: 0.78rem;
  color: var(--text-muted);
}
/* The frame when the thirty days themselves are empty: one sentence where
   the bars would be, rather than thirty bars of no height. */
.views-chart-empty {
  margin: 0.2rem 0 0.4rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
/* One Article's own days, at table-row size. `stroke: var(--accent)` and no
   fill: a filled polyline would close the shape across the window. */
.views-spark { flex: 0 0 auto; overflow: visible; }
.views-spark-line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.field-hint.is-error { color: #c0392b; }
[data-theme="dark"] .field-hint.is-error { color: #f07167; }

/* Consent (#47, ADR-0014): the checkbox on the signup form and the banner
   the Dashboard shows an Owner whose Consent is missing or a version behind.
   Every colour is a variable, so both live in either theme. */
.field-check .check-label {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.85rem;
  color: var(--text-muted);
  cursor: pointer;
}
.field-check input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  margin-top: 0.15rem;
  flex: 0 0 auto;
  accent-color: var(--accent);
}
.field-check a { color: var(--accent); }

.consent-banner {
  margin-bottom: 1.5rem;
  padding: 1rem 1.1rem;
  border: 1px solid var(--accent);
  border-radius: 10px;
  background: var(--accent-soft);
}
.consent-banner p { font-size: 0.9rem; }
.consent-banner .consent-links {
  margin-top: 0.5rem;
  font-size: 0.85rem;
}
.consent-banner .consent-links a { color: var(--accent); }
.consent-banner button {
  margin-top: 0.8rem;
  padding: 0.5rem 1.1rem;
  border: 0;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.consent-banner button:hover { background: var(--accent-hover); }
.consent-banner button:disabled { opacity: 0.6; cursor: default; }

/* ---- Erasure (#48, ADR-0013) ---- */
/* The dashboard's danger zone: the same card as the sections above it, marked
   down the edge so the one irreversible thing on the page does not read as
   another form. The submit button is red rather than the accent colour for
   the same reason. */
.auth.dashboard.danger-zone { border-left: 3px solid #c0392b; }
[data-theme="dark"] .auth.dashboard.danger-zone { border-left-color: #f07167; }
.auth-form button[type="submit"].is-danger { background: #c0392b; }
.auth-form button[type="submit"].is-danger:hover { background: #96281b; }

/* An erased Owner on the moderation page: a tombstone, not a row of counts. */
.owner-row.is-erased { border-left: 3px solid var(--text-muted); opacity: 0.8; }

/* The handle typed into an inline confirmation before it will go through. */
.confirm-input {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.85rem;
}

/* The Import picker (#90, ADR-0024): one row per public repository, each a
   label wrapping its own checkbox so the whole row is the hit area. The rows
   reuse `.dash-row`, because a repository waiting to be picked and an Article
   in the Dashboard are the same card with different words in it. */
.repo-row .check-label {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  cursor: pointer;
}
.repo-row input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  margin-top: 0.3rem;
  flex: 0 0 auto;
  accent-color: var(--accent);
}
.repo-text { min-width: 0; }
.repo-row .dash-answer { margin: 0.35rem 0 0; }
.repo-meta {
  margin: 0.35rem 0 0;
  font-size: 0.8rem;
  color: var(--text-muted);
}
/* The Goal of a ticked repository (ADR-0028), under its row and indented to
   the text so it reads as belonging to that repository and not the next. */
.repo-goal { margin: 0.6rem 0 0 1.7rem; }
.repo-goal label { font-size: 0.85rem; }
.import-language { margin: 1rem 0; max-width: 22rem; }
.import-language select {
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
}
.import-language select:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
/* `.field` is a flex box, which beats the browser's own `[hidden]`. */
.repo-goal[hidden], .import-language[hidden] { display: none; }

/* The Import itself (#91): the button that starts a run, and the run's own
   rows. The button sits outside the account form -- it acts on the list, not
   on the box above it -- so it repeats the submit button's look rather than
   inheriting it, and the rows reuse `.dash-row` like the picker's do. */
#import-button {
  margin-top: 1rem;
  padding: 0.7rem 1.1rem;
  border: 0;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
#import-button:hover { background: var(--accent-hover); }
#import-button:disabled { opacity: 0.6; cursor: default; }
#import-run .dash-row { margin-bottom: 0.6rem; }
