/* ============================================================================
   SLEUKRITH  ·  សាស្ត្រាស្លឹករឹត
   Khmer typography system v1.0

   Design source: the palm-leaf manuscript itself — incised lines darkened
   with lampblack on a dried leaf that is olive-grey, not cream. Text was cut
   in continuous rows with no word spacing, which is exactly the problem this
   stylesheet exists to solve. Rubric red and brass are the only accents,
   taken from lacquered manuscript edges.

   Values marked [S] are overridable from admin Settings and are injected as
   custom properties on :root at render time.
   ========================================================================== */

/* ── FONTS ─────────────────────────────────────────────────────────────────
   Face declarations live in fonts-selfhost.css, loaded only when the
   Typography setting `type.font_source` is set to "selfhost". The default
   is "google", so a fresh install renders correctly with no font files
   uploaded. Switch to selfhost once the WOFF2 files are in assets/fonts/ —
   it is faster on Cambodian mobile networks, where fonts.gstatic.com
   resolves slowly and Khmer files are large.

   Noto Serif Khmer is the recommendation for article text: the only widely
   available Khmer serif with correctly positioned coeng across weights, with
   a variable axis so bold costs no extra download. Kantumruy Pro handles the
   interface. Moul appears exactly once, in the wordmark — at body size it is
   unreadable, and using it twice cheapens it.
   ------------------------------------------------------------------------ */

/* ── TOKENS ─────────────────────────────────────────────────────────────── */

:root {
  /* ── palette · default preset "sleukrith" (lampblack on dried leaf) ──────
     Three presets ship with the platform, chosen in Settings → Appearance.
     Each defines the same six tokens, so nothing downstream needs to know
     which one is active. Individual colour pickers apply only when the
     preset is set to "custom". */
  --ink:        #191712;   /* soot, never pure black                        */
  --ink-soft:   #4A453B;
  --ink-faint:  #857E70;
  --leaf:       #F7F5EE;   /* page — warm-neutral, faintly green            */
  --leaf-sunk:  #EFEBE0;   /* recessed panels                               */
  --rule:       #D8D3C2;   /* hairline: the ruled guide line of a leaf      */
  --rubric:     #8C2318;   /* manuscript red — links, emphasis              */
  --brass:      #A8842C;   /* paid marker only                              */

  /* type families */
  --f-km-body:  'Noto Serif Khmer', 'Khmer OS Battambang', serif;
  --f-km-ui:    'Kantumruy Pro', 'Noto Sans Khmer', sans-serif;
  --f-km-disp:  'Moul', 'Noto Serif Khmer', serif;
  /* The Latin stacks carry a Khmer fallback, deliberately.

     A browser chooses a font per glyph, not per element. Inter has no Khmer
     glyphs, so with no Khmer family behind it every Khmer word inside a
     Latin-styled element — tabs, nav, buttons, meta lines, much of the
     interface — fell through to whatever the operating system happened to
     have. On Windows that is a visibly different letterform from the rest of
     the page, which is what made the dashboard tabs look wrong.

     Latin still renders in Inter; only the characters Inter cannot draw fall
     through to Kantumruy.

     system-ui and -apple-system were removed from this stack rather than
     merely reordered. They are not ordinary family names — engines resolve
     them against the platform's own font, and on a system whose UI font
     happens to carry Khmer that resolution can win before the list reaches
     Kantumruy. Since Inter and Kantumruy are both loaded, neither keyword was
     ever doing useful work here; the plain `sans-serif` at the end is the
     honest last resort. */
  --f-la-body:  'Source Serif 4', Georgia, 'Noto Serif Khmer', 'Khmer OS Battambang', serif;
  --f-la-ui:    'Inter', 'Kantumruy Pro', 'Noto Sans Khmer', sans-serif;

  /* metrics
     Khmer sits optically smaller than Latin at the same px, and its vowel
     signs stack above the line while coeng stack below. Those two facts
     drive the two numbers below — they are the whole system. */
  --size-body:    18px;
  --km-scale:     1.10;
  --lh-latin:     1.65;
  --lh-khmer:     2.00;   /* below ~1.85 the subscripts collide             */
  --measure-km:   34em;
  --measure-la:   38em;

  --space:        1.45em;
  --radius:       2px;
}

/* ── PRESET · slate ─────────────────────────────────────────────────────────
   Closest to the modern publishing platforms: near-white page, cool grey
   ink, a single blue accent. Quieter than the manuscript palette and the
   safer choice if the audience skews younger or more corporate. */
:root[data-preset="slate"] {
  --ink:       #14161A;
  --ink-soft:  #4B525C;
  --ink-faint: #858D99;
  --leaf:      #FFFFFF;
  --leaf-sunk: #F3F5F7;
  --rule:      #E3E7EB;
  --rubric:    #1E6FD9;
  --brass:     #0E8F6F;
  --radius:    6px;
}

/* ── PRESET · ink ───────────────────────────────────────────────────────────
   High-contrast editorial. Pure black on bone, one vermilion accent.
   Strongest for long-form reading and for a masthead that wants authority. */
:root[data-preset="ink"] {
  --ink:       #0B0B0B;
  --ink-soft:  #3D3D3D;
  --ink-faint: #767676;
  --leaf:      #FBFAF7;
  --leaf-sunk: #F0EEE9;
  --rule:      #DCD9D2;
  --rubric:    #C2410C;
  --brass:     #8A6D1F;
  --radius:    0px;
}

/* ── DARK ───────────────────────────────────────────────────────────────────
   data-theme is written server-side from a cookie so there is no flash of
   the wrong theme on load. "auto" follows the device; light and dark are
   explicit overrides chosen by the reader. */

@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] {
    --ink:       #EDEAE0;
    --ink-soft:  #B3ADA0;
    --ink-faint: #7E786C;
    --leaf:      #14130F;
    --leaf-sunk: #1D1B16;
    --rule:      #33302A;
    --rubric:    #D4695B;
    --brass:     #C9A448;
    color-scheme: dark;
  }
  :root[data-theme="auto"][data-preset="slate"] {
    --ink: #E6E9ED; --ink-soft: #A8B0BA; --ink-faint: #737C88;
    --leaf: #0F1216; --leaf-sunk: #171B21; --rule: #262C34;
    --rubric: #6AA6F5; --brass: #34C79E;
  }
  :root[data-theme="auto"][data-preset="ink"] {
    --ink: #F2F0EC; --ink-soft: #B0ACA5; --ink-faint: #7A7770;
    --leaf: #0C0C0B; --leaf-sunk: #161514; --rule: #2C2A27;
    --rubric: #F97316; --brass: #D3AC4E;
  }
}

:root[data-theme="dark"] {
  --ink:       #EDEAE0;
  --ink-soft:  #B3ADA0;
  --ink-faint: #7E786C;
  --leaf:      #14130F;
  --leaf-sunk: #1D1B16;
  --rule:      #33302A;
  --rubric:    #D4695B;
  --brass:     #C9A448;
  color-scheme: dark;
}
:root[data-theme="dark"][data-preset="slate"] {
  --ink: #E6E9ED; --ink-soft: #A8B0BA; --ink-faint: #737C88;
  --leaf: #0F1216; --leaf-sunk: #171B21; --rule: #262C34;
  --rubric: #6AA6F5; --brass: #34C79E;
}
:root[data-theme="dark"][data-preset="ink"] {
  --ink: #F2F0EC; --ink-soft: #B0ACA5; --ink-faint: #7A7770;
  --leaf: #0C0C0B; --leaf-sunk: #161514; --rule: #2C2A27;
  --rubric: #F97316; --brass: #D3AC4E;
}

:root[data-theme="light"] { color-scheme: light; }

/* Images and cover art are too bright against a dark page. */
:root[data-theme="dark"] img,
:root[data-theme="auto"] img { filter: brightness(0.92) contrast(1.02); }
@media (prefers-color-scheme: light) {
  :root[data-theme="auto"] img { filter: none; }
}

/* ── BASE ──────────────────────────────────────────────────────────────── */

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

body {
  background: var(--leaf);
  color: var(--ink);
  font-family: var(--f-la-ui), var(--f-km-ui);
  font-size: var(--size-body);
  line-height: var(--lh-latin);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Language switching is done with the lang attribute, not a class.
   Set lang="km" on <html> for the interface and on the article element
   for content — they are independent, which is the whole point of a
   Khmer-content / bilingual-interface platform. */

:lang(km) {
  font-family: var(--f-km-ui), var(--f-la-ui);
  line-height: var(--lh-khmer);
}

/* ── THE FOUR KHMER RULES ──────────────────────────────────────────────────
   These four exist because breaking any one of them is what makes most
   Khmer websites unpleasant to read. They are not stylistic preferences.
   ------------------------------------------------------------------------ */

:lang(km) {
  /* 1 — never track Khmer. Letter-spacing detaches vowel signs from their
         base consonant and the word visually falls apart. */
  letter-spacing: 0 !important;

  /* 2 — never justify. Khmer has no inter-word spaces, so the browser
         stretches inside clusters and rivers open up everywhere. */
  text-align: start;

  /* 3 — break only at ZWSP (U+200B). `word-break: break-all` will split a
         consonant from its subscript and render literal garbage. */
  word-break: normal;
  overflow-wrap: normal;
  line-break: strict;

  /* 4 — no faux styling. Khmer has no true italic, and synthesised bold
         thickens the coeng into a blob. Load real weights instead. */
  font-synthesis: none;
  font-style: normal;
}

:lang(km) em,
:lang(km) i {
  font-style: normal;
  color: var(--rubric);        /* emphasis by rubrication, as in manuscripts */
}

:lang(km) strong,
:lang(km) b { font-weight: 700; }

/* ── READING SURFACE ───────────────────────────────────────────────────── */

.article {
  max-width: var(--measure-la);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

.article:lang(km) {
  max-width: var(--measure-km);
  font-family: var(--f-km-body), var(--f-la-body);
  font-size: calc(var(--size-body) * var(--km-scale));
  line-height: var(--lh-khmer);
}

.article p {
  margin: 0 0 var(--space);
  hanging-punctuation: first;
}

.article:lang(km) p { margin-bottom: calc(var(--space) * 1.05); }

/* Khmer headings need tighter leading than body — the same 2.0 that keeps
   body text legible makes a two-line headline look unbound. */
.article h2,
.article h3 {
  font-family: var(--f-la-body);
  font-weight: 600;
  margin: 2.2em 0 0.7em;
  line-height: 1.3;
}
.article h2:lang(km),
.article h3:lang(km) {
  font-family: var(--f-km-body);
  line-height: 1.55;
  font-weight: 700;
}
.article h2 { font-size: 1.45em; }
.article h3 { font-size: 1.18em; }

.article a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--rubric);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
}
.article a:hover { color: var(--rubric); }

/* Khmer underlines collide with subscript consonants. Offset further and
   thin the line, or the descenders sit on top of it. */
.article:lang(km) a {
  text-underline-offset: 0.42em;
  text-decoration-thickness: 1px;
}

.article blockquote {
  margin: 2em 0;
  padding-inline-start: 1.4em;
  border-inline-start: 2px solid var(--rubric);
  color: var(--ink-soft);
}

.article img,
.article figure { margin: 2.4em 0; max-width: 100%; height: auto; }

.article figcaption {
  font-family: var(--f-la-ui);
  font-size: 0.82em;
  line-height: 1.5;
  color: var(--ink-faint);
  margin-top: 0.7em;
}
.article figcaption:lang(km) {
  font-family: var(--f-km-ui);
  line-height: 1.8;
}

/* ── THE RULED LINE ────────────────────────────────────────────────────────
   Signature element. A sastra leaf is scored with a guide line and pierced
   with two binding holes. The section divider reproduces that: a hairline
   rule interrupted by two small circles. It is the only ornament on the
   page, and it carries meaning rather than decoration.
   ------------------------------------------------------------------------ */

.leaf-rule {
  border: 0;
  height: 1px;
  background: var(--rule);
  margin: 3.4em auto;
  max-width: var(--measure-km);
  position: relative;
  overflow: visible;
}
.leaf-rule::before,
.leaf-rule::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--leaf);
  border: 1px solid var(--rule);
  transform: translateY(-50%);
}
.leaf-rule::before { left: 32%; }
.leaf-rule::after  { left: 68%; }

/* ── WORDMARK ──────────────────────────────────────────────────────────── */

.wordmark {
  font-family: var(--f-km-disp);
  font-size: clamp(1.5rem, 4vw, 2.1rem);
  line-height: 1.4;
  letter-spacing: 0;
  color: var(--ink);
}

/* ── UTILITY TYPE ──────────────────────────────────────────────────────── */

.meta {
  font-family: var(--f-la-ui);
  font-size: 0.8rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.meta:lang(km) {
  font-family: var(--f-km-ui);
  font-size: 0.86rem;
  letter-spacing: 0;          /* rule 1 applies to labels too */
  text-transform: none;       /* Khmer has no case             */
  line-height: 1.7;
}

.paid-mark {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--f-la-ui);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brass);
  border: 1px solid currentColor;
  border-radius: 2px;
  padding: 0.15em 0.5em;
}

/* Khmer numerals for dates — ០១២៣៤៥៦៧៨៩ — set from Settings. */
.khmer-numerals { font-feature-settings: 'lnum' 0; }

/* ── EDITOR ────────────────────────────────────────────────────────────────
   The composing surface must match the published surface exactly, or the
   writer is editing a document they have never seen.
   ------------------------------------------------------------------------ */

.editor[contenteditable] {
  font-family: var(--f-km-body), var(--f-la-body);
  font-size: calc(var(--size-body) * var(--km-scale));
  line-height: var(--lh-khmer);
  max-width: var(--measure-km);
  margin-inline: auto;
  outline: none;
  caret-color: var(--rubric);
}
.editor[contenteditable]:empty::before {
  content: attr(data-placeholder);
  color: var(--ink-faint);
  pointer-events: none;
}

/* Toggle in the editor toolbar: reveals where the ZWSP word breaks fall,
   so the writer can fix bad segmentation before publishing. */
.show-breaks .editor { --break-dot: var(--ink-faint); }
.show-breaks .editor::highlight(zwsp) { background: var(--leaf-sunk); }

/* ── PAYWALL ───────────────────────────────────────────────────────────── */

.paywall-fade {
  position: relative;
  max-height: 22em;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
          mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
}

/* ── RESPONSIVE ────────────────────────────────────────────────────────────
   Khmer at 16px on a phone is genuinely hard to read; hold the size and
   give up the margins instead. */

@media (max-width: 640px) {
  :root { --size-body: 17px; --km-scale: 1.14; --lh-khmer: 1.95; }
  .article { padding-inline: 1.15rem; }
}

@media print {
  :root { --leaf: #fff; --ink: #000; }
  .leaf-rule, nav, .paywall-fade { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ── FOCUS ─────────────────────────────────────────────────────────────── */

:focus-visible {
  outline: 2px solid var(--rubric);
  outline-offset: 3px;
  border-radius: 2px;
}
