/* ============================================================================
   scripture.living — design tokens
   A theme layer OVER @byre/brocade. We keep brocade's structural scales
   (spacing, type-scale, radii, shadow, motion, z-index, modes) and re-skin the
   palette + fonts to the "type-specimen" aesthetic: warm paper, book-page cards,
   palette B (Newsreader for scripture, Work Sans for the interface).

   Brocade is linked first; this layer is declared LAST so it wins, and it drives
   light/dark itself (matching brocade's dual activation: @media + .mode-* class),
   so the theme mod's toggle re-skins brocade AND scripture components at once.
   Domain semantics (must/shall/… , truth/wisdom/…) stay OURS — brocade never
   canonicalizes them; we only change what they point at.
   ============================================================================ */

/* Layer order (per brocade modes.draft "Mode Precedence"): our theme owns the
   palette + light/dark (above color-scheme), but brocade's ACCESSIBILITY modes
   (transparency/motion/contrast) must outrank it, so they sit ABOVE scripture.theme. */
@layer brocade.primitives, brocade.semantic,
       brocade.modes.color-scheme,
       scripture.theme,
       brocade.modes.transparency, brocade.modes.motion, brocade.modes.contrast,
       scripture.base;

@layer scripture.theme {
  :root {
    /* ---- scripture raw palette — light (the specimen aesthetic) ---------- */
    --scripture-raw-paper:      #faf9f7;
    --scripture-raw-card:       #ffffff;
    --scripture-raw-ink:        #1a1815;
    --scripture-raw-ink-soft:   #4a453e;
    --scripture-raw-muted:      #6b645a;   /* darkened for AA (>=4.5:1 on paper) */
    --scripture-raw-faint:      #e9e5df;
    --scripture-raw-line:       #ece8e2;
    --scripture-raw-accent:     #7c5cff;
    --scripture-raw-accent-ink: #ffffff;

    /* ---- fonts — palette B (default). Swap this block for A or C. -------- */
    --scripture-font-reading: "Newsreader", Georgia, "Times New Roman", serif;
    --scripture-font-display: "Newsreader", Georgia, serif;
    --scripture-font-ui:      "Work Sans", system-ui, -apple-system, sans-serif;

    /* ---- re-skin brocade semantic tokens onto the scripture palette ------ */
    /* (references to raw tokens are live, so the dark block below only needs
        to re-declare the raw palette and everything downstream re-resolves.)  */
    --brocade-color-background-base:     var(--scripture-raw-paper);
    --brocade-color-background-elevated: var(--scripture-raw-card);
    --brocade-color-background-muted:    var(--scripture-raw-faint);
    --brocade-color-background-hover:    var(--scripture-raw-faint);
    --brocade-color-foreground-base:     var(--scripture-raw-ink);
    --brocade-color-foreground-muted:    var(--scripture-raw-ink-soft);
    --brocade-color-foreground-subtle:   var(--scripture-raw-muted);
    --brocade-color-border-base:         var(--scripture-raw-line);
    --brocade-color-border-muted:        var(--scripture-raw-faint);
    --brocade-color-primary-base:        var(--scripture-raw-accent);
    --brocade-color-primary-foreground:  var(--scripture-raw-accent-ink);
    --brocade-font-family-base:          var(--scripture-font-ui);
    --brocade-font-family-heading:       var(--scripture-font-display);

    /* ---- scripture semantic tokens (what our own components consume) ----- */
    --scripture-bg:       var(--brocade-color-background-base);
    --scripture-surface:  var(--brocade-color-background-elevated);
    --scripture-ink:      var(--brocade-color-foreground-base);
    --scripture-ink-soft: var(--brocade-color-foreground-muted);
    --scripture-muted:    var(--brocade-color-foreground-subtle);
    --scripture-line:     var(--brocade-color-border-base);
    --scripture-faint:    var(--scripture-raw-faint);
    --scripture-accent:   var(--brocade-color-primary-base);

    /* ---- reading-surface metrics — poetry + editorial voices -------------
       Per the brocade consult (2026-07-27): READING metrics are minted at OUR
       raw layer in text-relative units (em/lh) so they scale with the reading
       type, never the app chrome (rem indents drift when a reader bumps the
       font). Part of the THEME CONTRACT: a font-variant theme may retune the
       hang. Rules consume only the semantic tokens below. */
    --scripture-raw-poetry-indent:   1em;    /* q2's extra step past q1 */
    --scripture-raw-poetry-hang:     1.5em;  /* wrapped-line hang, both levels */
    /* 1lh (one line of rhythm) is applied via the @supports override below —
       a custom-property declaration is grammar-agnostic, so declaring 1lh here
       directly would SET the token even in a non-lh browser and make every
       consumer's margin invalid-at-computed-value (0), with the var() fallbacks
       unreachable. Default to the em approximation; upgrade when lh is real. */
    --scripture-raw-stanza-gap:      1.5em;
    --scripture-raw-inset-indent:    1.5em;  /* pi/mi/li inset blocks */
    --scripture-raw-division-size:   1.08em; /* ms division: heading-ish, scales WITH the reading */
    /* THEME-CONTRACT INVARIANT (brocade review): poetry-hang MUST exceed
       poetry-indent, so every WRAPPED line lands deeper than every intentional
       line start — runovers can never be misread as a poetry level. The future
       custom-theme validator enforces this alongside the AA gate.
       MICRO-LITERAL POLICY: optical micro-adjustments (.vn metrics, the
       speaker-label 0.92em, 1px highlight rings) are an explicit exemption
       from token mediation until the stylelint token rule lands — a decision,
       not drift. */

    --scripture-poetry-indent-1: 0em;
    --scripture-poetry-indent-2: var(--scripture-raw-poetry-indent, 1em);
    --scripture-poetry-hang:     var(--scripture-raw-poetry-hang, 1.5em);
    --scripture-stanza-gap:      var(--scripture-raw-stanza-gap, 1.5em);
    --scripture-inset-indent:    var(--scripture-raw-inset-indent, 1.5em);
    --scripture-voice-division-size: var(--scripture-raw-division-size, 1.08em);

    /* editorial voice treatments (keyword-valued tokens; themes may restyle
       the voices without touching rules). d = received text (italic);
       sp = apparatus speaker label (spaced small-caps — data is mixed-case);
       ms = apparatus division (display caps). */
    --scripture-voice-super-style:    italic;
    --scripture-voice-label-variant:  small-caps;
    --scripture-voice-label-tracking: var(--brocade-raw-letter-spacing-wider, 0.05em);
    --scripture-voice-division-tracking: var(--brocade-raw-letter-spacing-widest, 0.1em);

    /* reading rhythm + spacing (bespoke scale referenced by app.css).
       Reading size is FLUID: comfortable on a phone, and larger on a big screen
       (the operator's 4K@100%) so the reading is physically bigger — while the ch
       measure holds the line length constant for readability (brocade's principle:
       width buys panes, never wider text). */
    --scripture-reading-size:    clamp(1.08rem, 1rem + 0.2vw, 1.5rem);
    --scripture-reading-leading: 1.72;
    --scripture-reading-measure: 72ch;
    /* layered chrome: drawers sit at 20/21 (literals, historical), the Visuals
       popover at 40; overlay surfaces (bottom sheet, its pill) above them. */
    --scripture-z-overlay:       50;
    --scripture-space-para:      1.05rem;   /* between reading paragraphs */
    --scripture-space-rule:      1.2rem;    /* around hairline dividers   */
    /* claim-goto landing (note tap → verse): scroll-margin clearance that parks
       the target word on the second-to-top line — the sticky chapter head's
       chrome (~3.4rem: its paddings + heading line + rule) plus ONE reading
       line, reading-relative so the breathing room scales with the type. */
    --scripture-goto-margin: calc(3.4rem + var(--scripture-reading-size, 1.15rem) * var(--scripture-reading-leading, 1.72));
    --scripture-dot-size:        3px;       /* metadata separator dot     */

    /* book-turn ceremony (discrete-volume nav): the vertical interstitial's cover/
       reveal timing + the dwell (longer at the testament hinge). Minted raw so a
       theme can retune the ritual; JS reads the durations + dwell via getComputedStyle,
       the CSS transition reads cover/reveal directly. */
    --scripture-raw-bookturn-cover:       .42s;
    --scripture-raw-bookturn-reveal:      .5s;
    --scripture-raw-bookturn-dwell:       .5s;
    --scripture-raw-bookturn-dwell-hinge: 1.1s;
    --scripture-raw-bookturn-ease:        cubic-bezier(.22, .61, .36, 1);
    --scripture-bookturn-cover-dur:   var(--scripture-raw-bookturn-cover, .42s);
    --scripture-bookturn-reveal-dur:  var(--scripture-raw-bookturn-reveal, .5s);
    --scripture-bookturn-dwell:       var(--scripture-raw-bookturn-dwell, .5s);
    --scripture-bookturn-dwell-hinge: var(--scripture-raw-bookturn-dwell-hinge, 1.1s);
    --scripture-bookturn-ease:        var(--scripture-raw-bookturn-ease, ease);
    --scripture-z-bookturn:           30;

    /* layout widths — the reading column sizes to its measure (capped); the shell
       holds reading + apparatus, and grows the study surface on wide screens. */
    --scripture-shell-max:   88rem;
    --scripture-reading-col: 58rem;
    --scripture-aside-col:   24rem;
    /* cap the reading window to ~legal-pad proportion (8.5:14) of its width, so on a
       tall screen it floats as a comfortable column instead of a full-height scroll */
    --scripture-reading-max-h: calc(var(--scripture-reading-col, 58rem) * 14 / 8.5);

    /* the book-page card.
       DEAD-FALLBACK RULE (brocade review 2026-07-27): a var() fallback fires
       only when the token is UNDEFINED — never park design intent in one.
       Where OUR value is the design, mint it at the raw layer and re-skin the
       brocade semantic token (the palette bridge pattern); where brocade's
       value is fine, the fallback merely approximates it. */
    --scripture-raw-shadow-card: 0 1px 3px rgba(30, 25, 20, .06),
                                 0 10px 34px rgba(30, 25, 20, .05);  /* the warm paper shadow — OUR design */
    --scripture-raw-shadow-sheet: 0 -8px 30px rgba(30, 25, 20, .18); /* bottom sheet: warm, UPWARD elevation */
    --scripture-raw-card-radius: 14px;
    --brocade-shadow-card:   var(--scripture-raw-shadow-card);  /* re-skin: keeps high-contrast shadow zeroing live */
    --scripture-card-bg:     var(--scripture-surface);
    --scripture-card-radius: var(--scripture-raw-card-radius, 14px);
    --scripture-card-shadow: var(--brocade-shadow-card, 0 1px 3px rgba(30, 25, 20, .08));
    --scripture-card-pad:    var(--brocade-size-padding-2xl, 3rem);
    --scripture-sheet-shadow: var(--scripture-raw-shadow-sheet, 0 -8px 30px rgba(30, 25, 20, .18));
    --scripture-sheet-content-pad: var(--brocade-size-padding-md, 1rem);

    /* ---- domain category + requirement colors (OUR theme) ---------------
       Light-mode values are darkened enough for AA as small label text on paper;
       the dark block below lightens them for dark surfaces. */
    --scripture-cat-faith:       #6a4bd6;   /* truth  */
    --scripture-cat-instruction: #0a53a8;   /* normative */
    --scripture-cat-wisdom:      #157347;   /* provisional */

    /* ---- interlinear version colours (design/interlinear.draft): WEB reads in
       the ink; source languages get distinct saturated hues; extra translations
       are muted so the eye anchors on WEB + the source line. Dark values in the
       dark blocks below. ------------------------------------------------------ */
    --scripture-version-hebrew:    #8a5a2b;   /* WLC   */
    --scripture-version-greek:     #2f6d8c;   /* TR    */
    --scripture-version-greek-alt: #3f8ea3;   /* Byz   */
    --scripture-version-latin:     #5c7a39;   /* Vulgate */
    --scripture-version-alt-a:     #6f675c;   /* ASV — warm grey */
    --scripture-version-alt-b:     #6d6480;   /* YLT — mauve grey */
    /* contrast ink to place ON a filled category chip. Aliases accent-ink, which
       every palette+mode block already flips (near-white in light modes, near-black
       in dark), so a pressed chip's label auto-inverts with the theme — no manual
       per-mode override in the component. */
    --scripture-cat-ink:         var(--scripture-raw-accent-ink);
    --scripture-req-must:      #1a7f37;
    --scripture-req-must-not:  #cf222e;
    --scripture-req-should:    #9a6700;
    --scripture-req-may:       #6639ba;
    /* the affirmative "approve/curate" action color; aliases the (themed-per-mode)
       wisdom green so it tracks light/dark automatically without a per-block override */
    --scripture-approve:       var(--scripture-cat-wisdom, #157347);

    /* palette-preview swatch signatures. A swatch previews an INACTIVE palette's
       paper+accent, so it can't read the live raw tokens (those reflect only the
       active palette) — the values are constants, kept here in the token layer
       rather than hardcoded in the component. */
    --scripture-swatch-paper: linear-gradient(135deg, #faf9f7 54%, #7c5cff 54%);
    --scripture-swatch-sepia: linear-gradient(135deg, #f3ead6 54%, #9d6a34 54%);
    --scripture-swatch-slate: linear-gradient(135deg, #eef1f4 54%, #3a6ea5 54%);
    --scripture-swatch-night: linear-gradient(135deg, #1e232c 54%, #7fa0dc 54%);
  }

  /* stanza gap upgrades to exactly one line of rhythm where lh is real
     (the design's support-check ruling — see the raw token's comment) */
  @supports (margin-block-start: 1lh) {
    :root { --scripture-raw-stanza-gap: 1lh; }
  }

  /* ---- dark: warm dark. Re-declare ONLY the raw palette; the semantic
          mappings above reference these live and re-resolve. ------------- */
  @media (prefers-color-scheme: dark) {
    :root:not(.mode-light) {
      --scripture-raw-paper:      #141311;
      --scripture-raw-card:       #1c1a17;
      --scripture-raw-ink:        #f2efe9;
      --scripture-raw-ink-soft:   #c3bcb1;
      --scripture-raw-muted:      #8f887d;
      --scripture-raw-faint:      #2a2723;
      --scripture-raw-line:       #2a2723;
      --scripture-raw-accent:     #a794ff;
      --scripture-raw-accent-ink: #141311;
      --scripture-cat-faith:      #a794ff;
      --scripture-cat-instruction:#6fa8ff;
      --scripture-cat-wisdom:     #4fc78a;
      --scripture-version-hebrew:    #ca9a6a;
      --scripture-version-greek:     #7fb8d8;
      --scripture-version-greek-alt: #8fcbe0;
      --scripture-version-latin:     #a3c780;
      --scripture-version-alt-a:     #a89f92;
      --scripture-version-alt-b:     #a89bc0;
    }
  }
  .mode-dark {
    --scripture-raw-paper:      #141311;
    --scripture-raw-card:       #1c1a17;
    --scripture-raw-ink:        #f2efe9;
    --scripture-raw-ink-soft:   #c3bcb1;
    --scripture-raw-muted:      #8f887d;
    --scripture-raw-faint:      #2a2723;
    --scripture-raw-line:       #2a2723;
    --scripture-raw-accent:     #a794ff;
    --scripture-raw-accent-ink: #141311;
    --scripture-cat-faith:      #a794ff;
    --scripture-cat-instruction:#6fa8ff;
    --scripture-cat-wisdom:     #4fc78a;
    --scripture-version-hebrew:    #ca9a6a;
    --scripture-version-greek:     #7fb8d8;
    --scripture-version-greek-alt: #8fcbe0;
    --scripture-version-latin:     #a3c780;
    --scripture-version-alt-a:     #a89f92;
    --scripture-version-alt-b:     #a89bc0;
  }

  /* ============ selectable PALETTE themes ==================================
     Per brocade modes.draft: THEMES touch the RAW layer, MODES touch semantic —
     so palette (a single-select ATTRIBUTE on :root) composes cleanly with the
     light/dark axis (the .mode-* class / prefers-color-scheme). Each palette
     re-declares ONLY the raw palette (+ category colors for a dark-toned palette);
     every semantic reference re-resolves live. Paper = the default block above. */

  /* ---- Sepia: aged, warm paper ---- */
  :root[data-palette="sepia"] {
    --scripture-raw-paper: #f3ead6; --scripture-raw-card: #f9f2e0; --scripture-raw-ink: #40331f;
    --scripture-raw-ink-soft: #665538; --scripture-raw-muted: #877656; --scripture-raw-faint: #e7dabf;
    --scripture-raw-line: #ded0b3; --scripture-raw-accent: #9d6a34; --scripture-raw-accent-ink: #fbf6ec;
  }
  :root[data-palette="sepia"].mode-dark {
    --scripture-raw-paper: #1d1710; --scripture-raw-card: #251e15; --scripture-raw-ink: #ece0c6;
    --scripture-raw-ink-soft: #cbb994; --scripture-raw-muted: #9c8b6d; --scripture-raw-faint: #322a1e;
    --scripture-raw-line: #322a1e; --scripture-raw-accent: #d6a05f; --scripture-raw-accent-ink: #1d1710;
  }
  @media (prefers-color-scheme: dark) { :root[data-palette="sepia"]:not(.mode-light) {
    --scripture-raw-paper: #1d1710; --scripture-raw-card: #251e15; --scripture-raw-ink: #ece0c6;
    --scripture-raw-ink-soft: #cbb994; --scripture-raw-muted: #9c8b6d; --scripture-raw-faint: #322a1e;
    --scripture-raw-line: #322a1e; --scripture-raw-accent: #d6a05f; --scripture-raw-accent-ink: #1d1710;
  } }

  /* ---- Slate: cool neutral grey ---- */
  :root[data-palette="slate"] {
    --scripture-raw-paper: #eef1f4; --scripture-raw-card: #ffffff; --scripture-raw-ink: #1b2531;
    --scripture-raw-ink-soft: #46515f; --scripture-raw-muted: #66727f; --scripture-raw-faint: #e0e5ea;
    --scripture-raw-line: #d9dfe6; --scripture-raw-accent: #3a6ea5; --scripture-raw-accent-ink: #ffffff;
  }
  :root[data-palette="slate"].mode-dark {
    --scripture-raw-paper: #10151b; --scripture-raw-card: #191f27; --scripture-raw-ink: #e6ecf3;
    --scripture-raw-ink-soft: #b1bbc9; --scripture-raw-muted: #7d8797; --scripture-raw-faint: #242b34;
    --scripture-raw-line: #242b34; --scripture-raw-accent: #6ba1de; --scripture-raw-accent-ink: #10151b;
  }
  @media (prefers-color-scheme: dark) { :root[data-palette="slate"]:not(.mode-light) {
    --scripture-raw-paper: #10151b; --scripture-raw-card: #191f27; --scripture-raw-ink: #e6ecf3;
    --scripture-raw-ink-soft: #b1bbc9; --scripture-raw-muted: #7d8797; --scripture-raw-faint: #242b34;
    --scripture-raw-line: #242b34; --scripture-raw-accent: #6ba1de; --scripture-raw-accent-ink: #10151b;
  } }

  /* ---- Night: deep low-light reading (dark-toned in BOTH modes → keep the
     lightened category colors so they stay legible) ---- */
  :root[data-palette="night"] {
    --scripture-raw-paper: #161922; --scripture-raw-card: #1e232c; --scripture-raw-ink: #dce2ea;
    --scripture-raw-ink-soft: #a9b1bf; --scripture-raw-muted: #79818e; --scripture-raw-faint: #29303a;
    --scripture-raw-line: #29303a; --scripture-raw-accent: #7fa0dc; --scripture-raw-accent-ink: #10131a;
    --scripture-cat-faith: #a794ff; --scripture-cat-instruction: #6fa8ff; --scripture-cat-wisdom: #4fc78a;
  }
  :root[data-palette="night"].mode-dark {
    --scripture-raw-paper: #0b0d11; --scripture-raw-card: #13161c; --scripture-raw-ink: #e4e8f0;
    --scripture-raw-ink-soft: #b0b8c6; --scripture-raw-muted: #7c8492; --scripture-raw-faint: #1c2028;
    --scripture-raw-line: #1c2028; --scripture-raw-accent: #8aa8e0; --scripture-raw-accent-ink: #0b0d11;
  }
  @media (prefers-color-scheme: dark) { :root[data-palette="night"]:not(.mode-light) {
    --scripture-raw-paper: #0b0d11; --scripture-raw-card: #13161c; --scripture-raw-ink: #e4e8f0;
    --scripture-raw-ink-soft: #b0b8c6; --scripture-raw-muted: #7c8492; --scripture-raw-faint: #1c2028;
    --scripture-raw-line: #1c2028; --scripture-raw-accent: #8aa8e0; --scripture-raw-accent-ink: #0b0d11;
  } }
}

/* ---- base: apply the aesthetic to the document shell --------------------- */
@layer scripture.base {
  :root { color-scheme: light dark; }
  html, body {
    margin: 0;
    min-height: 100vh;
    background: var(--scripture-bg, #faf9f7);
    color: var(--scripture-ink, #1a1815);
    font-family: var(--scripture-font-ui, system-ui, sans-serif);
    font-size: var(--brocade-font-size-base, 1rem);
    line-height: var(--brocade-line-height-normal, 1.5);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }
  * { box-sizing: border-box; }
}

/* ---- theme @byre/camber components -----------------------------------------
   camber components read --camber-* LIVE via var() inside their shadow DOM
   (confirmed with camber). Inherited custom properties cross the shadow boundary
   and re-resolve on any change — this is NOT subject to the ::part()-rule
   re-resolution limitation (that only bites ::part rules authored OUTSIDE the
   component). So we drive camber's palette from OUR semantic tokens: camber
   buttons/selects now flip on mode AND on palette / user-custom, with zero JS —
   no ::part hex, no re-creation on theme change.
   (Durable path, tracked with camber: camber consuming --brocade-color-* itself.) */
:root {
  --camber-color-background:         var(--scripture-card-bg);
  --camber-color-background-muted:   var(--scripture-faint);
  --camber-color-surface:            var(--scripture-card-bg);
  --camber-color-surface-hover:      var(--scripture-faint);
  --camber-color-surface-active:     var(--scripture-line);
  --camber-color-surface-raised:     var(--scripture-card-bg);
  --camber-color-foreground:         var(--scripture-ink);
  --camber-color-foreground-muted:   var(--scripture-muted);
  --camber-color-foreground-dim:     var(--scripture-muted);
  --camber-color-primary:            var(--scripture-accent);
  --camber-color-primary-hover:      var(--scripture-accent);
  --camber-color-primary-active:     var(--scripture-accent);
  --camber-color-primary-foreground: var(--scripture-raw-accent-ink);
  --camber-color-border:             var(--scripture-line);
  --camber-color-border-hover:       var(--scripture-muted);
  --camber-color-border-focus:       var(--scripture-accent);
  --camber-color-focus:              var(--scripture-accent);
}
