/*
 * SignalKit theme — Bootstrap 5.3 CSS-variable overrides.
 * Implements the seed direction in /DESIGN.md (kanban #127).
 *
 * Loaded by templates/feed/layout.php and templates/admin/layout.php
 * after bootstrap.min.css and before bootstrap-icons. Component
 * structure stays Bootstrap; only tokens + a handful of selector
 * overrides land here.
 *
 * Section ordering mirrors DESIGN.md §1–§6. Named Rules from
 * DESIGN.md are quoted in the section headers so each block traces
 * back to its design contract.
 *
 * Reopen: bump THEME_CSS_VERSION in src/helpers.php on edit so
 * deployed instances refresh the cache (kanban #127, Decision #3).
 */


/* =========================================================================
 * 1. @font-face — Source Serif 4 + Public Sans
 *    Self-hosted variable WOFF2, latin + latin-ext, font-display: swap.
 *    See public/fonts/NOTICE.md for hosting + subsetting provenance.
 * ========================================================================= */

@font-face {
  font-family: "Source Serif 4";
  src: url("/fonts/SourceSerif4-Roman.woff2") format("woff2-variations"),
       url("/fonts/SourceSerif4-Roman.woff2") format("woff2");
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-024F, U+0259, U+0152-0153, U+02BB-02BC,
                 U+02C6, U+02DA, U+02DC, U+1E00-1EFF, U+2000-206F, U+2074,
                 U+2113, U+20A0-20CF, U+2122, U+2191, U+2193, U+2212, U+2215,
                 U+2C60-2C7F, U+A720-A7FF, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Source Serif 4";
  src: url("/fonts/SourceSerif4-Italic.woff2") format("woff2-variations"),
       url("/fonts/SourceSerif4-Italic.woff2") format("woff2");
  font-weight: 200 900;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-024F, U+0259, U+0152-0153, U+02BB-02BC,
                 U+02C6, U+02DA, U+02DC, U+1E00-1EFF, U+2000-206F, U+2074,
                 U+2113, U+20A0-20CF, U+2122, U+2191, U+2193, U+2212, U+2215,
                 U+2C60-2C7F, U+A720-A7FF, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Public Sans";
  src: url("/fonts/PublicSans-Roman.woff2") format("woff2-variations"),
       url("/fonts/PublicSans-Roman.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-024F, U+0259, U+0152-0153, U+02BB-02BC,
                 U+02C6, U+02DA, U+02DC, U+1E00-1EFF, U+2000-206F, U+2074,
                 U+2113, U+20A0-20CF, U+2122, U+2191, U+2193, U+2212, U+2215,
                 U+2C60-2C7F, U+A720-A7FF, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Public Sans";
  src: url("/fonts/PublicSans-Italic.woff2") format("woff2-variations"),
       url("/fonts/PublicSans-Italic.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-024F, U+0259, U+0152-0153, U+02BB-02BC,
                 U+02C6, U+02DA, U+02DC, U+1E00-1EFF, U+2000-206F, U+2074,
                 U+2113, U+20A0-20CF, U+2122, U+2191, U+2193, U+2212, U+2215,
                 U+2C60-2C7F, U+A720-A7FF, U+FEFF, U+FFFD;
}


/* =========================================================================
 * 2. :root — theme-agnostic tokens
 *    Bootstrap variables that don't change between light and dark themes,
 *    plus SignalKit-private tokens prefixed --sk-*.
 * ========================================================================= */

:root {
  /* Typography — body family, chrome family, sizes.
     The 1.0625rem Body Rule: 17px body, not Bootstrap's default 16px. */
  --bs-body-font-family: "Source Serif 4", Charter, "Iowan Old Style",
                         "Apple Garamond", Georgia, serif;
  --bs-body-font-size: 1.0625rem;
  --bs-body-line-height: 1.6;
  --bs-heading-font-family: "Source Serif 4", Charter, "Iowan Old Style",
                            "Apple Garamond", Georgia, serif;

  /* The Sans-for-Chrome Rule: Public Sans appears only on nav, labels,
     buttons, metadata. Private token, applied via selector overrides
     in §5 below. */
  --sk-font-label: "Public Sans", -apple-system, "Segoe UI", system-ui,
                   "Helvetica Neue", Arial, sans-serif;

  /* Shape — minimal radii. Pill kept for chips/badges. */
  --bs-border-radius: 2px;
  --bs-border-radius-sm: 2px;
  --bs-border-radius-lg: 3px;
  --bs-border-radius-xl: 4px;
  --bs-border-radius-2xl: 6px;
  --bs-border-radius-pill: 999px;

  /* The No-Shadow Rule: decorative shadows forbidden. Box-shadow
     reserved for focus rings (§5) and modal backdrops (Bootstrap default). */
  --bs-box-shadow: none;
  --bs-box-shadow-sm: none;
  --bs-box-shadow-lg: none;
  --bs-box-shadow-inset: none;

  /* Motion — ease-out-quint per DESIGN.md, with the 100/300/500 cadence
     from impeccable's motion-design.md. */
  --sk-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --sk-dur-fast: 120ms;
  --sk-dur-base: 200ms;
}


/* =========================================================================
 * 3. Theme-scoped tokens — the Paper-and-Clay palette.
 *    Light and dark share the 60–65° hue family (Same-Room Rule).
 *    Clay Accent stays identical across themes; neutrals swap.
 *    Hex fallbacks listed alongside OKLCH for tools that need sRGB.
 * ========================================================================= */

[data-bs-theme="light"] {
  /* Surfaces — Paper Cream / Paper Card. */
  --bs-body-bg:           oklch(96.5% 0.012 65);  /* #f6f1e7 — Paper Cream */
  --bs-body-bg-rgb:       246, 241, 231;
  --bs-secondary-bg:      oklch(98% 0.008 65);    /* #fbf7ef — Paper Card */
  --bs-secondary-bg-rgb:  251, 247, 239;
  --bs-tertiary-bg:       oklch(94% 0.012 65);    /* slightly deeper paper for input chrome */
  --bs-tertiary-bg-rgb:   238, 232, 220;

  /* Text — Ink Deep / Meta. */
  --bs-body-color:        oklch(20% 0.015 60);    /* #2a2520 — Ink Deep */
  --bs-body-color-rgb:    42, 37, 32;
  --bs-secondary-color:   oklch(50% 0.012 60);    /* #6f685e — Meta */
  --bs-tertiary-color:    oklch(60% 0.01 60);
  --bs-emphasis-color:    oklch(15% 0.02 60);     /* darker ink for strong text */

  /* Rules — single hairline carries hierarchy (Flat-by-Default). */
  --bs-border-color:                oklch(88% 0.008 65);  /* #dcd4c5 — Paper Rule */
  --bs-border-color-translucent:    rgba(42, 37, 32, 0.12);

  /* Brand accent — Clay (One Accent Rule). */
  --bs-primary:            oklch(54% 0.13 35);    /* #b8552d — Clay Accent */
  --bs-primary-rgb:        184, 85, 45;
  --bs-link-color:         oklch(54% 0.13 35);
  --bs-link-color-rgb:     184, 85, 45;
  --bs-link-hover-color:   oklch(45% 0.14 35);    /* #9c4422 — Clay Accent Deep */
  --bs-link-hover-color-rgb: 156, 68, 34;

  /* Body weight — heading + body share the same render under serif. */
  --bs-body-font-weight: 400;

  /* SignalKit privates carrying through to selectors. */
  --sk-clay:              oklch(54% 0.13 35);
  --sk-clay-deep:         oklch(45% 0.14 35);
  --sk-clay-soft:         oklch(54% 0.13 35 / 0.5);    /* focus ring at 0.5 alpha */
  --sk-clay-tint:         oklch(54% 0.13 35 / 0.08);   /* faint background tint */
  --sk-rule:              oklch(88% 0.008 65);
}

[data-bs-theme="dark"] {
  /* Surfaces — Paper Deep / Paper Deep Card. */
  --bs-body-bg:           oklch(18% 0.012 65);    /* #221e18 — Paper Deep */
  --bs-body-bg-rgb:       34, 30, 24;
  --bs-secondary-bg:      oklch(22% 0.012 65);    /* #2c271f — Paper Deep Card */
  --bs-secondary-bg-rgb:  44, 39, 31;
  --bs-tertiary-bg:       oklch(25% 0.012 65);
  --bs-tertiary-bg-rgb:   50, 45, 36;

  /* Text — Ink Pale / Meta Dark. Body weight steps down per
     color-and-contrast.md compensation: light text on dark reads heavier. */
  --bs-body-color:        oklch(92% 0.008 60);    /* #ebe5d9 — Ink Pale */
  --bs-body-color-rgb:    235, 229, 217;
  --bs-secondary-color:   oklch(70% 0.01 60);     /* #a89f91 — Meta Dark */
  --bs-tertiary-color:    oklch(60% 0.01 60);
  --bs-emphasis-color:    oklch(98% 0.005 60);

  /* Rules — Paper Rule Dark. */
  --bs-border-color:                oklch(30% 0.01 65);   /* #3a342c */
  --bs-border-color-translucent:    rgba(235, 229, 217, 0.12);

  /* Brand accent — Clay holds across themes (Same-Room Rule).
     Lightened a touch for legibility on dark paper. */
  --bs-primary:            oklch(62% 0.14 35);
  --bs-primary-rgb:        209, 109, 67;
  --bs-link-color:         oklch(62% 0.14 35);
  --bs-link-color-rgb:     209, 109, 67;
  --bs-link-hover-color:   oklch(72% 0.14 35);    /* lifts on hover in dark */
  --bs-link-hover-color-rgb: 234, 144, 99;

  /* Body weight steps down to 380 in dark theme to compensate
     for perceived weight gain (typography.md). */
  --bs-body-font-weight: 380;

  --sk-clay:              oklch(62% 0.14 35);
  --sk-clay-deep:         oklch(72% 0.14 35);
  --sk-clay-soft:         oklch(62% 0.14 35 / 0.55);
  --sk-clay-tint:         oklch(62% 0.14 35 / 0.1);
  --sk-rule:              oklch(30% 0.01 65);
}


/* =========================================================================
 * 4. Body + heading typography
 *    Variable-font features, optical sizing, text-wrap polish, the
 *    68ch measure cap on long-form prose.
 * ========================================================================= */

html {
  /* Improve subpixel rendering on macOS without breaking Linux. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Reserve space for the vertical scrollbar even when it's not needed.
     Without this, pages that cross the scrollbar-visible threshold cause
     centered containers to shift by (scrollbar-width / 2) — e.g. navigating
     between / and /tag/{slug} when one fits in the viewport and the other
     doesn't. scrollbar-gutter: stable keeps the viewport width constant. */
  scrollbar-gutter: stable;
}

body {
  font-optical-sizing: auto;
  font-kerning: normal;
  font-variant-ligatures: common-ligatures contextual;
}

/* Headings — even out line lengths, match body family. */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: var(--bs-heading-font-family);
  font-weight: 600;
  letter-spacing: -0.005em;
  text-wrap: balance;
}

h1, .h1 {
  font-size: clamp(1.85rem, 1.4rem + 1.8vw, 2.65rem);
  line-height: 1.15;
  font-weight: 600;
}
h2, .h2 { line-height: 1.2; }
h3, .h3 { line-height: 1.25; }

/* Heading link inheritance — the One Accent Rule.
   Linked headings (feed-card titles, etc.) must NOT take on Clay link
   color. Otherwise stacked story titles dominate the surface and blow
   past the ≤10% accent budget. Heading links read as Ink Deep at rest;
   Clay only on hover/focus where the affordance helps. */
:where(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) a {
  color: inherit;
  text-decoration: none;
  transition: color var(--sk-dur-base) var(--sk-ease);
}
:where(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) a:hover,
:where(h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6) a:focus-visible {
  color: var(--sk-clay);
  text-decoration: none;
}

/* Long-form prose — 68ch measure cap (the 68ch Rule). Containers tagged
   with these classes get the cap; admin tables and grids are unaffected.
   .e-content is the microformats class for h-entry article bodies. */
.story-body,
.page-body,
.h-entry .e-content,
article.h-entry > .e-content {
  max-width: 68ch;
  text-wrap: pretty;
}

.story-body p,
.page-body p,
.h-entry .e-content p {
  text-wrap: pretty;
}

/* Tabular numerals on data-shaped surfaces. */
.table,
.font-tabular,
time, .meta-time, .h-entry time {
  font-variant-numeric: tabular-nums;
}


/* =========================================================================
 * 5. Component selectors — minimal, only where Bootstrap defaults
 *    fight the design contract.
 *    See DESIGN.md §5 (Components) for the per-component rationale.
 * ========================================================================= */

/* Sans-for-Chrome surfaces. */
.btn,
.nav-link,
.navbar-brand,
.navbar-text,
.form-label,
.form-check-label,
.input-group-text,
.dropdown-item,
.breadcrumb,
.breadcrumb-item,
.badge,
.pagination,
.pagination .page-link,
.alert .alert-heading,
.list-group-item-action,
.btn-toolbar,
.toast-header,
.modal-title {
  font-family: var(--sk-font-label);
}

/* Buttons — Clay Accent as primary; flat surfaces; transition only color. */
.btn {
  font-weight: 500;
  letter-spacing: 0.01em;
  transition: background-color var(--sk-dur-base) var(--sk-ease),
              border-color var(--sk-dur-base) var(--sk-ease),
              color var(--sk-dur-base) var(--sk-ease);
}

.btn-primary,
.btn-primary:active {
  background-color: var(--sk-clay);
  border-color: var(--sk-clay);
  color: var(--bs-body-bg);
}
.btn-primary:hover,
.btn-primary:focus-visible {
  background-color: var(--sk-clay-deep);
  border-color: var(--sk-clay-deep);
  color: var(--bs-body-bg);
}
.btn-primary:disabled,
.btn-primary.disabled {
  background-color: var(--sk-clay);
  border-color: var(--sk-clay);
  opacity: 0.55;
}

/* Outline-primary — Paper Card surface, Clay text, hairline border. */
.btn-outline-primary {
  color: var(--sk-clay);
  border-color: var(--sk-clay);
  background-color: transparent;
}
.btn-outline-primary:hover,
.btn-outline-primary:focus-visible {
  background-color: var(--sk-clay-tint);
  color: var(--sk-clay-deep);
  border-color: var(--sk-clay-deep);
}

/* Links — underline only on hover in chrome contexts; persistent
   underline within long-form prose so links stay legible. */
a {
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--sk-dur-base) var(--sk-ease);
}
.story-body a,
.page-body a,
.h-entry .e-content a {
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}
.nav-link,
.navbar-nav .nav-link,
.dropdown-item,
.breadcrumb a {
  text-decoration: none;
}

/* Focus visibility — 2px ring in Clay at 0.5 alpha, offset 2px.
   Replaces Bootstrap's blue glow on every interactive element. */
.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible,
.nav-link:focus-visible,
.dropdown-item:focus-visible,
a:focus-visible,
.page-link:focus-visible,
.btn-close:focus-visible {
  outline: 2px solid var(--sk-clay-soft);
  outline-offset: 2px;
  box-shadow: none;
}

/* Form controls — color shift on focus, no glow (No-Shadow Rule). */
.form-control,
.form-select {
  background-color: var(--bs-body-bg);
  border-color: var(--bs-border-color);
  color: var(--bs-body-color);
  transition: border-color var(--sk-dur-base) var(--sk-ease);
}
.form-control:focus,
.form-select:focus {
  background-color: var(--bs-body-bg);
  border-color: var(--sk-clay);
  box-shadow: none;
  color: var(--bs-body-color);
}
.form-control::placeholder { color: var(--bs-secondary-color); opacity: 1; }

/* Cards — Flat Card Rule. Hairline border, Paper Card background, no shadow. */
.card {
  background-color: var(--bs-secondary-bg);
  border: 1px solid var(--bs-border-color);
  box-shadow: none;
}
.card-header,
.card-footer {
  background-color: transparent;
  border-color: var(--bs-border-color);
}
/* Nested cards are forbidden; this neutralizes the inner card if one slips in. */
.card .card { border: 0; background-color: transparent; }

/* Navigation — active state uses an underline-from-below in Clay,
   not Bootstrap's default background pill. */
.navbar-nav .nav-link {
  color: var(--bs-secondary-color);
  position: relative;
}
.navbar-nav .nav-link:hover,
.navbar-nav .nav-link.active {
  color: var(--bs-body-color);
}
.navbar-nav .nav-link.active::after {
  content: "";
  position: absolute;
  left: 0.5rem;
  right: 0.5rem;
  bottom: 0.25rem;
  height: 2px;
  background: var(--sk-clay);
}
/* Dark navbar (top nav + footer + admin top bar) keeps the white-on-dark
   contract for legibility, BUT the surface itself retunes to Paper Deep
   instead of Bootstrap's near-black `--bs-dark-rgb` (33, 37, 41).
   Same-Room Rule: against Paper Cream the nav must read as the same
   building at evening lamp, not a stranger. */
.navbar.bg-dark,
footer.bg-dark {
  background-color: oklch(18% 0.012 65) !important;
}
.navbar[data-bs-theme="dark"] .nav-link {
  color: rgba(235, 229, 217, 0.78);
}
.navbar[data-bs-theme="dark"] .nav-link:hover,
.navbar[data-bs-theme="dark"] .nav-link.active {
  color: rgba(235, 229, 217, 1);
}
.navbar[data-bs-theme="dark"] .nav-link.active::after {
  background: var(--sk-clay);
}
/* Search affordances inside dark nav — outline-light buttons and
   form-control should read on Paper Deep, not on Bootstrap's flat dark. */
.navbar[data-bs-theme="dark"] .btn-outline-light {
  color: rgba(235, 229, 217, 0.92);
  border-color: rgba(235, 229, 217, 0.5);
}
.navbar[data-bs-theme="dark"] .btn-outline-light:hover,
.navbar[data-bs-theme="dark"] .btn-outline-light:focus-visible {
  color: oklch(18% 0.012 65);
  background-color: rgba(235, 229, 217, 0.92);
  border-color: rgba(235, 229, 217, 0.92);
}

/* Tag chips / badges — Public Sans, pill, Paper Rule border by default,
   Clay Accent invert when selected. */
.badge {
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 0.35em 0.75em;
}
.bg-primary {
  background-color: var(--sk-clay) !important;
}
.text-bg-primary {
  background-color: var(--sk-clay) !important;
  color: var(--bs-body-bg) !important;
}

/* Tag-filter chips (used by /js/tag-filter.js on the homepage). */
.tag-filter .badge,
.tag-filter a.badge {
  background-color: transparent;
  border: 1px solid var(--bs-border-color);
  color: var(--bs-secondary-color);
  text-decoration: none;
  transition: background-color var(--sk-dur-base) var(--sk-ease),
              color var(--sk-dur-base) var(--sk-ease),
              border-color var(--sk-dur-base) var(--sk-ease);
}
.tag-filter .badge:hover,
.tag-filter a.badge:hover {
  border-color: var(--sk-clay);
  color: var(--sk-clay);
}
.tag-filter .badge.active,
.tag-filter a.badge.active {
  background-color: var(--sk-clay);
  border-color: var(--sk-clay);
  color: var(--bs-body-bg);
}

/* Bordered taxonomy badges (#131 follow-up).
   When templates use `class="badge border text-primary"` or
   `class="badge border text-body-secondary"`, they get a transparent-bg
   chip with a 1px border in the matching token color. Used for category
   labels (Blog, Note, etc.) so they read as taxonomy, not action
   affordances. Honors the One Accent Rule by keeping Clay used as text
   and stroke only, never as filled rectangles. */
.badge.border.text-primary {
  background-color: transparent;
  border-color: var(--sk-clay) !important;
  color: var(--sk-clay) !important;
  font-weight: 500;
}
.badge.border.text-body-secondary {
  background-color: transparent;
  border-color: var(--bs-border-color) !important;
  color: var(--bs-secondary-color) !important;
  font-weight: 500;
}

/* Story-card image previews (#131 finding A).
   The card has a hairline `var(--bs-border-color)` border per the Flat
   Card Rule; the image inside should match that weight so the chrome
   reads as one piece. Matches `border-radius` to the card's small radius. */
.story-card img.rounded,
article.h-entry img.rounded,
.feed-list img.rounded,
img.story-thumbnail {
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
}

/* Dropdowns — flat surface with a hairline. */
.dropdown-menu {
  background-color: var(--bs-body-bg);
  border: 1px solid var(--bs-border-color);
  box-shadow: none;
}
.dropdown-item:hover,
.dropdown-item:focus {
  background-color: var(--sk-clay-tint);
  color: var(--bs-body-color);
}

/* Alerts — flat with a single full border, never side-stripe (absolute ban). */
.alert {
  border: 1px solid var(--bs-border-color);
  background-color: var(--bs-secondary-bg);
}
.alert-primary {
  border-color: var(--sk-clay);
  background-color: var(--sk-clay-tint);
  color: var(--bs-body-color);
}

/* Tables — quiet hairline rules, no zebra by default. */
.table {
  --bs-table-bg: transparent;
  --bs-table-border-color: var(--bs-border-color);
  --bs-table-color: var(--bs-body-color);
}
.table > :not(caption) > * > * {
  padding: 0.65rem 0.75rem;
}

/* Pagination — flat, Clay accent on current page. */
.page-link {
  background-color: transparent;
  border-color: var(--bs-border-color);
  color: var(--bs-body-color);
}
.page-link:hover {
  background-color: var(--sk-clay-tint);
  color: var(--sk-clay-deep);
  border-color: var(--bs-border-color);
}
.page-item.active .page-link {
  background-color: var(--sk-clay);
  border-color: var(--sk-clay);
  color: var(--bs-body-bg);
}


/* =========================================================================
 * 6. Reduced motion — universal collapse.
 *    Honored across every transition + animation regardless of selector.
 *    Theme toggle is intentionally instant (no transition) regardless.
 * ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}
